Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/arch/x86/shutdown.c
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 * arch/x86/shutdown.c
3
 *
4
 * x86-specific shutdown handling.
5
 */
6
7
#include <xen/init.h>
8
#include <xen/lib.h>
9
#include <xen/sched.h>
10
#include <xen/smp.h>
11
#include <xen/delay.h>
12
#include <xen/dmi.h>
13
#include <xen/irq.h>
14
#include <xen/watchdog.h>
15
#include <xen/console.h>
16
#include <xen/shutdown.h>
17
#include <xen/acpi.h>
18
#include <xen/efi.h>
19
#include <asm/msr.h>
20
#include <asm/regs.h>
21
#include <asm/mc146818rtc.h>
22
#include <asm/system.h>
23
#include <asm/io.h>
24
#include <asm/processor.h>
25
#include <asm/mpspec.h>
26
#include <asm/tboot.h>
27
#include <asm/apic.h>
28
29
enum reboot_type {
30
        BOOT_INVALID,
31
        BOOT_TRIPLE = 't',
32
        BOOT_KBD = 'k',
33
        BOOT_ACPI = 'a',
34
        BOOT_CF9 = 'p',
35
        BOOT_CF9_PWR = 'P',
36
        BOOT_EFI = 'e',
37
};
38
39
static int reboot_mode;
40
41
/*
42
 * reboot=t[riple] | k[bd] | a[cpi] | p[ci] | n[o] | [e]fi [, [w]arm | [c]old]
43
 * warm   Don't set the cold reboot flag
44
 * cold   Set the cold reboot flag
45
 * no     Suppress automatic reboot after panics or crashes
46
 * triple Force a triple fault (init)
47
 * kbd    Use the keyboard controller. cold reset (default)
48
 * acpi   Use the RESET_REG in the FADT
49
 * pci    Use the so-called "PCI reset register", CF9
50
 * Power  Like 'pci' but for a full power-cyle reset
51
 * efi    Use the EFI reboot (if running under EFI)
52
 */
