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