source: src/linux/universal/linux-4.9/arch/x86/kernel/reboot.c @ 31859

Last change on this file since 31859 was 31859, checked in by brainslayer, 10 days ago

kernel update

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