53
static enum reboot_type reboot_type = BOOT_INVALID;
54
55
static int __init set_reboot_type(const char *str)
56
0
{
57
0
    int rc = 0;
58
0
59
0
    for ( ; ; )
60
0
    {
61
0
        switch ( *str )
62
0
        {
63
0
        case 'n': /* no reboot */
64
0
            opt_noreboot = 1;
65
0
            break;
66
0
        case 'w': /* "warm" reboot (no memory testing etc) */
67
0
            reboot_mode = 0x1234;
68
0
            break;
69
0
        case 'c': /* "cold" reboot (with memory testing etc) */
70
0
            reboot_mode = 0x0;
71
0
            break;
72
0
        case 'a':
73
0
        case 'e':
74
0
        case 'k':
75
0
        case 'P':
76
0
        case 'p':
77
0
        case 't':
78
0
            reboot_type = *str;
79
0
            break;
80
0
        default:
81
0
            rc = -EINVAL;
82
0
            break;
83
0
        }
84
0
        if ( (str = strchr(str, ',')) == NULL )
85
0
            break;
86
0
        str++;
87
0
    }
88
0
89
0
    if ( reboot_type == BOOT_EFI && !efi_enabled(EFI_RS) )
90
0
    {
91
0
        printk("EFI reboot selected, but no EFI runtime services available.\n"
92
0
               "Falling back to default reboot type.\n");
93
0
        reboot_type = BOOT_INVALID;
94
0
    }
95
0
96
0
    return rc;
97
0
}
98
custom_param("reboot", set_reboot_type);
99
100
static inline void kb_wait(void)
101
0
{
102
0
    int i;
103
0
104
0
    for ( i = 0; i < 0x10000; i++ )
105
0
        if ( (inb_p(0x64) & 0x02) == 0 )
106
0
            break;
107
0
}
108
109
static void noreturn __machine_halt(void *unused)
110
0
{
111
0
    local_irq_disable();
112
0
    for ( ; ; )
113
0
        halt();
114
0
}
115
116
void machine_halt(void)
117
0
{
118
0
    watchdog_disable();
119
0
    console_start_sync();
120
0
121
0
    if ( system_state >= SYS_STATE_smp_boot )
122
0
    {
123
0
        local_irq_enable();
124
0
        smp_call_function(__machine_halt, NULL, 0);
125
0
    }
126
0
127
0
    __machine_halt(NULL);
128
0
}
129
130
static void default_reboot_type(void)
131
1
{
132
1
    if ( reboot_type == BOOT_INVALID )
133
1
        reboot_type = efi_enabled(EFI_RS) ? BOOT_EFI
134
1
                                  : acpi_disabled ? BOOT_KBD
135
1
                                                  : BOOT_ACPI;
136
1
}
137
138
static int __init override_reboot(struct dmi_system_id *d)
139
0
{
140
0
    enum reboot_type type = (long)d->driver_data;
141
0
142
0
    if ( type == BOOT_ACPI && acpi_disabled )
143
0
        type = BOOT_KBD;
144
0
145
0
    if ( reboot_type != type )
146
0
    {
147
0
        static const char *__initdata msg[] =
148
0
        {
149
0
            [BOOT_KBD]  = "keyboard controller",
150
0
            [BOOT_ACPI] = "ACPI",
151
0
            [BOOT_CF9]  = "PCI",
152
0
        };
153
0
154
0
        reboot_type = type;
155
0
        ASSERT(type >= 0 && type < ARRAY_SIZE(msg) && msg[type]);
156
0
        printk("%s series board detected. Selecting %s reboot method.\n",
157
0
               d->ident, msg[type]);
158
0
    }
159
0
    return 0;
160
0
}
161
162
static struct dmi_system_id __initdata reboot_dmi_table[] = {
163
    {    /* Handle problems with rebooting on Dell E520's */
164
        .callback = override_reboot,
165
        .driver_data = (void *)(long)BOOT_KBD,
166
        .ident = "Dell E520",
167
        .matches = {
168
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
169
            DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM061"),
170
        },
171
    },
172
    {    /* Handle problems with rebooting on Dell 1300's */
173
        .callback = override_reboot,
174
        .driver_data = (void *)(long)BOOT_KBD,
175
        .ident = "Dell PowerEdge 1300",
176
        .matches = {
177
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
178
            DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
179
        },
180
    },
181
    {    /* Handle problems with rebooting on Dell 300's */
182
        .callback = override_reboot,
183
        .driver_data = (void *)(long)BOOT_KBD,
184
        .ident = "Dell PowerEdge 300",
185
        .matches = {
186
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
187
            DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
188
        },
189
    },
190
    {    /* Handle problems with rebooting on Dell Optiplex 745's SFF */
191
        .callback = override_reboot,
192
        .driver_data = (void *)(long)BOOT_KBD,
193
        .ident = "Dell OptiPlex 745",
194
        .matches = {
195
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
196
            DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
197
        },
198
    },
199
    {    /* Handle problems with rebooting on Dell Optiplex 745's DFF */
200
        .callback = override_reboot,
201
        .driver_data = (void *)(long)BOOT_KBD,
202
        .ident = "Dell OptiPlex 745",
203
        .matches = {
204
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
205
            DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
206
            DMI_MATCH(DMI_BOARD_NAME, "0MM599"),
207
        },
208
    },
209
    {    /* Handle problems with rebooting on Dell Optiplex 745 with 0KW626 */
210
        .callback = override_reboot,
211
        .driver_data = (void *)(long)BOOT_KBD,
212
        .ident = "Dell OptiPlex 745",
213
        .matches = {
214
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
215
            DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
216
            DMI_MATCH(DMI_BOARD_NAME, "0KW626"),
217
        },
218
    },
219
    {    /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */
220
        .callback = override_reboot,
221
        .driver_data = (void *)(long)BOOT_KBD,
222
        .ident = "Dell OptiPlex 330",
223
        .matches = {
224
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
225
            DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 330"),
226
            DMI_MATCH(DMI_BOARD_NAME, "0KP561"),
227
        },
228
    },
229
    {    /* Handle problems with rebooting on Dell Optiplex 360 with 0T656F */
230
        .callback = override_reboot,
231
        .driver_data = (void *)(long)BOOT_KBD,
232
        .ident = "Dell OptiPlex 360",
233
        .matches = {
234
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
235
            DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 360"),
236
            DMI_MATCH(DMI_BOARD_NAME, "0T656F"),
237
        },
238
    },
239
    {    /* Handle problems with rebooting on Dell OptiPlex 760 with 0G919G */
240
        .callback = override_reboot,
241
        .driver_data = (void *)(long)BOOT_KBD,
242
        .ident = "Dell OptiPlex 760",
243
        .matches = {
244
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
245
            DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 760"),
246
            DMI_MATCH(DMI_BOARD_NAME, "0G919G"),
247
        },
248
    },
249
    {    /* Handle problems with rebooting on Dell 2400's */
250
        .callback = override_reboot,
251
        .driver_data = (void *)(long)BOOT_KBD,
252
        .ident = "Dell PowerEdge 2400",
253
        .matches = {
254
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
255
            DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
256
        },
257
    },
258
    {    /* Handle problems with rebooting on Dell T5400's */
259
        .callback = override_reboot,
260
        .driver_data = (void *)(long)BOOT_KBD,
261
        .ident = "Dell Precision T5400",
262
        .matches = {
263
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
264
            DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"),
265
        },
266
    },
267
    {    /* Handle problems with rebooting on Dell T7400's */
268
        .callback = override_reboot,
269
        .driver_data = (void *)(long)BOOT_KBD,
270
        .ident = "Dell Precision T7400",
271
        .matches = {
272
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
273
            DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T7400"),
274
        },
275
    },
276
    {    /* Handle problems with rebooting on HP laptops */
277
        .callback = override_reboot,
278
        .driver_data = (void *)(long)BOOT_KBD,
279
        .ident = "HP Compaq Laptop",
280
        .matches = {
281
            DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
282
            DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"),
283
        },
284
    },
285
    {    /* Handle problems with rebooting on Dell XPS710 */
286
        .callback = override_reboot,
287
        .driver_data = (void *)(long)BOOT_KBD,
288
        .ident = "Dell XPS710",
289
        .matches = {
290
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
291
            DMI_MATCH(DMI_PRODUCT_NAME, "Dell XPS710"),
292
        },
293
    },
294
    {    /* Handle problems with rebooting on Dell DXP061 */
295
        .callback = override_reboot,
296
        .driver_data = (void *)(long)BOOT_KBD,
297
        .ident = "Dell DXP061",
298
        .matches = {
299
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
300
            DMI_MATCH(DMI_PRODUCT_NAME, "Dell DXP061"),
301
        },
302
    },
303
    {    /* Handle problems with rebooting on Sony VGN-Z540N */
304
        .callback = override_reboot,
305
        .driver_data = (void *)(long)BOOT_KBD,
306
        .ident = "Sony VGN-Z540N",
307
        .matches = {
308
            DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
309
            DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"),
310
        },
311
    },
312
    {    /* Handle problems with rebooting on ASUS P4S800 */
313
        .callback = override_reboot,
314
        .driver_data = (void *)(long)BOOT_KBD,
315
        .ident = "ASUS P4S800",
316
        .matches = {
317
            DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
318
            DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
319
        },
320
    },
321
    {    /* Handle reboot issue on Acer Aspire one */
322
        .callback = override_reboot,
323
        .driver_data = (void *)(long)BOOT_KBD,
324
        .ident = "Acer Aspire One A110",
325
        .matches = {
326
            DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
327
            DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"),
328
        },
329
    },
330
    {    /* Handle problems with rebooting on Apple MacBook5 */
331
        .callback = override_reboot,
332
        .driver_data = (void *)(long)BOOT_CF9,
333
        .ident = "Apple MacBook5",
334
        .matches = {
335
            DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
336
            DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5"),
337
        },
338
    },
339
    {    /* Handle problems with rebooting on Apple MacBookPro5 */
340
        .callback = override_reboot,
341
        .driver_data = (void *)(long)BOOT_CF9,
342
        .ident = "Apple MacBookPro5",
343
        .matches = {
344
            DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
345
            DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5"),
346
        },
347
    },
348
    {    /* Handle problems with rebooting on Apple Macmini3,1 */
349
        .callback = override_reboot,
350
        .driver_data = (void *)(long)BOOT_CF9,
351
        .ident = "Apple Macmini3,1",
352
        .matches = {
353
            DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
354
            DMI_MATCH(DMI_PRODUCT_NAME, "Macmini3,1"),
355
        },
356
    },
357
    {    /* Handle problems with rebooting on the iMac9,1. */
358
        .callback = override_reboot,
359
        .driver_data = (void *)(long)BOOT_CF9,
360
        .ident = "Apple iMac9,1",
361
        .matches = {
362
            DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
363
            DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"),
364
        },
365
    },
366
    {    /* Handle problems with rebooting on the Latitude E6320. */
367
        .callback = override_reboot,
368
        .driver_data = (void *)(long)BOOT_CF9,
369
        .ident = "Dell Latitude E6320",
370
        .matches = {
371
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
372
            DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6320"),
373
        },
374
    },
375
    {    /* Handle problems with rebooting on the Latitude E5420. */
376
        .callback = override_reboot,
377
        .driver_data = (void *)(long)BOOT_CF9,
378
        .ident = "Dell Latitude E5420",
379
        .matches = {
380
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
381
            DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5420"),
382
        },
383
    },
384
    {       /* Handle problems with rebooting on the Latitude E6220. */
385
        .callback = override_reboot,
386
        .driver_data = (void *)(long)BOOT_CF9,
387
        .ident = "Dell Latitude E6220",
388
        .matches = {
389
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
390
            DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6220"),
391
        },
392
    },
393
    {    /* Handle problems with rebooting on the Latitude E6420. */
394
        .callback = override_reboot,
395
        .driver_data = (void *)(long)BOOT_CF9,
396
        .ident = "Dell Latitude E6420",
397
        .matches = {
398
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
399
            DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6420"),
400
        },
401
    },
402
    {    /* Handle problems with rebooting on the OptiPlex 990. */
403
        .callback = override_reboot,
404
        .driver_data = (void *)(long)BOOT_CF9,
405
        .ident = "Dell OptiPlex 990",
406
        .matches = {
407
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
408
            DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"),
409
        },
410
    },
411
    {    /* Handle problems with rebooting on the Precision M6600. */
412
        .callback = override_reboot,
413
        .driver_data = (void *)(long)BOOT_CF9,
414
        .ident = "Dell OptiPlex 990",
415
        .matches = {
416
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
417
            DMI_MATCH(DMI_PRODUCT_NAME, "Precision M6600"),
418
        },
419
    },
420
    {    /* Handle problems with rebooting on the Latitude E6520. */
421
        .callback = override_reboot,
422
        .driver_data = (void *)(long)BOOT_CF9,
423
        .ident = "Dell Latitude E6520",
424
        .matches = {
425
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
426
            DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6520"),
427
        },
428
    },
429
    {       /* Handle problems with rebooting on the OptiPlex 790. */
430
        .callback = override_reboot,
431
        .driver_data = (void *)(long)BOOT_CF9,
432
        .ident = "Dell OptiPlex 790",
433
        .matches = {
434
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
435
            DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 790"),
436
        },
437
    },
438
    {    /* Handle problems with rebooting on the OptiPlex 990. */
439
        .callback = override_reboot,
440
        .driver_data = (void *)(long)BOOT_CF9,
441
        .ident = "Dell OptiPlex 990",
442
        .matches = {
443
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
444
            DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"),
445
        },
446
    },
447
    {    /* Handle problems with rebooting on the OptiPlex 390. */
448
        .callback = override_reboot,
449
        .driver_data = (void *)(long)BOOT_CF9,
450
        .ident = "Dell OptiPlex 390",
451
        .matches = {
452
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
453
            DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 390"),
454
        },
455
    },
456
    {    /* Handle problems with rebooting on Dell OptiPlex 9020. */
457
        .callback = override_reboot,
458
        .driver_data = (void *)(long)BOOT_ACPI,
459
        .ident = "Dell OptiPlex 9020",
460
        .matches = {
461
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
462
            DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 9020"),
463
        },
464
    },
465
    {    /* Handle problems with rebooting on the Latitude E6320. */
466
        .callback = override_reboot,
467
        .driver_data = (void *)(long)BOOT_CF9,
468
        .ident = "Dell Latitude E6320",
469
        .matches = {
470
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
471
            DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6320"),
472
        },
473
    },
474
    {    /* Handle problems with rebooting on the Latitude E6420. */
475
        .callback = override_reboot,
476
        .driver_data = (void *)(long)BOOT_CF9,
477
        .ident = "Dell Latitude E6420",
478
        .matches = {
479
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
480
            DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6420"),
481
        },
482
    },
483
    {    /* Handle problems with rebooting on the Latitude E6520. */
484
        .callback = override_reboot,
485
        .driver_data = (void *)(long)BOOT_CF9,
486
        .ident = "Dell Latitude E6520",
487
        .matches = {
488
            DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
489
            DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6520"),
490
        },
491
    },
492
    { }
493
};
494
495
static int __init reboot_init(void)
496
1
{
497
1
    /*
498
1
     * Only do the DMI check if reboot_type hasn't been overridden
499
1
     * on the command line
500
1
     */
501
1
    if ( reboot_type != BOOT_INVALID )
502
0
        return 0;
503
1
504
1
    default_reboot_type();
505
1
    dmi_check_system(reboot_dmi_table);
506
1
    return 0;
507
1
}
508
__initcall(reboot_init);
509
510
static void noreturn __machine_restart(void *pdelay)
511
0
{
512
0
    machine_restart(*(unsigned int *)pdelay);
513
0
}
514
515
void machine_restart(unsigned int delay_millisecs)
516
0
{
517
0
    unsigned int i, attempt;
518
0
    enum reboot_type orig_reboot_type;
519
0
    const struct desc_ptr no_idt = { 0 };
520
0
521
0
    watchdog_disable();
522
0
    console_start_sync();
523
0
    spin_debug_disable();
524
0
525
0
    /*
526
0
     * We may be called from an interrupt context, and various functions we
527
0
     * may need to call (alloc_domheap_pages, map_domain_page, ...) assert that
528
0
     * they are not called from interrupt context. This hack keeps them happy.
529
0
     */
530
0
    local_irq_count(0) = 0;
531
0
532
0
    if ( system_state >= SYS_STATE_smp_boot )
533
0
    {
534
0
        local_irq_enable();
535
0
536
0
        /* Ensure we are the boot CPU. */
537
0
        if ( get_apic_id() != boot_cpu_physical_apicid )
538
0
        {
539
0
            /* Send IPI to the boot CPU (logical cpu 0). */
540
0
            on_selected_cpus(cpumask_of(0), __machine_restart,
541
0
                             &delay_millisecs, 0);
542
0
            for ( ; ; )
543
0
                halt();
544
0
        }
545
0
546
0
        smp_send_stop();
547
0
    }
548
0
549
0
    mdelay(delay_millisecs);
550
0
551
0
    if ( tboot_in_measured_env() )
552
0
    {
553
0
        acpi_dmar_reinstate();
554
0
        tboot_shutdown(TB_SHUTDOWN_REBOOT);
555
0
    }
556
0
557
0
    /* Just in case reboot_init() didn't run yet. */
558
0
    default_reboot_type();
559
0
    orig_reboot_type = reboot_type;
560
0
561
0
    /* Rebooting needs to touch the page at absolute address 0. */
562
0
    if ( reboot_type != BOOT_EFI )
563
0
        *((unsigned short *)__va(0x472)) = reboot_mode;
564
0
565
0
    for ( attempt = 0; ; attempt++ )
566
0
    {
567
0
        switch ( reboot_type )
568
0
        {
569
0
        case BOOT_INVALID:
570
0
            ASSERT_UNREACHABLE();
571
0
            /* fall through */
572
0
        case BOOT_KBD:
573
0
            /* Pulse the keyboard reset line. */
574
0
            for ( i = 0; i < 100; i++ )
575
0
            {
576
0
                kb_wait();
577
0
                udelay(50);
578
0
                outb(0xfe,0x64); /* pulse reset low */
579
0
                udelay(50);
580
0
            }
581
0
            /*
582
0
             * If this platform supports ACPI reset, we follow a Windows-style
583
0
             * reboot attempt sequence:
584
0
             *   ACPI -> KBD -> ACPI -> KBD
585
0
             * After this we revert to our usual sequence:
586
0
             *   KBD -> TRIPLE -> KBD -> TRIPLE -> KBD -> ...
587
0
             */
588
0
            reboot_type = (((attempt == 1) && (orig_reboot_type == BOOT_ACPI))
589
0
                           ? BOOT_ACPI : BOOT_TRIPLE);
590
0
            break;
591
0
        case BOOT_EFI:
592
0
            reboot_type = acpi_disabled ? BOOT_KBD : BOOT_ACPI;
593
0
            efi_reset_system(reboot_mode != 0);
594
0
            *((unsigned short *)__va(0x472)) = reboot_mode;
595
0
            break;
596
0
        case BOOT_TRIPLE:
597
0
            asm volatile ("lidt %0; int3" : : "m" (no_idt));
598
0
            reboot_type = BOOT_KBD;
599
0
            break;
600
0
        case BOOT_ACPI:
601
0
            acpi_reboot();
602
0
            reboot_type = BOOT_KBD;
603
0
            break;
604
0
        case BOOT_CF9:
605
0
        case BOOT_CF9_PWR:
606
0
            {
607
0
                u8 cf9 = inb(0xcf9) & ~0x0e;
608
0
609
0
                /* Request warm, hard, or power-cycle reset. */
610
0
                if ( reboot_type == BOOT_CF9_PWR )
611
0
                    cf9 |= 0x0a;
612
0
                else if ( reboot_mode == 0 )
613
0
                    cf9 |= 0x02;
614
0
                outb(cf9, 0xcf9);
615
0
                udelay(50);
616
0
                outb(cf9 | 0x04, 0xcf9); /* Actually do the reset. */
617
0
                udelay(50);
618
0
            }
619
0
            reboot_type = BOOT_ACPI;
620
0
            break;
621
0
        }
622
0
    }
623
0
}
624
625
/*
626
 * Local variables:
627
 * mode: C
628
 * c-file-style: "BSD"
629
 * c-basic-offset: 4
630
 * tab-width: 4
631
 * indent-tabs-mode: nil
632
 * End:
633
 */