LCOV - code coverage report
Current view: top level - arch/x86/kernel - reboot.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 4 161 2.5 %
Date: 2021-04-22 12:43:58 Functions: 1 20 5.0 %

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

Generated by: LCOV version 1.14