Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0003 
0004 #include <linux/export.h>
0005 #include <linux/reboot.h>
0006 #include <linux/init.h>
0007 #include <linux/pm.h>
0008 #include <linux/efi.h>
0009 #include <linux/dmi.h>
0010 #include <linux/sched.h>
0011 #include <linux/tboot.h>
0012 #include <linux/delay.h>
0013 #include <linux/objtool.h>
0014 #include <linux/pgtable.h>
0015 #include <acpi/reboot.h>
0016 #include <asm/io.h>
0017 #include <asm/apic.h>
0018 #include <asm/io_apic.h>
0019 #include <asm/desc.h>
0020 #include <asm/hpet.h>
0021 #include <asm/proto.h>
0022 #include <asm/reboot_fixups.h>
0023 #include <asm/reboot.h>
0024 #include <asm/pci_x86.h>
0025 #include <asm/virtext.h>
0026 #include <asm/cpu.h>
0027 #include <asm/nmi.h>
0028 #include <asm/smp.h>
0029 
0030 #include <linux/ctype.h>
0031 #include <linux/mc146818rtc.h>
0032 #include <asm/realmode.h>
0033 #include <asm/x86_init.h>
0034 #include <asm/efi.h>
0035 
0036 /*
0037  * Power off function, if any
0038  */
0039 void (*pm_power_off)(void);
0040 EXPORT_SYMBOL(pm_power_off);
0041 
0042 /*
0043  * This is set if we need to go through the 'emergency' path.
0044  * When machine_emergency_restart() is called, we may be on
0045  * an inconsistent state and won't be able to do a clean cleanup
0046  */
0047 static int reboot_emergency;
0048 
0049 /* This is set by the PCI code if either type 1 or type 2 PCI is detected */
0050 bool port_cf9_safe = false;
0051 
0052 /*
0053  * Reboot options and system auto-detection code provided by
0054  * Dell Inc. so their systems "just work". :-)
0055  */
0056 
0057 /*
0058  * Some machines require the "reboot=a" commandline options
0059  */
0060 static int __init set_acpi_reboot(const struct dmi_system_id *d)
0061 {
0062     if (reboot_type != BOOT_ACPI) {
0063         reboot_type = BOOT_ACPI;
0064         pr_info("%s series board detected. Selecting %s-method for reboots.\n",
0065             d->ident, "ACPI");
0066     }
0067     return 0;
0068 }
0069 
0070 /*
0071  * Some machines require the "reboot=b" or "reboot=k"  commandline options,
0072  * this quirk makes that automatic.
0073  */
0074 static int __init set_bios_reboot(const struct dmi_system_id *d)
0075 {
0076     if (reboot_type != BOOT_BIOS) {
0077         reboot_type = BOOT_BIOS;
0078         pr_info("%s series board detected. Selecting %s-method for reboots.\n",
0079             d->ident, "BIOS");
0080     }
0081     return 0;
0082 }
0083 
0084 /*
0085  * Some machines don't handle the default ACPI reboot method and
0086  * require the EFI reboot method:
0087  */
0088 static int __init set_efi_reboot(const struct dmi_system_id *d)
0089 {
0090     if (reboot_type != BOOT_EFI && !efi_runtime_disabled()) {
0091         reboot_type = BOOT_EFI;
0092         pr_info("%s series board detected. Selecting EFI-method for reboot.\n", d->ident);
0093     }
0094     return 0;
0095 }
0096 
0097 void __noreturn machine_real_restart(unsigned int type)
0098 {
0099     local_irq_disable();
0100 
0101     /*
0102      * Write zero to CMOS register number 0x0f, which the BIOS POST
0103      * routine will recognize as telling it to do a proper reboot.  (Well
0104      * that's what this book in front of me says -- it may only apply to
0105      * the Phoenix BIOS though, it's not clear).  At the same time,
0106      * disable NMIs by setting the top bit in the CMOS address register,
0107      * as we're about to do peculiar things to the CPU.  I'm not sure if
0108      * `outb_p' is needed instead of just `outb'.  Use it to be on the
0109      * safe side.  (Yes, CMOS_WRITE does outb_p's. -  Paul G.)
0110      */
0111     spin_lock(&rtc_lock);
0112     CMOS_WRITE(0x00, 0x8f);
0113     spin_unlock(&rtc_lock);
0114 
0115     /*
0116      * Switch to the trampoline page table.
0117      */
0118     load_trampoline_pgtable();
0119 
0120     /* Jump to the identity-mapped low memory code */
0121 #ifdef CONFIG_X86_32
0122     asm volatile("jmpl *%0" : :
0123              "rm" (real_mode_header->machine_real_restart_asm),
0124              "a" (type));
0125 #else
0126     asm volatile("ljmpl *%0" : :
0127              "m" (real_mode_header->machine_real_restart_asm),
0128              "D" (type));
0129 #endif
0130     unreachable();
0131 }
0132 #ifdef CONFIG_APM_MODULE
0133 EXPORT_SYMBOL(machine_real_restart);
0134 #endif
0135 STACK_FRAME_NON_STANDARD(machine_real_restart);
0136 
0137 /*
0138  * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
0139  */
0140 static int __init set_pci_reboot(const struct dmi_system_id *d)
0141 {
0142     if (reboot_type != BOOT_CF9_FORCE) {
0143         reboot_type = BOOT_CF9_FORCE;
0144         pr_info("%s series board detected. Selecting %s-method for reboots.\n",
0145             d->ident, "PCI");
0146     }
0147     return 0;
0148 }
0149 
0150 static int __init set_kbd_reboot(const struct dmi_system_id *d)
0151 {
0152     if (reboot_type != BOOT_KBD) {
0153         reboot_type = BOOT_KBD;
0154         pr_info("%s series board detected. Selecting %s-method for reboot.\n",
0155             d->ident, "KBD");
0156     }
0157     return 0;
0158 }
0159 
0160 /*
0161  * This is a single dmi_table handling all reboot quirks.
0162  */
0163 static const struct dmi_system_id reboot_dmi_table[] __initconst = {
0164 
0165     /* Acer */
0166     {   /* Handle reboot issue on Acer Aspire one */
0167         .callback = set_kbd_reboot,
0168         .ident = "Acer Aspire One A110",
0169         .matches = {
0170             DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
0171             DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"),
0172         },
0173     },
0174     {   /* Handle reboot issue on Acer TravelMate X514-51T */
0175         .callback = set_efi_reboot,
0176         .ident = "Acer TravelMate X514-51T",
0177         .matches = {
0178             DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
0179             DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate X514-51T"),
0180         },
0181     },
0182 
0183     /* Apple */
0184     {   /* Handle problems with rebooting on Apple MacBook5 */
0185         .callback = set_pci_reboot,
0186         .ident = "Apple MacBook5",
0187         .matches = {
0188             DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
0189             DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5"),
0190         },
0191     },
0192     {   /* Handle problems with rebooting on Apple MacBook6,1 */
0193         .callback = set_pci_reboot,
0194         .ident = "Apple MacBook6,1",
0195         .matches = {
0196             DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
0197             DMI_MATCH(DMI_PRODUCT_NAME, "MacBook6,1"),
0198         },
0199     },
0200     {   /* Handle problems with rebooting on Apple MacBookPro5 */
0201         .callback = set_pci_reboot,
0202         .ident = "Apple MacBookPro5",
0203         .matches = {
0204             DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
0205             DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5"),
0206         },
0207     },
0208     {   /* Handle problems with rebooting on Apple Macmini3,1 */
0209         .callback = set_pci_reboot,
0210         .ident = "Apple Macmini3,1",
0211         .matches = {
0212             DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
0213             DMI_MATCH(DMI_PRODUCT_NAME, "Macmini3,1"),
0214         },
0215     },
0216     {   /* Handle problems with rebooting on the iMac9,1. */
0217         .callback = set_pci_reboot,
0218         .ident = "Apple iMac9,1",
0219         .matches = {
0220             DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
0221             DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"),
0222         },
0223     },
0224     {   /* Handle problems with rebooting on the iMac10,1. */
0225         .callback = set_pci_reboot,
0226         .ident = "Apple iMac10,1",
0227         .matches = {
0228             DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
0229             DMI_MATCH(DMI_PRODUCT_NAME, "iMac10,1"),
0230         },
0231     },
0232 
0233     /* ASRock */
0234     {   /* Handle problems with rebooting on ASRock Q1900DC-ITX */
0235         .callback = set_pci_reboot,
0236         .ident = "ASRock Q1900DC-ITX",
0237         .matches = {
0238             DMI_MATCH(DMI_BOARD_VENDOR, "ASRock"),
0239             DMI_MATCH(DMI_BOARD_NAME, "Q1900DC-ITX"),
0240         },
0241     },
0242 
0243     /* ASUS */
0244     {   /* Handle problems with rebooting on ASUS P4S800 */
0245         .callback = set_bios_reboot,
0246         .ident = "ASUS P4S800",
0247         .matches = {
0248             DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
0249             DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
0250         },
0251     },
0252     {   /* Handle problems with rebooting on ASUS EeeBook X205TA */
0253         .callback = set_acpi_reboot,
0254         .ident = "ASUS EeeBook X205TA",
0255         .matches = {
0256             DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
0257             DMI_MATCH(DMI_PRODUCT_NAME, "X205TA"),
0258         },
0259     },
0260     {   /* Handle problems with rebooting on ASUS EeeBook X205TAW */
0261         .callback = set_acpi_reboot,
0262         .ident = "ASUS EeeBook X205TAW",
0263         .matches = {
0264             DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
0265             DMI_MATCH(DMI_PRODUCT_NAME, "X205TAW"),
0266         },
0267     },
0268 
0269     /* Certec */
0270     {       /* Handle problems with rebooting on Certec BPC600 */
0271         .callback = set_pci_reboot,
0272         .ident = "Certec BPC600",
0273         .matches = {
0274             DMI_MATCH(DMI_SYS_VENDOR, "Certec"),
0275             DMI_MATCH(DMI_PRODUCT_NAME, "BPC600"),
0276         },
0277     },
0278 
0279     /* Dell */
0280     {   /* Handle problems with rebooting on Dell DXP061 */
0281         .callback = set_bios_reboot,
0282         .ident = "Dell DXP061",
0283         .matches = {
0284             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0285             DMI_MATCH(DMI_PRODUCT_NAME, "Dell DXP061"),
0286         },
0287     },
0288     {   /* Handle problems with rebooting on Dell E520's */
0289         .callback = set_bios_reboot,
0290         .ident = "Dell E520",
0291         .matches = {
0292             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0293             DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM061"),
0294         },
0295     },
0296     {   /* Handle problems with rebooting on the Latitude E5410. */
0297         .callback = set_pci_reboot,
0298         .ident = "Dell Latitude E5410",
0299         .matches = {
0300             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0301             DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5410"),
0302         },
0303     },
0304     {   /* Handle problems with rebooting on the Latitude E5420. */
0305         .callback = set_pci_reboot,
0306         .ident = "Dell Latitude E5420",
0307         .matches = {
0308             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0309             DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5420"),
0310         },
0311     },
0312     {   /* Handle problems with rebooting on the Latitude E6320. */
0313         .callback = set_pci_reboot,
0314         .ident = "Dell Latitude E6320",
0315         .matches = {
0316             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0317             DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6320"),
0318         },
0319     },
0320     {   /* Handle problems with rebooting on the Latitude E6420. */
0321         .callback = set_pci_reboot,
0322         .ident = "Dell Latitude E6420",
0323         .matches = {
0324             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0325             DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6420"),
0326         },
0327     },
0328     {   /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */
0329         .callback = set_bios_reboot,
0330         .ident = "Dell OptiPlex 330",
0331         .matches = {
0332             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0333             DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 330"),
0334             DMI_MATCH(DMI_BOARD_NAME, "0KP561"),
0335         },
0336     },
0337     {   /* Handle problems with rebooting on Dell Optiplex 360 with 0T656F */
0338         .callback = set_bios_reboot,
0339         .ident = "Dell OptiPlex 360",
0340         .matches = {
0341             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0342             DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 360"),
0343             DMI_MATCH(DMI_BOARD_NAME, "0T656F"),
0344         },
0345     },
0346     {   /* Handle problems with rebooting on Dell Optiplex 745's SFF */
0347         .callback = set_bios_reboot,
0348         .ident = "Dell OptiPlex 745",
0349         .matches = {
0350             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0351             DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
0352         },
0353     },
0354     {   /* Handle problems with rebooting on Dell Optiplex 745's DFF */
0355         .callback = set_bios_reboot,
0356         .ident = "Dell OptiPlex 745",
0357         .matches = {
0358             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0359             DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
0360             DMI_MATCH(DMI_BOARD_NAME, "0MM599"),
0361         },
0362     },
0363     {   /* Handle problems with rebooting on Dell Optiplex 745 with 0KW626 */
0364         .callback = set_bios_reboot,
0365         .ident = "Dell OptiPlex 745",
0366         .matches = {
0367             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0368             DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
0369             DMI_MATCH(DMI_BOARD_NAME, "0KW626"),
0370         },
0371     },
0372     {   /* Handle problems with rebooting on Dell OptiPlex 760 with 0G919G */
0373         .callback = set_bios_reboot,
0374         .ident = "Dell OptiPlex 760",
0375         .matches = {
0376             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0377             DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 760"),
0378             DMI_MATCH(DMI_BOARD_NAME, "0G919G"),
0379         },
0380     },
0381     {   /* Handle problems with rebooting on the OptiPlex 990. */
0382         .callback = set_pci_reboot,
0383         .ident = "Dell OptiPlex 990 BIOS A0x",
0384         .matches = {
0385             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0386             DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"),
0387             DMI_MATCH(DMI_BIOS_VERSION, "A0"),
0388         },
0389     },
0390     {   /* Handle problems with rebooting on Dell 300's */
0391         .callback = set_bios_reboot,
0392         .ident = "Dell PowerEdge 300",
0393         .matches = {
0394             DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
0395             DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
0396         },
0397     },
0398     {   /* Handle problems with rebooting on Dell 1300's */
0399         .callback = set_bios_reboot,
0400         .ident = "Dell PowerEdge 1300",
0401         .matches = {
0402             DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
0403             DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
0404         },
0405     },
0406     {   /* Handle problems with rebooting on Dell 2400's */
0407         .callback = set_bios_reboot,
0408         .ident = "Dell PowerEdge 2400",
0409         .matches = {
0410             DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
0411             DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
0412         },
0413     },
0414     {   /* Handle problems with rebooting on the Dell PowerEdge C6100. */
0415         .callback = set_pci_reboot,
0416         .ident = "Dell PowerEdge C6100",
0417         .matches = {
0418             DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
0419             DMI_MATCH(DMI_PRODUCT_NAME, "C6100"),
0420         },
0421     },
0422     {   /* Handle problems with rebooting on the Precision M6600. */
0423         .callback = set_pci_reboot,
0424         .ident = "Dell Precision M6600",
0425         .matches = {
0426             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0427             DMI_MATCH(DMI_PRODUCT_NAME, "Precision M6600"),
0428         },
0429     },
0430     {   /* Handle problems with rebooting on Dell T5400's */
0431         .callback = set_bios_reboot,
0432         .ident = "Dell Precision T5400",
0433         .matches = {
0434             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0435             DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"),
0436         },
0437     },
0438     {   /* Handle problems with rebooting on Dell T7400's */
0439         .callback = set_bios_reboot,
0440         .ident = "Dell Precision T7400",
0441         .matches = {
0442             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0443             DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T7400"),
0444         },
0445     },
0446     {   /* Handle problems with rebooting on Dell XPS710 */
0447         .callback = set_bios_reboot,
0448         .ident = "Dell XPS710",
0449         .matches = {
0450             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0451             DMI_MATCH(DMI_PRODUCT_NAME, "Dell XPS710"),
0452         },
0453     },
0454     {   /* Handle problems with rebooting on Dell Optiplex 7450 AIO */
0455         .callback = set_acpi_reboot,
0456         .ident = "Dell OptiPlex 7450 AIO",
0457         .matches = {
0458             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0459             DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 7450 AIO"),
0460         },
0461     },
0462 
0463     /* Hewlett-Packard */
0464     {   /* Handle problems with rebooting on HP laptops */
0465         .callback = set_bios_reboot,
0466         .ident = "HP Compaq Laptop",
0467         .matches = {
0468             DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
0469             DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"),
0470         },
0471     },
0472 
0473     {   /* PCIe Wifi card isn't detected after reboot otherwise */
0474         .callback = set_pci_reboot,
0475         .ident = "Zotac ZBOX CI327 nano",
0476         .matches = {
0477             DMI_MATCH(DMI_SYS_VENDOR, "NA"),
0478             DMI_MATCH(DMI_PRODUCT_NAME, "ZBOX-CI327NANO-GS-01"),
0479         },
0480     },
0481 
0482     /* Sony */
0483     {   /* Handle problems with rebooting on Sony VGN-Z540N */
0484         .callback = set_bios_reboot,
0485         .ident = "Sony VGN-Z540N",
0486         .matches = {
0487             DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
0488             DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"),
0489         },
0490     },
0491 
0492     { }
0493 };
0494 
0495 static int __init reboot_init(void)
0496 {
0497     int rv;
0498 
0499     /*
0500      * Only do the DMI check if reboot_type hasn't been overridden
0501      * on the command line
0502      */
0503     if (!reboot_default)
0504         return 0;
0505 
0506     /*
0507      * The DMI quirks table takes precedence. If no quirks entry
0508      * matches and the ACPI Hardware Reduced bit is set and EFI
0509      * runtime services are enabled, force EFI reboot.
0510      */
0511     rv = dmi_check_system(reboot_dmi_table);
0512 
0513     if (!rv && efi_reboot_required() && !efi_runtime_disabled())
0514         reboot_type = BOOT_EFI;
0515 
0516     return 0;
0517 }
0518 core_initcall(reboot_init);
0519 
0520 static inline void kb_wait(void)
0521 {
0522     int i;
0523 
0524     for (i = 0; i < 0x10000; i++) {
0525         if ((inb(0x64) & 0x02) == 0)
0526             break;
0527         udelay(2);
0528     }
0529 }
0530 
0531 static void vmxoff_nmi(int cpu, struct pt_regs *regs)
0532 {
0533     cpu_emergency_vmxoff();
0534 }
0535 
0536 /* Use NMIs as IPIs to tell all CPUs to disable virtualization */
0537 static void emergency_vmx_disable_all(void)
0538 {
0539     /* Just make sure we won't change CPUs while doing this */
0540     local_irq_disable();
0541 
0542     /*
0543      * Disable VMX on all CPUs before rebooting, otherwise we risk hanging
0544      * the machine, because the CPU blocks INIT when it's in VMX root.
0545      *
0546      * We can't take any locks and we may be on an inconsistent state, so
0547      * use NMIs as IPIs to tell the other CPUs to exit VMX root and halt.
0548      *
0549      * Do the NMI shootdown even if VMX if off on _this_ CPU, as that
0550      * doesn't prevent a different CPU from being in VMX root operation.
0551      */
0552     if (cpu_has_vmx()) {
0553         /* Safely force _this_ CPU out of VMX root operation. */
0554         __cpu_emergency_vmxoff();
0555 
0556         /* Halt and exit VMX root operation on the other CPUs. */
0557         nmi_shootdown_cpus(vmxoff_nmi);
0558     }
0559 }
0560 
0561 
0562 void __attribute__((weak)) mach_reboot_fixups(void)
0563 {
0564 }
0565 
0566 /*
0567  * To the best of our knowledge Windows compatible x86 hardware expects
0568  * the following on reboot:
0569  *
0570  * 1) If the FADT has the ACPI reboot register flag set, try it
0571  * 2) If still alive, write to the keyboard controller
0572  * 3) If still alive, write to the ACPI reboot register again
0573  * 4) If still alive, write to the keyboard controller again
0574  * 5) If still alive, call the EFI runtime service to reboot
0575  * 6) If no EFI runtime service, call the BIOS to do a reboot
0576  *
0577  * We default to following the same pattern. We also have
0578  * two other reboot methods: 'triple fault' and 'PCI', which
0579  * can be triggered via the reboot= kernel boot option or
0580  * via quirks.
0581  *
0582  * This means that this function can never return, it can misbehave
0583  * by not rebooting properly and hanging.
0584  */
0585 static void native_machine_emergency_restart(void)
0586 {
0587     int i;
0588     int attempt = 0;
0589     int orig_reboot_type = reboot_type;
0590     unsigned short mode;
0591 
0592     if (reboot_emergency)
0593         emergency_vmx_disable_all();
0594 
0595     tboot_shutdown(TB_SHUTDOWN_REBOOT);
0596 
0597     /* Tell the BIOS if we want cold or warm reboot */
0598     mode = reboot_mode == REBOOT_WARM ? 0x1234 : 0;
0599     *((unsigned short *)__va(0x472)) = mode;
0600 
0601     /*
0602      * If an EFI capsule has been registered with the firmware then
0603      * override the reboot= parameter.
0604      */
0605     if (efi_capsule_pending(NULL)) {
0606         pr_info("EFI capsule is pending, forcing EFI reboot.\n");
0607         reboot_type = BOOT_EFI;
0608     }
0609 
0610     for (;;) {
0611         /* Could also try the reset bit in the Hammer NB */
0612         switch (reboot_type) {
0613         case BOOT_ACPI:
0614             acpi_reboot();
0615             reboot_type = BOOT_KBD;
0616             break;
0617 
0618         case BOOT_KBD:
0619             mach_reboot_fixups(); /* For board specific fixups */
0620 
0621             for (i = 0; i < 10; i++) {
0622                 kb_wait();
0623                 udelay(50);
0624                 outb(0xfe, 0x64); /* Pulse reset low */
0625                 udelay(50);
0626             }
0627             if (attempt == 0 && orig_reboot_type == BOOT_ACPI) {
0628                 attempt = 1;
0629                 reboot_type = BOOT_ACPI;
0630             } else {
0631                 reboot_type = BOOT_EFI;
0632             }
0633             break;
0634 
0635         case BOOT_EFI:
0636             efi_reboot(reboot_mode, NULL);
0637             reboot_type = BOOT_BIOS;
0638             break;
0639 
0640         case BOOT_BIOS:
0641             machine_real_restart(MRR_BIOS);
0642 
0643             /* We're probably dead after this, but... */
0644             reboot_type = BOOT_CF9_SAFE;
0645             break;
0646 
0647         case BOOT_CF9_FORCE:
0648             port_cf9_safe = true;
0649             fallthrough;
0650 
0651         case BOOT_CF9_SAFE:
0652             if (port_cf9_safe) {
0653                 u8 reboot_code = reboot_mode == REBOOT_WARM ?  0x06 : 0x0E;
0654                 u8 cf9 = inb(0xcf9) & ~reboot_code;
0655                 outb(cf9|2, 0xcf9); /* Request hard reset */
0656                 udelay(50);
0657                 /* Actually do the reset */
0658                 outb(cf9|reboot_code, 0xcf9);
0659                 udelay(50);
0660             }
0661             reboot_type = BOOT_TRIPLE;
0662             break;
0663 
0664         case BOOT_TRIPLE:
0665             idt_invalidate();
0666             __asm__ __volatile__("int3");
0667 
0668             /* We're probably dead after this, but... */
0669             reboot_type = BOOT_KBD;
0670             break;
0671         }
0672     }
0673 }
0674 
0675 void native_machine_shutdown(void)
0676 {
0677     /* Stop the cpus and apics */
0678 #ifdef CONFIG_X86_IO_APIC
0679     /*
0680      * Disabling IO APIC before local APIC is a workaround for
0681      * erratum AVR31 in "Intel Atom Processor C2000 Product Family
0682      * Specification Update". In this situation, interrupts that target
0683      * a Logical Processor whose Local APIC is either in the process of
0684      * being hardware disabled or software disabled are neither delivered
0685      * nor discarded. When this erratum occurs, the processor may hang.
0686      *
0687      * Even without the erratum, it still makes sense to quiet IO APIC
0688      * before disabling Local APIC.
0689      */
0690     clear_IO_APIC();
0691 #endif
0692 
0693 #ifdef CONFIG_SMP
0694     /*
0695      * Stop all of the others. Also disable the local irq to
0696      * not receive the per-cpu timer interrupt which may trigger
0697      * scheduler's load balance.
0698      */
0699     local_irq_disable();
0700     stop_other_cpus();
0701 #endif
0702 
0703     lapic_shutdown();
0704     restore_boot_irq_mode();
0705 
0706 #ifdef CONFIG_HPET_TIMER
0707     hpet_disable();
0708 #endif
0709 
0710 #ifdef CONFIG_X86_64
0711     x86_platform.iommu_shutdown();
0712 #endif
0713 }
0714 
0715 static void __machine_emergency_restart(int emergency)
0716 {
0717     reboot_emergency = emergency;
0718     machine_ops.emergency_restart();
0719 }
0720 
0721 static void native_machine_restart(char *__unused)
0722 {
0723     pr_notice("machine restart\n");
0724 
0725     if (!reboot_force)
0726         machine_shutdown();
0727     __machine_emergency_restart(0);
0728 }
0729 
0730 static void native_machine_halt(void)
0731 {
0732     /* Stop other cpus and apics */
0733     machine_shutdown();
0734 
0735     tboot_shutdown(TB_SHUTDOWN_HALT);
0736 
0737     stop_this_cpu(NULL);
0738 }
0739 
0740 static void native_machine_power_off(void)
0741 {
0742     if (kernel_can_power_off()) {
0743         if (!reboot_force)
0744             machine_shutdown();
0745         do_kernel_power_off();
0746     }
0747     /* A fallback in case there is no PM info available */
0748     tboot_shutdown(TB_SHUTDOWN_HALT);
0749 }
0750 
0751 struct machine_ops machine_ops __ro_after_init = {
0752     .power_off = native_machine_power_off,
0753     .shutdown = native_machine_shutdown,
0754     .emergency_restart = native_machine_emergency_restart,
0755     .restart = native_machine_restart,
0756     .halt = native_machine_halt,
0757 #ifdef CONFIG_KEXEC_CORE
0758     .crash_shutdown = native_machine_crash_shutdown,
0759 #endif
0760 };
0761 
0762 void machine_power_off(void)
0763 {
0764     machine_ops.power_off();
0765 }
0766 
0767 void machine_shutdown(void)
0768 {
0769     machine_ops.shutdown();
0770 }
0771 
0772 void machine_emergency_restart(void)
0773 {
0774     __machine_emergency_restart(1);
0775 }
0776 
0777 void machine_restart(char *cmd)
0778 {
0779     machine_ops.restart(cmd);
0780 }
0781 
0782 void machine_halt(void)
0783 {
0784     machine_ops.halt();
0785 }
0786 
0787 #ifdef CONFIG_KEXEC_CORE
0788 void machine_crash_shutdown(struct pt_regs *regs)
0789 {
0790     machine_ops.crash_shutdown(regs);
0791 }
0792 #endif
0793 
0794 
0795 /* This is the CPU performing the emergency shutdown work. */
0796 int crashing_cpu = -1;
0797 
0798 #if defined(CONFIG_SMP)
0799 
0800 static nmi_shootdown_cb shootdown_callback;
0801 
0802 static atomic_t waiting_for_crash_ipi;
0803 static int crash_ipi_issued;
0804 
0805 static int crash_nmi_callback(unsigned int val, struct pt_regs *regs)
0806 {
0807     int cpu;
0808 
0809     cpu = raw_smp_processor_id();
0810 
0811     /*
0812      * Don't do anything if this handler is invoked on crashing cpu.
0813      * Otherwise, system will completely hang. Crashing cpu can get
0814      * an NMI if system was initially booted with nmi_watchdog parameter.
0815      */
0816     if (cpu == crashing_cpu)
0817         return NMI_HANDLED;
0818     local_irq_disable();
0819 
0820     shootdown_callback(cpu, regs);
0821 
0822     atomic_dec(&waiting_for_crash_ipi);
0823     /* Assume hlt works */
0824     halt();
0825     for (;;)
0826         cpu_relax();
0827 
0828     return NMI_HANDLED;
0829 }
0830 
0831 /*
0832  * Halt all other CPUs, calling the specified function on each of them
0833  *
0834  * This function can be used to halt all other CPUs on crash
0835  * or emergency reboot time. The function passed as parameter
0836  * will be called inside a NMI handler on all CPUs.
0837  */
0838 void nmi_shootdown_cpus(nmi_shootdown_cb callback)
0839 {
0840     unsigned long msecs;
0841     local_irq_disable();
0842 
0843     /* Make a note of crashing cpu. Will be used in NMI callback. */
0844     crashing_cpu = safe_smp_processor_id();
0845 
0846     shootdown_callback = callback;
0847 
0848     atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
0849     /* Would it be better to replace the trap vector here? */
0850     if (register_nmi_handler(NMI_LOCAL, crash_nmi_callback,
0851                  NMI_FLAG_FIRST, "crash"))
0852         return;     /* Return what? */
0853     /*
0854      * Ensure the new callback function is set before sending
0855      * out the NMI
0856      */
0857     wmb();
0858 
0859     apic_send_IPI_allbutself(NMI_VECTOR);
0860 
0861     /* Kick CPUs looping in NMI context. */
0862     WRITE_ONCE(crash_ipi_issued, 1);
0863 
0864     msecs = 1000; /* Wait at most a second for the other cpus to stop */
0865     while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
0866         mdelay(1);
0867         msecs--;
0868     }
0869 
0870     /* Leave the nmi callback set */
0871 }
0872 
0873 /*
0874  * Check if the crash dumping IPI got issued and if so, call its callback
0875  * directly. This function is used when we have already been in NMI handler.
0876  * It doesn't return.
0877  */
0878 void run_crash_ipi_callback(struct pt_regs *regs)
0879 {
0880     if (crash_ipi_issued)
0881         crash_nmi_callback(0, regs);
0882 }
0883 
0884 /* Override the weak function in kernel/panic.c */
0885 void nmi_panic_self_stop(struct pt_regs *regs)
0886 {
0887     while (1) {
0888         /* If no CPU is preparing crash dump, we simply loop here. */
0889         run_crash_ipi_callback(regs);
0890         cpu_relax();
0891     }
0892 }
0893 
0894 #else /* !CONFIG_SMP */
0895 void nmi_shootdown_cpus(nmi_shootdown_cb callback)
0896 {
0897     /* No other CPUs to shoot down */
0898 }
0899 
0900 void run_crash_ipi_callback(struct pt_regs *regs)
0901 {
0902 }
0903 #endif