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