x86: Properly parenthesize cmpxchg() macro arguments
[deliverable/linux.git] / arch / x86 / kernel / reboot.c
CommitLineData
1da177e4 1#include <linux/module.h>
cd6ed525 2#include <linux/reboot.h>
4d022e35
MB
3#include <linux/init.h>
4#include <linux/pm.h>
5#include <linux/efi.h>
6c6c51e4 6#include <linux/dmi.h>
d43c36dc 7#include <linux/sched.h>
69575d38 8#include <linux/tboot.h>
ca444564 9#include <linux/delay.h>
4d022e35
MB
10#include <acpi/reboot.h>
11#include <asm/io.h>
1da177e4 12#include <asm/apic.h>
4d37e7e3 13#include <asm/desc.h>
4d022e35 14#include <asm/hpet.h>
68db065c 15#include <asm/pgtable.h>
4412620f 16#include <asm/proto.h>
973efae2 17#include <asm/reboot_fixups.h>
07f3331c 18#include <asm/reboot.h>
82487711 19#include <asm/pci_x86.h>
d176720d 20#include <asm/virtext.h>
96b89dc6 21#include <asm/cpu.h>
c410b830 22#include <asm/nmi.h>
1da177e4 23
4d022e35 24#ifdef CONFIG_X86_32
4d022e35
MB
25# include <linux/ctype.h>
26# include <linux/mc146818rtc.h>
4d022e35 27#else
338bac52 28# include <asm/x86_init.h>
4d022e35
MB
29#endif
30
1da177e4
LT
31/*
32 * Power off function, if any
33 */
34void (*pm_power_off)(void);
129f6946 35EXPORT_SYMBOL(pm_power_off);
1da177e4 36
ebdd561a 37static const struct desc_ptr no_idt = {};
1da177e4 38static int reboot_mode;
660e34ce 39enum reboot_type reboot_type = BOOT_ACPI;
4d022e35 40int reboot_force;
1da177e4 41
4d022e35 42#if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
1da177e4 43static int reboot_cpu = -1;
1da177e4 44#endif
4d022e35 45
d176720d
EH
46/* This is set if we need to go through the 'emergency' path.
47 * When machine_emergency_restart() is called, we may be on
48 * an inconsistent state and won't be able to do a clean cleanup
49 */
50static int reboot_emergency;
51
14d7ca5c
PA
52/* This is set by the PCI code if either type 1 or type 2 PCI is detected */
53bool port_cf9_safe = false;
54
55/* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci]
4d022e35
MB
56 warm Don't set the cold reboot flag
57 cold Set the cold reboot flag
58 bios Reboot by jumping through the BIOS (only for X86_32)
59 smp Reboot by executing reset on BSP or other CPU (only for X86_32)
60 triple Force a triple fault (init)
61 kbd Use the keyboard controller. cold reset (default)
62 acpi Use the RESET_REG in the FADT
63 efi Use efi reset_system runtime service
14d7ca5c 64 pci Use the so-called "PCI reset register", CF9
4d022e35
MB
65 force Avoid anything that could hang.
66 */
1da177e4
LT
67static int __init reboot_setup(char *str)
68{
4d022e35 69 for (;;) {
1da177e4 70 switch (*str) {
4d022e35 71 case 'w':
1da177e4
LT
72 reboot_mode = 0x1234;
73 break;
4d022e35
MB
74
75 case 'c':
76 reboot_mode = 0;
1da177e4 77 break;
4d022e35
MB
78
79#ifdef CONFIG_X86_32
1da177e4 80#ifdef CONFIG_SMP
4d022e35 81 case 's':
6f673d83 82 if (isdigit(*(str+1))) {
1da177e4 83 reboot_cpu = (int) (*(str+1) - '0');
6f673d83 84 if (isdigit(*(str+2)))
1da177e4
LT
85 reboot_cpu = reboot_cpu*10 + (int)(*(str+2) - '0');
86 }
4d022e35
MB
87 /* we will leave sorting out the final value
88 when we are ready to reboot, since we might not
f6e9456c 89 have detected BSP APIC ID or smp_num_cpu */
1da177e4 90 break;
4d022e35
MB
91#endif /* CONFIG_SMP */
92
93 case 'b':
1da177e4 94#endif
4d022e35
MB
95 case 'a':
96 case 'k':
97 case 't':
98 case 'e':
14d7ca5c 99 case 'p':
4d022e35
MB
100 reboot_type = *str;
101 break;
102
103 case 'f':
104 reboot_force = 1;
105 break;
1da177e4 106 }
4d022e35
MB
107
108 str = strchr(str, ',');
109 if (str)
1da177e4
LT
110 str++;
111 else
112 break;
113 }
114 return 1;
115}
116
117__setup("reboot=", reboot_setup);
118
4d022e35
MB
119
120#ifdef CONFIG_X86_32
1da177e4
LT
121/*
122 * Reboot options and system auto-detection code provided by
123 * Dell Inc. so their systems "just work". :-)
124 */
125
126/*
1ef03890 127 * Some machines require the "reboot=b" or "reboot=k" commandline options,
4d022e35 128 * this quirk makes that automatic.
1da177e4 129 */
1855256c 130static int __init set_bios_reboot(const struct dmi_system_id *d)
1da177e4 131{
4d022e35
MB
132 if (reboot_type != BOOT_BIOS) {
133 reboot_type = BOOT_BIOS;
1da177e4
LT
134 printk(KERN_INFO "%s series board detected. Selecting BIOS-method for reboots.\n", d->ident);
135 }
136 return 0;
137}
138
1ef03890
PC
139static int __init set_kbd_reboot(const struct dmi_system_id *d)
140{
141 if (reboot_type != BOOT_KBD) {
142 reboot_type = BOOT_KBD;
143 printk(KERN_INFO "%s series board detected. Selecting KBD-method for reboot.\n", d->ident);
144 }
145 return 0;
146}
147
1da177e4 148static struct dmi_system_id __initdata reboot_dmi_table[] = {
b9e82af8
TG
149 { /* Handle problems with rebooting on Dell E520's */
150 .callback = set_bios_reboot,
151 .ident = "Dell E520",
152 .matches = {
153 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
154 DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM061"),
155 },
156 },
1da177e4 157 { /* Handle problems with rebooting on Dell 1300's */
dd2a1305 158 .callback = set_bios_reboot,
1da177e4
LT
159 .ident = "Dell PowerEdge 1300",
160 .matches = {
161 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
162 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
163 },
164 },
165 { /* Handle problems with rebooting on Dell 300's */
166 .callback = set_bios_reboot,
167 .ident = "Dell PowerEdge 300",
168 .matches = {
169 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
170 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
171 },
172 },
df2edcf3
JJ
173 { /* Handle problems with rebooting on Dell Optiplex 745's SFF*/
174 .callback = set_bios_reboot,
175 .ident = "Dell OptiPlex 745",
176 .matches = {
177 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
178 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
df2edcf3
JJ
179 },
180 },
fc115bf1
CK
181 { /* Handle problems with rebooting on Dell Optiplex 745's DFF*/
182 .callback = set_bios_reboot,
183 .ident = "Dell OptiPlex 745",
184 .matches = {
185 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
186 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
187 DMI_MATCH(DMI_BOARD_NAME, "0MM599"),
188 },
189 },
fc1c8925
HAA
190 { /* Handle problems with rebooting on Dell Optiplex 745 with 0KW626 */
191 .callback = set_bios_reboot,
192 .ident = "Dell OptiPlex 745",
193 .matches = {
194 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
195 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
196 DMI_MATCH(DMI_BOARD_NAME, "0KW626"),
197 },
198 },
093bac15
SC
199 { /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */
200 .callback = set_bios_reboot,
201 .ident = "Dell OptiPlex 330",
202 .matches = {
203 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
204 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 330"),
205 DMI_MATCH(DMI_BOARD_NAME, "0KP561"),
206 },
207 },
4a4aca64
JD
208 { /* Handle problems with rebooting on Dell Optiplex 360 with 0T656F */
209 .callback = set_bios_reboot,
210 .ident = "Dell OptiPlex 360",
211 .matches = {
212 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
213 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 360"),
214 DMI_MATCH(DMI_BOARD_NAME, "0T656F"),
215 },
216 },
35ea63d7
LO
217 { /* Handle problems with rebooting on Dell OptiPlex 760 with 0G919G*/
218 .callback = set_bios_reboot,
219 .ident = "Dell OptiPlex 760",
220 .matches = {
221 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
222 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 760"),
223 DMI_MATCH(DMI_BOARD_NAME, "0G919G"),
224 },
225 },
1da177e4
LT
226 { /* Handle problems with rebooting on Dell 2400's */
227 .callback = set_bios_reboot,
228 .ident = "Dell PowerEdge 2400",
229 .matches = {
230 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
231 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
232 },
233 },
fab3b58d
IM
234 { /* Handle problems with rebooting on Dell T5400's */
235 .callback = set_bios_reboot,
236 .ident = "Dell Precision T5400",
237 .matches = {
238 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
239 DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"),
240 },
241 },
890ffedc
TB
242 { /* Handle problems with rebooting on Dell T7400's */
243 .callback = set_bios_reboot,
244 .ident = "Dell Precision T7400",
245 .matches = {
246 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
247 DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T7400"),
248 },
249 },
766c3f94 250 { /* Handle problems with rebooting on HP laptops */
d91b14c4 251 .callback = set_bios_reboot,
766c3f94 252 .ident = "HP Compaq Laptop",
d91b14c4
TV
253 .matches = {
254 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
766c3f94 255 DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"),
d91b14c4
TV
256 },
257 },
dd4124a8
LO
258 { /* Handle problems with rebooting on Dell XPS710 */
259 .callback = set_bios_reboot,
260 .ident = "Dell XPS710",
261 .matches = {
262 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
263 DMI_MATCH(DMI_PRODUCT_NAME, "Dell XPS710"),
264 },
265 },
c5da9a2b
AC
266 { /* Handle problems with rebooting on Dell DXP061 */
267 .callback = set_bios_reboot,
268 .ident = "Dell DXP061",
269 .matches = {
270 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
271 DMI_MATCH(DMI_PRODUCT_NAME, "Dell DXP061"),
272 },
273 },
88dff493
ZR
274 { /* Handle problems with rebooting on Sony VGN-Z540N */
275 .callback = set_bios_reboot,
276 .ident = "Sony VGN-Z540N",
277 .matches = {
278 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
279 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"),
280 },
281 },
77f32dfd
DT
282 { /* Handle problems with rebooting on CompuLab SBC-FITPC2 */
283 .callback = set_bios_reboot,
284 .ident = "CompuLab SBC-FITPC2",
285 .matches = {
286 DMI_MATCH(DMI_SYS_VENDOR, "CompuLab"),
287 DMI_MATCH(DMI_PRODUCT_NAME, "SBC-FITPC2"),
288 },
289 },
4832ddda
LO
290 { /* Handle problems with rebooting on ASUS P4S800 */
291 .callback = set_bios_reboot,
292 .ident = "ASUS P4S800",
293 .matches = {
294 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
295 DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
296 },
297 },
e19e074b
KK
298 { /* Handle problems with rebooting on VersaLogic Menlow boards */
299 .callback = set_bios_reboot,
300 .ident = "VersaLogic Menlow based board",
301 .matches = {
302 DMI_MATCH(DMI_BOARD_VENDOR, "VersaLogic Corporation"),
303 DMI_MATCH(DMI_BOARD_NAME, "VersaLogic Menlow board"),
304 },
305 },
b49c78d4 306 { /* Handle reboot issue on Acer Aspire one */
1ef03890 307 .callback = set_kbd_reboot,
b49c78d4
PC
308 .ident = "Acer Aspire One A110",
309 .matches = {
310 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
311 DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"),
312 },
313 },
1da177e4
LT
314 { }
315};
316
317static int __init reboot_init(void)
318{
319 dmi_check_system(reboot_dmi_table);
320 return 0;
321}
1da177e4
LT
322core_initcall(reboot_init);
323
3d35ac34
PA
324extern const unsigned char machine_real_restart_asm[];
325extern const u64 machine_real_restart_gdt[3];
1da177e4 326
3d35ac34 327void machine_real_restart(unsigned int type)
1da177e4 328{
3d35ac34
PA
329 void *restart_va;
330 unsigned long restart_pa;
331 void (*restart_lowmem)(unsigned int);
332 u64 *lowmem_gdt;
1da177e4 333
1da177e4
LT
334 local_irq_disable();
335
336 /* Write zero to CMOS register number 0x0f, which the BIOS POST
337 routine will recognize as telling it to do a proper reboot. (Well
338 that's what this book in front of me says -- it may only apply to
339 the Phoenix BIOS though, it's not clear). At the same time,
340 disable NMIs by setting the top bit in the CMOS address register,
341 as we're about to do peculiar things to the CPU. I'm not sure if
342 `outb_p' is needed instead of just `outb'. Use it to be on the
343 safe side. (Yes, CMOS_WRITE does outb_p's. - Paul G.)
344 */
62dbc210 345 spin_lock(&rtc_lock);
1da177e4 346 CMOS_WRITE(0x00, 0x8f);
62dbc210 347 spin_unlock(&rtc_lock);
1da177e4 348
1da177e4 349 /*
b40827fa 350 * Switch back to the initial page table.
1da177e4 351 */
b40827fa 352 load_cr3(initial_page_table);
1da177e4
LT
353
354 /* Write 0x1234 to absolute memory location 0x472. The BIOS reads
355 this on booting to tell it to "Bypass memory test (also warm
356 boot)". This seems like a fairly standard thing that gets set by
357 REBOOT.COM programs, and the previous reset routine did this
358 too. */
1da177e4
LT
359 *((unsigned short *)0x472) = reboot_mode;
360
3d35ac34
PA
361 /* Patch the GDT in the low memory trampoline */
362 lowmem_gdt = TRAMPOLINE_SYM(machine_real_restart_gdt);
363
364 restart_va = TRAMPOLINE_SYM(machine_real_restart_asm);
365 restart_pa = virt_to_phys(restart_va);
366 restart_lowmem = (void (*)(unsigned int))restart_pa;
367
368 /* GDT[0]: GDT self-pointer */
369 lowmem_gdt[0] =
370 (u64)(sizeof(machine_real_restart_gdt) - 1) +
371 ((u64)virt_to_phys(lowmem_gdt) << 16);
372 /* GDT[1]: 64K real mode code segment */
373 lowmem_gdt[1] =
374 GDT_ENTRY(0x009b, restart_pa, 0xffff);
375
376 /* Jump to the identity-mapped low memory code */
377 restart_lowmem(type);
1da177e4 378}
129f6946
AD
379#ifdef CONFIG_APM_MODULE
380EXPORT_SYMBOL(machine_real_restart);
381#endif
1da177e4 382
4d022e35
MB
383#endif /* CONFIG_X86_32 */
384
6c6c51e4 385/*
498cdbfb 386 * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
6c6c51e4
PM
387 */
388static int __init set_pci_reboot(const struct dmi_system_id *d)
389{
390 if (reboot_type != BOOT_CF9) {
391 reboot_type = BOOT_CF9;
392 printk(KERN_INFO "%s series board detected. "
393 "Selecting PCI-method for reboots.\n", d->ident);
394 }
395 return 0;
396}
397
398static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
3e03bbea 399 { /* Handle problems with rebooting on Apple MacBook5 */
6c6c51e4 400 .callback = set_pci_reboot,
3e03bbea 401 .ident = "Apple MacBook5",
6c6c51e4
PM
402 .matches = {
403 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
3e03bbea 404 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5"),
6c6c51e4
PM
405 },
406 },
3e03bbea 407 { /* Handle problems with rebooting on Apple MacBookPro5 */
498cdbfb 408 .callback = set_pci_reboot,
3e03bbea 409 .ident = "Apple MacBookPro5",
498cdbfb
OÇ
410 .matches = {
411 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
3e03bbea 412 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5"),
498cdbfb
OÇ
413 },
414 },
05154752
GH
415 { /* Handle problems with rebooting on Apple Macmini3,1 */
416 .callback = set_pci_reboot,
417 .ident = "Apple Macmini3,1",
418 .matches = {
419 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
420 DMI_MATCH(DMI_PRODUCT_NAME, "Macmini3,1"),
421 },
422 },
0a832320
JM
423 { /* Handle problems with rebooting on the iMac9,1. */
424 .callback = set_pci_reboot,
425 .ident = "Apple iMac9,1",
426 .matches = {
427 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
428 DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"),
429 },
430 },
3628c3f5
MR
431 { /* Handle problems with rebooting on the Latitude E6320. */
432 .callback = set_pci_reboot,
433 .ident = "Dell Latitude E6320",
434 .matches = {
435 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
436 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6320"),
437 },
438 },
b7798d28
DB
439 { /* Handle problems with rebooting on the Latitude E5420. */
440 .callback = set_pci_reboot,
441 .ident = "Dell Latitude E5420",
442 .matches = {
443 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
444 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5420"),
445 },
446 },
a536877e
PA
447 { /* Handle problems with rebooting on the Latitude E6420. */
448 .callback = set_pci_reboot,
449 .ident = "Dell Latitude E6420",
450 .matches = {
451 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
452 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6420"),
453 },
454 },
6be30bb7
RW
455 { /* Handle problems with rebooting on the OptiPlex 990. */
456 .callback = set_pci_reboot,
457 .ident = "Dell OptiPlex 990",
458 .matches = {
459 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
460 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"),
461 },
462 },
6c6c51e4
PM
463 { }
464};
465
466static int __init pci_reboot_init(void)
467{
468 dmi_check_system(pci_reboot_dmi_table);
469 return 0;
470}
471core_initcall(pci_reboot_init);
472
4d022e35
MB
473static inline void kb_wait(void)
474{
475 int i;
476
c84d6af8
AC
477 for (i = 0; i < 0x10000; i++) {
478 if ((inb(0x64) & 0x02) == 0)
4d022e35 479 break;
c84d6af8
AC
480 udelay(2);
481 }
4d022e35
MB
482}
483
9c48f1c6 484static void vmxoff_nmi(int cpu, struct pt_regs *regs)
d176720d
EH
485{
486 cpu_emergency_vmxoff();
487}
488
489/* Use NMIs as IPIs to tell all CPUs to disable virtualization
490 */
491static void emergency_vmx_disable_all(void)
492{
493 /* Just make sure we won't change CPUs while doing this */
494 local_irq_disable();
495
496 /* We need to disable VMX on all CPUs before rebooting, otherwise
497 * we risk hanging up the machine, because the CPU ignore INIT
498 * signals when VMX is enabled.
499 *
500 * We can't take any locks and we may be on an inconsistent
501 * state, so we use NMIs as IPIs to tell the other CPUs to disable
502 * VMX and halt.
503 *
504 * For safety, we will avoid running the nmi_shootdown_cpus()
505 * stuff unnecessarily, but we don't have a way to check
506 * if other CPUs have VMX enabled. So we will call it only if the
507 * CPU we are running on has VMX enabled.
508 *
509 * We will miss cases where VMX is not enabled on all CPUs. This
510 * shouldn't do much harm because KVM always enable VMX on all
511 * CPUs anyway. But we can miss it on the small window where KVM
512 * is still enabling VMX.
513 */
514 if (cpu_has_vmx() && cpu_vmx_enabled()) {
515 /* Disable VMX on this CPU.
516 */
517 cpu_vmxoff();
518
519 /* Halt and disable VMX on the other CPUs */
520 nmi_shootdown_cpus(vmxoff_nmi);
521
522 }
523}
524
525
7432d149
IM
526void __attribute__((weak)) mach_reboot_fixups(void)
527{
528}
529
660e34ce
MG
530/*
531 * Windows compatible x86 hardware expects the following on reboot:
532 *
533 * 1) If the FADT has the ACPI reboot register flag set, try it
534 * 2) If still alive, write to the keyboard controller
535 * 3) If still alive, write to the ACPI reboot register again
536 * 4) If still alive, write to the keyboard controller again
537 *
538 * If the machine is still alive at this stage, it gives up. We default to
539 * following the same pattern, except that if we're still alive after (4) we'll
540 * try to force a triple fault and then cycle between hitting the keyboard
541 * controller and doing that
542 */
416e2d63 543static void native_machine_emergency_restart(void)
1da177e4 544{
4d022e35 545 int i;
660e34ce
MG
546 int attempt = 0;
547 int orig_reboot_type = reboot_type;
4d022e35 548
d176720d
EH
549 if (reboot_emergency)
550 emergency_vmx_disable_all();
551
840c2baf
JC
552 tboot_shutdown(TB_SHUTDOWN_REBOOT);
553
4d022e35
MB
554 /* Tell the BIOS if we want cold or warm reboot */
555 *((unsigned short *)__va(0x472)) = reboot_mode;
556
557 for (;;) {
558 /* Could also try the reset bit in the Hammer NB */
559 switch (reboot_type) {
560 case BOOT_KBD:
7432d149
IM
561 mach_reboot_fixups(); /* for board specific fixups */
562
4d022e35
MB
563 for (i = 0; i < 10; i++) {
564 kb_wait();
565 udelay(50);
566 outb(0xfe, 0x64); /* pulse reset low */
567 udelay(50);
568 }
660e34ce
MG
569 if (attempt == 0 && orig_reboot_type == BOOT_ACPI) {
570 attempt = 1;
571 reboot_type = BOOT_ACPI;
572 } else {
573 reboot_type = BOOT_TRIPLE;
574 }
575 break;
4d022e35
MB
576
577 case BOOT_TRIPLE:
ebdd561a 578 load_idt(&no_idt);
4d022e35
MB
579 __asm__ __volatile__("int3");
580
581 reboot_type = BOOT_KBD;
582 break;
583
584#ifdef CONFIG_X86_32
585 case BOOT_BIOS:
3d35ac34 586 machine_real_restart(MRR_BIOS);
4d022e35
MB
587
588 reboot_type = BOOT_KBD;
589 break;
590#endif
591
592 case BOOT_ACPI:
593 acpi_reboot();
594 reboot_type = BOOT_KBD;
595 break;
596
4d022e35
MB
597 case BOOT_EFI:
598 if (efi_enabled)
14d7ca5c
PA
599 efi.reset_system(reboot_mode ?
600 EFI_RESET_WARM :
601 EFI_RESET_COLD,
4d022e35 602 EFI_SUCCESS, 0, NULL);
b47b9288 603 reboot_type = BOOT_KBD;
14d7ca5c 604 break;
4d022e35 605
14d7ca5c
PA
606 case BOOT_CF9:
607 port_cf9_safe = true;
608 /* fall through */
4d022e35 609
14d7ca5c
PA
610 case BOOT_CF9_COND:
611 if (port_cf9_safe) {
612 u8 cf9 = inb(0xcf9) & ~6;
613 outb(cf9|2, 0xcf9); /* Request hard reset */
614 udelay(50);
615 outb(cf9|6, 0xcf9); /* Actually do the reset */
616 udelay(50);
617 }
4d022e35
MB
618 reboot_type = BOOT_KBD;
619 break;
620 }
621 }
622}
623
3c62c625 624void native_machine_shutdown(void)
4d022e35
MB
625{
626 /* Stop the cpus and apics */
1da177e4 627#ifdef CONFIG_SMP
dd2a1305
EB
628
629 /* The boot cpu is always logical cpu 0 */
65c01184 630 int reboot_cpu_id = 0;
dd2a1305 631
4d022e35 632#ifdef CONFIG_X86_32
dd2a1305 633 /* See if there has been given a command line override */
9628937d 634 if ((reboot_cpu != -1) && (reboot_cpu < nr_cpu_ids) &&
0bc3cc03 635 cpu_online(reboot_cpu))
dd2a1305 636 reboot_cpu_id = reboot_cpu;
4d022e35 637#endif
1da177e4 638
4d022e35 639 /* Make certain the cpu I'm about to reboot on is online */
0bc3cc03 640 if (!cpu_online(reboot_cpu_id))
dd2a1305 641 reboot_cpu_id = smp_processor_id();
dd2a1305
EB
642
643 /* Make certain I only run on the appropriate processor */
9628937d 644 set_cpus_allowed_ptr(current, cpumask_of(reboot_cpu_id));
dd2a1305 645
4d022e35
MB
646 /* O.K Now that I'm on the appropriate processor,
647 * stop all of the others.
1da177e4 648 */
76fac077 649 stop_other_cpus();
4d022e35 650#endif
1da177e4
LT
651
652 lapic_shutdown();
653
654#ifdef CONFIG_X86_IO_APIC
655 disable_IO_APIC();
656#endif
4d022e35 657
c86c7fbc
OH
658#ifdef CONFIG_HPET_TIMER
659 hpet_disable();
660#endif
dd2a1305 661
4d022e35 662#ifdef CONFIG_X86_64
338bac52 663 x86_platform.iommu_shutdown();
4d022e35 664#endif
973efae2
JF
665}
666
d176720d
EH
667static void __machine_emergency_restart(int emergency)
668{
669 reboot_emergency = emergency;
670 machine_ops.emergency_restart();
671}
672
416e2d63 673static void native_machine_restart(char *__unused)
dd2a1305 674{
4d022e35 675 printk("machine restart\n");
1da177e4 676
4d022e35
MB
677 if (!reboot_force)
678 machine_shutdown();
d176720d 679 __machine_emergency_restart(0);
4a1421f8
EB
680}
681
416e2d63 682static void native_machine_halt(void)
1da177e4 683{
d3ec5cae
IV
684 /* stop other cpus and apics */
685 machine_shutdown();
686
840c2baf
JC
687 tboot_shutdown(TB_SHUTDOWN_HALT);
688
d3ec5cae
IV
689 /* stop this cpu */
690 stop_this_cpu(NULL);
1da177e4
LT
691}
692
416e2d63 693static void native_machine_power_off(void)
1da177e4 694{
6e3fbee5 695 if (pm_power_off) {
4d022e35
MB
696 if (!reboot_force)
697 machine_shutdown();
1da177e4 698 pm_power_off();
6e3fbee5 699 }
840c2baf
JC
700 /* a fallback in case there is no PM info available */
701 tboot_shutdown(TB_SHUTDOWN_HALT);
1da177e4
LT
702}
703
07f3331c 704struct machine_ops machine_ops = {
416e2d63
JB
705 .power_off = native_machine_power_off,
706 .shutdown = native_machine_shutdown,
707 .emergency_restart = native_machine_emergency_restart,
708 .restart = native_machine_restart,
ed23dc6f
GC
709 .halt = native_machine_halt,
710#ifdef CONFIG_KEXEC
711 .crash_shutdown = native_machine_crash_shutdown,
712#endif
07f3331c 713};
416e2d63
JB
714
715void machine_power_off(void)
716{
717 machine_ops.power_off();
718}
719
720void machine_shutdown(void)
721{
722 machine_ops.shutdown();
723}
724
725void machine_emergency_restart(void)
726{
d176720d 727 __machine_emergency_restart(1);
416e2d63
JB
728}
729
730void machine_restart(char *cmd)
731{
732 machine_ops.restart(cmd);
733}
734
735void machine_halt(void)
736{
737 machine_ops.halt();
738}
739
ed23dc6f
GC
740#ifdef CONFIG_KEXEC
741void machine_crash_shutdown(struct pt_regs *regs)
742{
743 machine_ops.crash_shutdown(regs);
744}
745#endif
2ddded21
EH
746
747
bb8dd270 748#if defined(CONFIG_SMP)
2ddded21
EH
749
750/* This keeps a track of which one is crashing cpu. */
751static int crashing_cpu;
752static nmi_shootdown_cb shootdown_callback;
753
754static atomic_t waiting_for_crash_ipi;
755
9c48f1c6 756static int crash_nmi_callback(unsigned int val, struct pt_regs *regs)
2ddded21
EH
757{
758 int cpu;
759
2ddded21
EH
760 cpu = raw_smp_processor_id();
761
762 /* Don't do anything if this handler is invoked on crashing cpu.
763 * Otherwise, system will completely hang. Crashing cpu can get
764 * an NMI if system was initially booted with nmi_watchdog parameter.
765 */
766 if (cpu == crashing_cpu)
9c48f1c6 767 return NMI_HANDLED;
2ddded21
EH
768 local_irq_disable();
769
9c48f1c6 770 shootdown_callback(cpu, regs);
2ddded21
EH
771
772 atomic_dec(&waiting_for_crash_ipi);
773 /* Assume hlt works */
774 halt();
775 for (;;)
776 cpu_relax();
777
9c48f1c6 778 return NMI_HANDLED;
2ddded21
EH
779}
780
781static void smp_send_nmi_allbutself(void)
782{
dac5f412 783 apic->send_IPI_allbutself(NMI_VECTOR);
2ddded21
EH
784}
785
bb8dd270
EH
786/* Halt all other CPUs, calling the specified function on each of them
787 *
788 * This function can be used to halt all other CPUs on crash
789 * or emergency reboot time. The function passed as parameter
790 * will be called inside a NMI handler on all CPUs.
791 */
2ddded21
EH
792void nmi_shootdown_cpus(nmi_shootdown_cb callback)
793{
794 unsigned long msecs;
c415b3dc 795 local_irq_disable();
2ddded21
EH
796
797 /* Make a note of crashing cpu. Will be used in NMI callback.*/
798 crashing_cpu = safe_smp_processor_id();
799
800 shootdown_callback = callback;
801
802 atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
803 /* Would it be better to replace the trap vector here? */
9c48f1c6
DZ
804 if (register_nmi_handler(NMI_LOCAL, crash_nmi_callback,
805 NMI_FLAG_FIRST, "crash"))
2ddded21
EH
806 return; /* return what? */
807 /* Ensure the new callback function is set before sending
808 * out the NMI
809 */
810 wmb();
811
812 smp_send_nmi_allbutself();
813
814 msecs = 1000; /* Wait at most a second for the other cpus to stop */
815 while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
816 mdelay(1);
817 msecs--;
818 }
819
820 /* Leave the nmi callback set */
821}
bb8dd270
EH
822#else /* !CONFIG_SMP */
823void nmi_shootdown_cpus(nmi_shootdown_cb callback)
824{
825 /* No other CPUs to shoot down */
826}
2ddded21 827#endif
This page took 0.736468 seconds and 5 git commands to generate.