xref: /linux/arch/x86/kernel/reboot.c (revision d176720d34c72f7a8474a12204add93e54fe3ef1)
14d022e35SMiguel Boton #include <linux/module.h>
24d022e35SMiguel Boton #include <linux/reboot.h>
34d022e35SMiguel Boton #include <linux/init.h>
44d022e35SMiguel Boton #include <linux/pm.h>
54d022e35SMiguel Boton #include <linux/efi.h>
64d022e35SMiguel Boton #include <acpi/reboot.h>
74d022e35SMiguel Boton #include <asm/io.h>
84d022e35SMiguel Boton #include <asm/apic.h>
94d022e35SMiguel Boton #include <asm/desc.h>
104d022e35SMiguel Boton #include <asm/hpet.h>
1168db065cSJeremy Fitzhardinge #include <asm/pgtable.h>
124412620fSDmitri Vorobiev #include <asm/proto.h>
134d022e35SMiguel Boton #include <asm/reboot_fixups.h>
144d022e35SMiguel Boton #include <asm/reboot.h>
15*d176720dSEduardo Habkost #include <asm/virtext.h>
164d022e35SMiguel Boton 
174d022e35SMiguel Boton #ifdef CONFIG_X86_32
184d022e35SMiguel Boton # include <linux/dmi.h>
194d022e35SMiguel Boton # include <linux/ctype.h>
204d022e35SMiguel Boton # include <linux/mc146818rtc.h>
214d022e35SMiguel Boton #else
224d022e35SMiguel Boton # include <asm/iommu.h>
234d022e35SMiguel Boton #endif
244d022e35SMiguel Boton 
252ddded21SEduardo Habkost #include <mach_ipi.h>
262ddded21SEduardo Habkost 
272ddded21SEduardo Habkost 
284d022e35SMiguel Boton /*
294d022e35SMiguel Boton  * Power off function, if any
304d022e35SMiguel Boton  */
314d022e35SMiguel Boton void (*pm_power_off)(void);
324d022e35SMiguel Boton EXPORT_SYMBOL(pm_power_off);
334d022e35SMiguel Boton 
34ebdd561aSJan Beulich static const struct desc_ptr no_idt = {};
354d022e35SMiguel Boton static int reboot_mode;
368d00450dSEduardo Habkost enum reboot_type reboot_type = BOOT_KBD;
374d022e35SMiguel Boton int reboot_force;
384d022e35SMiguel Boton 
394d022e35SMiguel Boton #if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
404d022e35SMiguel Boton static int reboot_cpu = -1;
414d022e35SMiguel Boton #endif
424d022e35SMiguel Boton 
43*d176720dSEduardo Habkost /* This is set if we need to go through the 'emergency' path.
44*d176720dSEduardo Habkost  * When machine_emergency_restart() is called, we may be on
45*d176720dSEduardo Habkost  * an inconsistent state and won't be able to do a clean cleanup
46*d176720dSEduardo Habkost  */
47*d176720dSEduardo Habkost static int reboot_emergency;
48*d176720dSEduardo Habkost 
4914d7ca5cSH. Peter Anvin /* This is set by the PCI code if either type 1 or type 2 PCI is detected */
5014d7ca5cSH. Peter Anvin bool port_cf9_safe = false;
5114d7ca5cSH. Peter Anvin 
5214d7ca5cSH. Peter Anvin /* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci]
534d022e35SMiguel Boton    warm   Don't set the cold reboot flag
544d022e35SMiguel Boton    cold   Set the cold reboot flag
554d022e35SMiguel Boton    bios   Reboot by jumping through the BIOS (only for X86_32)
564d022e35SMiguel Boton    smp    Reboot by executing reset on BSP or other CPU (only for X86_32)
574d022e35SMiguel Boton    triple Force a triple fault (init)
584d022e35SMiguel Boton    kbd    Use the keyboard controller. cold reset (default)
594d022e35SMiguel Boton    acpi   Use the RESET_REG in the FADT
604d022e35SMiguel Boton    efi    Use efi reset_system runtime service
6114d7ca5cSH. Peter Anvin    pci    Use the so-called "PCI reset register", CF9
624d022e35SMiguel Boton    force  Avoid anything that could hang.
634d022e35SMiguel Boton  */
644d022e35SMiguel Boton static int __init reboot_setup(char *str)
654d022e35SMiguel Boton {
664d022e35SMiguel Boton 	for (;;) {
674d022e35SMiguel Boton 		switch (*str) {
684d022e35SMiguel Boton 		case 'w':
694d022e35SMiguel Boton 			reboot_mode = 0x1234;
704d022e35SMiguel Boton 			break;
714d022e35SMiguel Boton 
724d022e35SMiguel Boton 		case 'c':
734d022e35SMiguel Boton 			reboot_mode = 0;
744d022e35SMiguel Boton 			break;
754d022e35SMiguel Boton 
764d022e35SMiguel Boton #ifdef CONFIG_X86_32
774d022e35SMiguel Boton #ifdef CONFIG_SMP
784d022e35SMiguel Boton 		case 's':
794d022e35SMiguel Boton 			if (isdigit(*(str+1))) {
804d022e35SMiguel Boton 				reboot_cpu = (int) (*(str+1) - '0');
814d022e35SMiguel Boton 				if (isdigit(*(str+2)))
824d022e35SMiguel Boton 					reboot_cpu = reboot_cpu*10 + (int)(*(str+2) - '0');
834d022e35SMiguel Boton 			}
844d022e35SMiguel Boton 				/* we will leave sorting out the final value
854d022e35SMiguel Boton 				   when we are ready to reboot, since we might not
864d022e35SMiguel Boton 				   have set up boot_cpu_id or smp_num_cpu */
874d022e35SMiguel Boton 			break;
884d022e35SMiguel Boton #endif /* CONFIG_SMP */
894d022e35SMiguel Boton 
904d022e35SMiguel Boton 		case 'b':
914d022e35SMiguel Boton #endif
924d022e35SMiguel Boton 		case 'a':
934d022e35SMiguel Boton 		case 'k':
944d022e35SMiguel Boton 		case 't':
954d022e35SMiguel Boton 		case 'e':
9614d7ca5cSH. Peter Anvin 		case 'p':
974d022e35SMiguel Boton 			reboot_type = *str;
984d022e35SMiguel Boton 			break;
994d022e35SMiguel Boton 
1004d022e35SMiguel Boton 		case 'f':
1014d022e35SMiguel Boton 			reboot_force = 1;
1024d022e35SMiguel Boton 			break;
1034d022e35SMiguel Boton 		}
1044d022e35SMiguel Boton 
1054d022e35SMiguel Boton 		str = strchr(str, ',');
1064d022e35SMiguel Boton 		if (str)
1074d022e35SMiguel Boton 			str++;
1084d022e35SMiguel Boton 		else
1094d022e35SMiguel Boton 			break;
1104d022e35SMiguel Boton 	}
1114d022e35SMiguel Boton 	return 1;
1124d022e35SMiguel Boton }
1134d022e35SMiguel Boton 
1144d022e35SMiguel Boton __setup("reboot=", reboot_setup);
1154d022e35SMiguel Boton 
1164d022e35SMiguel Boton 
1174d022e35SMiguel Boton #ifdef CONFIG_X86_32
1184d022e35SMiguel Boton /*
1194d022e35SMiguel Boton  * Reboot options and system auto-detection code provided by
1204d022e35SMiguel Boton  * Dell Inc. so their systems "just work". :-)
1214d022e35SMiguel Boton  */
1224d022e35SMiguel Boton 
1234d022e35SMiguel Boton /*
1244d022e35SMiguel Boton  * Some machines require the "reboot=b"  commandline option,
1254d022e35SMiguel Boton  * this quirk makes that automatic.
1264d022e35SMiguel Boton  */
1274d022e35SMiguel Boton static int __init set_bios_reboot(const struct dmi_system_id *d)
1284d022e35SMiguel Boton {
1294d022e35SMiguel Boton 	if (reboot_type != BOOT_BIOS) {
1304d022e35SMiguel Boton 		reboot_type = BOOT_BIOS;
1314d022e35SMiguel Boton 		printk(KERN_INFO "%s series board detected. Selecting BIOS-method for reboots.\n", d->ident);
1324d022e35SMiguel Boton 	}
1334d022e35SMiguel Boton 	return 0;
1344d022e35SMiguel Boton }
1354d022e35SMiguel Boton 
1364d022e35SMiguel Boton static struct dmi_system_id __initdata reboot_dmi_table[] = {
1374d022e35SMiguel Boton 	{	/* Handle problems with rebooting on Dell E520's */
1384d022e35SMiguel Boton 		.callback = set_bios_reboot,
1394d022e35SMiguel Boton 		.ident = "Dell E520",
1404d022e35SMiguel Boton 		.matches = {
1414d022e35SMiguel Boton 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
1424d022e35SMiguel Boton 			DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM061"),
1434d022e35SMiguel Boton 		},
1444d022e35SMiguel Boton 	},
1454d022e35SMiguel Boton 	{	/* Handle problems with rebooting on Dell 1300's */
1464d022e35SMiguel Boton 		.callback = set_bios_reboot,
1474d022e35SMiguel Boton 		.ident = "Dell PowerEdge 1300",
1484d022e35SMiguel Boton 		.matches = {
1494d022e35SMiguel Boton 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
1504d022e35SMiguel Boton 			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
1514d022e35SMiguel Boton 		},
1524d022e35SMiguel Boton 	},
1534d022e35SMiguel Boton 	{	/* Handle problems with rebooting on Dell 300's */
1544d022e35SMiguel Boton 		.callback = set_bios_reboot,
1554d022e35SMiguel Boton 		.ident = "Dell PowerEdge 300",
1564d022e35SMiguel Boton 		.matches = {
1574d022e35SMiguel Boton 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
1584d022e35SMiguel Boton 			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
1594d022e35SMiguel Boton 		},
1604d022e35SMiguel Boton 	},
1614d022e35SMiguel Boton 	{       /* Handle problems with rebooting on Dell Optiplex 745's SFF*/
1624d022e35SMiguel Boton 		.callback = set_bios_reboot,
1634d022e35SMiguel Boton 		.ident = "Dell OptiPlex 745",
1644d022e35SMiguel Boton 		.matches = {
1654d022e35SMiguel Boton 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
1664d022e35SMiguel Boton 			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
1674d022e35SMiguel Boton 		},
1684d022e35SMiguel Boton 	},
169fc115bf1SColeman Kane 	{       /* Handle problems with rebooting on Dell Optiplex 745's DFF*/
170fc115bf1SColeman Kane 		.callback = set_bios_reboot,
171fc115bf1SColeman Kane 		.ident = "Dell OptiPlex 745",
172fc115bf1SColeman Kane 		.matches = {
173fc115bf1SColeman Kane 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
174fc115bf1SColeman Kane 			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
175fc115bf1SColeman Kane 			DMI_MATCH(DMI_BOARD_NAME, "0MM599"),
176fc115bf1SColeman Kane 		},
177fc115bf1SColeman Kane 	},
178fc1c8925SHeinz-Ado Arnolds 	{       /* Handle problems with rebooting on Dell Optiplex 745 with 0KW626 */
179fc1c8925SHeinz-Ado Arnolds 		.callback = set_bios_reboot,
180fc1c8925SHeinz-Ado Arnolds 		.ident = "Dell OptiPlex 745",
181fc1c8925SHeinz-Ado Arnolds 		.matches = {
182fc1c8925SHeinz-Ado Arnolds 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
183fc1c8925SHeinz-Ado Arnolds 			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
184fc1c8925SHeinz-Ado Arnolds 			DMI_MATCH(DMI_BOARD_NAME, "0KW626"),
185fc1c8925SHeinz-Ado Arnolds 		},
186fc1c8925SHeinz-Ado Arnolds 	},
187093bac15SSteve Conklin 	{   /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */
188093bac15SSteve Conklin 		.callback = set_bios_reboot,
189093bac15SSteve Conklin 		.ident = "Dell OptiPlex 330",
190093bac15SSteve Conklin 		.matches = {
191093bac15SSteve Conklin 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
192093bac15SSteve Conklin 			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 330"),
193093bac15SSteve Conklin 			DMI_MATCH(DMI_BOARD_NAME, "0KP561"),
194093bac15SSteve Conklin 		},
195093bac15SSteve Conklin 	},
1964d022e35SMiguel Boton 	{	/* Handle problems with rebooting on Dell 2400's */
1974d022e35SMiguel Boton 		.callback = set_bios_reboot,
1984d022e35SMiguel Boton 		.ident = "Dell PowerEdge 2400",
1994d022e35SMiguel Boton 		.matches = {
2004d022e35SMiguel Boton 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2014d022e35SMiguel Boton 			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
2024d022e35SMiguel Boton 		},
2034d022e35SMiguel Boton 	},
204fab3b58dSIngo Molnar 	{	/* Handle problems with rebooting on Dell T5400's */
205fab3b58dSIngo Molnar 		.callback = set_bios_reboot,
206fab3b58dSIngo Molnar 		.ident = "Dell Precision T5400",
207fab3b58dSIngo Molnar 		.matches = {
208fab3b58dSIngo Molnar 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
209fab3b58dSIngo Molnar 			DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"),
210fab3b58dSIngo Molnar 		},
211fab3b58dSIngo Molnar 	},
2124d022e35SMiguel Boton 	{	/* Handle problems with rebooting on HP laptops */
2134d022e35SMiguel Boton 		.callback = set_bios_reboot,
2144d022e35SMiguel Boton 		.ident = "HP Compaq Laptop",
2154d022e35SMiguel Boton 		.matches = {
2164d022e35SMiguel Boton 			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
2174d022e35SMiguel Boton 			DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"),
2184d022e35SMiguel Boton 		},
2194d022e35SMiguel Boton 	},
2204d022e35SMiguel Boton 	{ }
2214d022e35SMiguel Boton };
2224d022e35SMiguel Boton 
2234d022e35SMiguel Boton static int __init reboot_init(void)
2244d022e35SMiguel Boton {
2254d022e35SMiguel Boton 	dmi_check_system(reboot_dmi_table);
2264d022e35SMiguel Boton 	return 0;
2274d022e35SMiguel Boton }
2284d022e35SMiguel Boton core_initcall(reboot_init);
2294d022e35SMiguel Boton 
2304d022e35SMiguel Boton /* The following code and data reboots the machine by switching to real
2314d022e35SMiguel Boton    mode and jumping to the BIOS reset entry point, as if the CPU has
2324d022e35SMiguel Boton    really been reset.  The previous version asked the keyboard
2334d022e35SMiguel Boton    controller to pulse the CPU reset line, which is more thorough, but
2344d022e35SMiguel Boton    doesn't work with at least one type of 486 motherboard.  It is easy
2354d022e35SMiguel Boton    to stop this code working; hence the copious comments. */
236ebdd561aSJan Beulich static const unsigned long long
2374d022e35SMiguel Boton real_mode_gdt_entries [3] =
2384d022e35SMiguel Boton {
2394d022e35SMiguel Boton 	0x0000000000000000ULL,	/* Null descriptor */
240ebdd561aSJan Beulich 	0x00009b000000ffffULL,	/* 16-bit real-mode 64k code at 0x00000000 */
241ebdd561aSJan Beulich 	0x000093000100ffffULL	/* 16-bit real-mode 64k data at 0x00000100 */
2424d022e35SMiguel Boton };
2434d022e35SMiguel Boton 
244ebdd561aSJan Beulich static const struct desc_ptr
2454d022e35SMiguel Boton real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, (long)real_mode_gdt_entries },
2464d022e35SMiguel Boton real_mode_idt = { 0x3ff, 0 };
2474d022e35SMiguel Boton 
2484d022e35SMiguel Boton /* This is 16-bit protected mode code to disable paging and the cache,
2494d022e35SMiguel Boton    switch to real mode and jump to the BIOS reset code.
2504d022e35SMiguel Boton 
2514d022e35SMiguel Boton    The instruction that switches to real mode by writing to CR0 must be
2524d022e35SMiguel Boton    followed immediately by a far jump instruction, which set CS to a
2534d022e35SMiguel Boton    valid value for real mode, and flushes the prefetch queue to avoid
2544d022e35SMiguel Boton    running instructions that have already been decoded in protected
2554d022e35SMiguel Boton    mode.
2564d022e35SMiguel Boton 
2574d022e35SMiguel Boton    Clears all the flags except ET, especially PG (paging), PE
2584d022e35SMiguel Boton    (protected-mode enable) and TS (task switch for coprocessor state
2594d022e35SMiguel Boton    save).  Flushes the TLB after paging has been disabled.  Sets CD and
2604d022e35SMiguel Boton    NW, to disable the cache on a 486, and invalidates the cache.  This
2614d022e35SMiguel Boton    is more like the state of a 486 after reset.  I don't know if
2624d022e35SMiguel Boton    something else should be done for other chips.
2634d022e35SMiguel Boton 
2644d022e35SMiguel Boton    More could be done here to set up the registers as if a CPU reset had
2654d022e35SMiguel Boton    occurred; hopefully real BIOSs don't assume much. */
266ebdd561aSJan Beulich static const unsigned char real_mode_switch [] =
2674d022e35SMiguel Boton {
2684d022e35SMiguel Boton 	0x66, 0x0f, 0x20, 0xc0,			/*    movl  %cr0,%eax        */
2694d022e35SMiguel Boton 	0x66, 0x83, 0xe0, 0x11,			/*    andl  $0x00000011,%eax */
2704d022e35SMiguel Boton 	0x66, 0x0d, 0x00, 0x00, 0x00, 0x60,	/*    orl   $0x60000000,%eax */
2714d022e35SMiguel Boton 	0x66, 0x0f, 0x22, 0xc0,			/*    movl  %eax,%cr0        */
2724d022e35SMiguel Boton 	0x66, 0x0f, 0x22, 0xd8,			/*    movl  %eax,%cr3        */
2734d022e35SMiguel Boton 	0x66, 0x0f, 0x20, 0xc3,			/*    movl  %cr0,%ebx        */
2744d022e35SMiguel Boton 	0x66, 0x81, 0xe3, 0x00, 0x00, 0x00, 0x60,	/*    andl  $0x60000000,%ebx */
2754d022e35SMiguel Boton 	0x74, 0x02,				/*    jz    f                */
2764d022e35SMiguel Boton 	0x0f, 0x09,				/*    wbinvd                 */
2774d022e35SMiguel Boton 	0x24, 0x10,				/* f: andb  $0x10,al         */
2784d022e35SMiguel Boton 	0x66, 0x0f, 0x22, 0xc0			/*    movl  %eax,%cr0        */
2794d022e35SMiguel Boton };
280ebdd561aSJan Beulich static const unsigned char jump_to_bios [] =
2814d022e35SMiguel Boton {
2824d022e35SMiguel Boton 	0xea, 0x00, 0x00, 0xff, 0xff		/*    ljmp  $0xffff,$0x0000  */
2834d022e35SMiguel Boton };
2844d022e35SMiguel Boton 
2854d022e35SMiguel Boton /*
2864d022e35SMiguel Boton  * Switch to real mode and then execute the code
2874d022e35SMiguel Boton  * specified by the code and length parameters.
2884d022e35SMiguel Boton  * We assume that length will aways be less that 100!
2894d022e35SMiguel Boton  */
290ebdd561aSJan Beulich void machine_real_restart(const unsigned char *code, int length)
2914d022e35SMiguel Boton {
2924d022e35SMiguel Boton 	local_irq_disable();
2934d022e35SMiguel Boton 
2944d022e35SMiguel Boton 	/* Write zero to CMOS register number 0x0f, which the BIOS POST
2954d022e35SMiguel Boton 	   routine will recognize as telling it to do a proper reboot.  (Well
2964d022e35SMiguel Boton 	   that's what this book in front of me says -- it may only apply to
2974d022e35SMiguel Boton 	   the Phoenix BIOS though, it's not clear).  At the same time,
2984d022e35SMiguel Boton 	   disable NMIs by setting the top bit in the CMOS address register,
2994d022e35SMiguel Boton 	   as we're about to do peculiar things to the CPU.  I'm not sure if
3004d022e35SMiguel Boton 	   `outb_p' is needed instead of just `outb'.  Use it to be on the
3014d022e35SMiguel Boton 	   safe side.  (Yes, CMOS_WRITE does outb_p's. -  Paul G.)
3024d022e35SMiguel Boton 	 */
3034d022e35SMiguel Boton 	spin_lock(&rtc_lock);
3044d022e35SMiguel Boton 	CMOS_WRITE(0x00, 0x8f);
3054d022e35SMiguel Boton 	spin_unlock(&rtc_lock);
3064d022e35SMiguel Boton 
3074d022e35SMiguel Boton 	/* Remap the kernel at virtual address zero, as well as offset zero
3084d022e35SMiguel Boton 	   from the kernel segment.  This assumes the kernel segment starts at
3094d022e35SMiguel Boton 	   virtual address PAGE_OFFSET. */
31068db065cSJeremy Fitzhardinge 	memcpy(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
3114d022e35SMiguel Boton 		sizeof(swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
3124d022e35SMiguel Boton 
3134d022e35SMiguel Boton 	/*
3144d022e35SMiguel Boton 	 * Use `swapper_pg_dir' as our page directory.
3154d022e35SMiguel Boton 	 */
3164d022e35SMiguel Boton 	load_cr3(swapper_pg_dir);
3174d022e35SMiguel Boton 
3184d022e35SMiguel Boton 	/* Write 0x1234 to absolute memory location 0x472.  The BIOS reads
3194d022e35SMiguel Boton 	   this on booting to tell it to "Bypass memory test (also warm
3204d022e35SMiguel Boton 	   boot)".  This seems like a fairly standard thing that gets set by
3214d022e35SMiguel Boton 	   REBOOT.COM programs, and the previous reset routine did this
3224d022e35SMiguel Boton 	   too. */
3234d022e35SMiguel Boton 	*((unsigned short *)0x472) = reboot_mode;
3244d022e35SMiguel Boton 
3254d022e35SMiguel Boton 	/* For the switch to real mode, copy some code to low memory.  It has
3264d022e35SMiguel Boton 	   to be in the first 64k because it is running in 16-bit mode, and it
3274d022e35SMiguel Boton 	   has to have the same physical and virtual address, because it turns
3284d022e35SMiguel Boton 	   off paging.  Copy it near the end of the first page, out of the way
3294d022e35SMiguel Boton 	   of BIOS variables. */
3304d022e35SMiguel Boton 	memcpy((void *)(0x1000 - sizeof(real_mode_switch) - 100),
3314d022e35SMiguel Boton 		real_mode_switch, sizeof (real_mode_switch));
3324d022e35SMiguel Boton 	memcpy((void *)(0x1000 - 100), code, length);
3334d022e35SMiguel Boton 
3344d022e35SMiguel Boton 	/* Set up the IDT for real mode. */
3354d022e35SMiguel Boton 	load_idt(&real_mode_idt);
3364d022e35SMiguel Boton 
3374d022e35SMiguel Boton 	/* Set up a GDT from which we can load segment descriptors for real
3384d022e35SMiguel Boton 	   mode.  The GDT is not used in real mode; it is just needed here to
3394d022e35SMiguel Boton 	   prepare the descriptors. */
3404d022e35SMiguel Boton 	load_gdt(&real_mode_gdt);
3414d022e35SMiguel Boton 
3424d022e35SMiguel Boton 	/* Load the data segment registers, and thus the descriptors ready for
3434d022e35SMiguel Boton 	   real mode.  The base address of each segment is 0x100, 16 times the
3444d022e35SMiguel Boton 	   selector value being loaded here.  This is so that the segment
3454d022e35SMiguel Boton 	   registers don't have to be reloaded after switching to real mode:
3464d022e35SMiguel Boton 	   the values are consistent for real mode operation already. */
3474d022e35SMiguel Boton 	__asm__ __volatile__ ("movl $0x0010,%%eax\n"
3484d022e35SMiguel Boton 				"\tmovl %%eax,%%ds\n"
3494d022e35SMiguel Boton 				"\tmovl %%eax,%%es\n"
3504d022e35SMiguel Boton 				"\tmovl %%eax,%%fs\n"
3514d022e35SMiguel Boton 				"\tmovl %%eax,%%gs\n"
3524d022e35SMiguel Boton 				"\tmovl %%eax,%%ss" : : : "eax");
3534d022e35SMiguel Boton 
3544d022e35SMiguel Boton 	/* Jump to the 16-bit code that we copied earlier.  It disables paging
3554d022e35SMiguel Boton 	   and the cache, switches to real mode, and jumps to the BIOS reset
3564d022e35SMiguel Boton 	   entry point. */
3574d022e35SMiguel Boton 	__asm__ __volatile__ ("ljmp $0x0008,%0"
3584d022e35SMiguel Boton 				:
3594d022e35SMiguel Boton 				: "i" ((void *)(0x1000 - sizeof (real_mode_switch) - 100)));
3604d022e35SMiguel Boton }
3614d022e35SMiguel Boton #ifdef CONFIG_APM_MODULE
3624d022e35SMiguel Boton EXPORT_SYMBOL(machine_real_restart);
3634d022e35SMiguel Boton #endif
3644d022e35SMiguel Boton 
3654d022e35SMiguel Boton #endif /* CONFIG_X86_32 */
3664d022e35SMiguel Boton 
3674d022e35SMiguel Boton static inline void kb_wait(void)
3684d022e35SMiguel Boton {
3694d022e35SMiguel Boton 	int i;
3704d022e35SMiguel Boton 
371c84d6af8SAlan Cox 	for (i = 0; i < 0x10000; i++) {
372c84d6af8SAlan Cox 		if ((inb(0x64) & 0x02) == 0)
3734d022e35SMiguel Boton 			break;
374c84d6af8SAlan Cox 		udelay(2);
375c84d6af8SAlan Cox 	}
3764d022e35SMiguel Boton }
3774d022e35SMiguel Boton 
378*d176720dSEduardo Habkost static void vmxoff_nmi(int cpu, struct die_args *args)
379*d176720dSEduardo Habkost {
380*d176720dSEduardo Habkost 	cpu_emergency_vmxoff();
381*d176720dSEduardo Habkost }
382*d176720dSEduardo Habkost 
383*d176720dSEduardo Habkost /* Use NMIs as IPIs to tell all CPUs to disable virtualization
384*d176720dSEduardo Habkost  */
385*d176720dSEduardo Habkost static void emergency_vmx_disable_all(void)
386*d176720dSEduardo Habkost {
387*d176720dSEduardo Habkost 	/* Just make sure we won't change CPUs while doing this */
388*d176720dSEduardo Habkost 	local_irq_disable();
389*d176720dSEduardo Habkost 
390*d176720dSEduardo Habkost 	/* We need to disable VMX on all CPUs before rebooting, otherwise
391*d176720dSEduardo Habkost 	 * we risk hanging up the machine, because the CPU ignore INIT
392*d176720dSEduardo Habkost 	 * signals when VMX is enabled.
393*d176720dSEduardo Habkost 	 *
394*d176720dSEduardo Habkost 	 * We can't take any locks and we may be on an inconsistent
395*d176720dSEduardo Habkost 	 * state, so we use NMIs as IPIs to tell the other CPUs to disable
396*d176720dSEduardo Habkost 	 * VMX and halt.
397*d176720dSEduardo Habkost 	 *
398*d176720dSEduardo Habkost 	 * For safety, we will avoid running the nmi_shootdown_cpus()
399*d176720dSEduardo Habkost 	 * stuff unnecessarily, but we don't have a way to check
400*d176720dSEduardo Habkost 	 * if other CPUs have VMX enabled. So we will call it only if the
401*d176720dSEduardo Habkost 	 * CPU we are running on has VMX enabled.
402*d176720dSEduardo Habkost 	 *
403*d176720dSEduardo Habkost 	 * We will miss cases where VMX is not enabled on all CPUs. This
404*d176720dSEduardo Habkost 	 * shouldn't do much harm because KVM always enable VMX on all
405*d176720dSEduardo Habkost 	 * CPUs anyway. But we can miss it on the small window where KVM
406*d176720dSEduardo Habkost 	 * is still enabling VMX.
407*d176720dSEduardo Habkost 	 */
408*d176720dSEduardo Habkost 	if (cpu_has_vmx() && cpu_vmx_enabled()) {
409*d176720dSEduardo Habkost 		/* Disable VMX on this CPU.
410*d176720dSEduardo Habkost 		 */
411*d176720dSEduardo Habkost 		cpu_vmxoff();
412*d176720dSEduardo Habkost 
413*d176720dSEduardo Habkost 		/* Halt and disable VMX on the other CPUs */
414*d176720dSEduardo Habkost 		nmi_shootdown_cpus(vmxoff_nmi);
415*d176720dSEduardo Habkost 
416*d176720dSEduardo Habkost 	}
417*d176720dSEduardo Habkost }
418*d176720dSEduardo Habkost 
419*d176720dSEduardo Habkost 
4207432d149SIngo Molnar void __attribute__((weak)) mach_reboot_fixups(void)
4217432d149SIngo Molnar {
4227432d149SIngo Molnar }
4237432d149SIngo Molnar 
424416e2d63SJody Belka static void native_machine_emergency_restart(void)
4254d022e35SMiguel Boton {
4264d022e35SMiguel Boton 	int i;
4274d022e35SMiguel Boton 
428*d176720dSEduardo Habkost 	if (reboot_emergency)
429*d176720dSEduardo Habkost 		emergency_vmx_disable_all();
430*d176720dSEduardo Habkost 
4314d022e35SMiguel Boton 	/* Tell the BIOS if we want cold or warm reboot */
4324d022e35SMiguel Boton 	*((unsigned short *)__va(0x472)) = reboot_mode;
4334d022e35SMiguel Boton 
4344d022e35SMiguel Boton 	for (;;) {
4354d022e35SMiguel Boton 		/* Could also try the reset bit in the Hammer NB */
4364d022e35SMiguel Boton 		switch (reboot_type) {
4374d022e35SMiguel Boton 		case BOOT_KBD:
4387432d149SIngo Molnar 			mach_reboot_fixups(); /* for board specific fixups */
4397432d149SIngo Molnar 
4404d022e35SMiguel Boton 			for (i = 0; i < 10; i++) {
4414d022e35SMiguel Boton 				kb_wait();
4424d022e35SMiguel Boton 				udelay(50);
4434d022e35SMiguel Boton 				outb(0xfe, 0x64); /* pulse reset low */
4444d022e35SMiguel Boton 				udelay(50);
4454d022e35SMiguel Boton 			}
4464d022e35SMiguel Boton 
4474d022e35SMiguel Boton 		case BOOT_TRIPLE:
448ebdd561aSJan Beulich 			load_idt(&no_idt);
4494d022e35SMiguel Boton 			__asm__ __volatile__("int3");
4504d022e35SMiguel Boton 
4514d022e35SMiguel Boton 			reboot_type = BOOT_KBD;
4524d022e35SMiguel Boton 			break;
4534d022e35SMiguel Boton 
4544d022e35SMiguel Boton #ifdef CONFIG_X86_32
4554d022e35SMiguel Boton 		case BOOT_BIOS:
4564d022e35SMiguel Boton 			machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
4574d022e35SMiguel Boton 
4584d022e35SMiguel Boton 			reboot_type = BOOT_KBD;
4594d022e35SMiguel Boton 			break;
4604d022e35SMiguel Boton #endif
4614d022e35SMiguel Boton 
4624d022e35SMiguel Boton 		case BOOT_ACPI:
4634d022e35SMiguel Boton 			acpi_reboot();
4644d022e35SMiguel Boton 			reboot_type = BOOT_KBD;
4654d022e35SMiguel Boton 			break;
4664d022e35SMiguel Boton 
4674d022e35SMiguel Boton 		case BOOT_EFI:
4684d022e35SMiguel Boton 			if (efi_enabled)
46914d7ca5cSH. Peter Anvin 				efi.reset_system(reboot_mode ?
47014d7ca5cSH. Peter Anvin 						 EFI_RESET_WARM :
47114d7ca5cSH. Peter Anvin 						 EFI_RESET_COLD,
4724d022e35SMiguel Boton 						 EFI_SUCCESS, 0, NULL);
473b47b9288SH. Peter Anvin 			reboot_type = BOOT_KBD;
47414d7ca5cSH. Peter Anvin 			break;
4754d022e35SMiguel Boton 
47614d7ca5cSH. Peter Anvin 		case BOOT_CF9:
47714d7ca5cSH. Peter Anvin 			port_cf9_safe = true;
47814d7ca5cSH. Peter Anvin 			/* fall through */
47914d7ca5cSH. Peter Anvin 
48014d7ca5cSH. Peter Anvin 		case BOOT_CF9_COND:
48114d7ca5cSH. Peter Anvin 			if (port_cf9_safe) {
48214d7ca5cSH. Peter Anvin 				u8 cf9 = inb(0xcf9) & ~6;
48314d7ca5cSH. Peter Anvin 				outb(cf9|2, 0xcf9); /* Request hard reset */
48414d7ca5cSH. Peter Anvin 				udelay(50);
48514d7ca5cSH. Peter Anvin 				outb(cf9|6, 0xcf9); /* Actually do the reset */
48614d7ca5cSH. Peter Anvin 				udelay(50);
48714d7ca5cSH. Peter Anvin 			}
4884d022e35SMiguel Boton 			reboot_type = BOOT_KBD;
4894d022e35SMiguel Boton 			break;
4904d022e35SMiguel Boton 		}
4914d022e35SMiguel Boton 	}
4924d022e35SMiguel Boton }
4934d022e35SMiguel Boton 
4943c62c625SGlauber Costa void native_machine_shutdown(void)
4954d022e35SMiguel Boton {
4964d022e35SMiguel Boton 	/* Stop the cpus and apics */
4974d022e35SMiguel Boton #ifdef CONFIG_SMP
4984d022e35SMiguel Boton 
4994d022e35SMiguel Boton 	/* The boot cpu is always logical cpu 0 */
50065c01184SMike Travis 	int reboot_cpu_id = 0;
5014d022e35SMiguel Boton 
5024d022e35SMiguel Boton #ifdef CONFIG_X86_32
5034d022e35SMiguel Boton 	/* See if there has been given a command line override */
5044d022e35SMiguel Boton 	if ((reboot_cpu != -1) && (reboot_cpu < NR_CPUS) &&
5050bc3cc03SMike Travis 		cpu_online(reboot_cpu))
5064d022e35SMiguel Boton 		reboot_cpu_id = reboot_cpu;
5074d022e35SMiguel Boton #endif
5084d022e35SMiguel Boton 
5094d022e35SMiguel Boton 	/* Make certain the cpu I'm about to reboot on is online */
5100bc3cc03SMike Travis 	if (!cpu_online(reboot_cpu_id))
5114d022e35SMiguel Boton 		reboot_cpu_id = smp_processor_id();
5124d022e35SMiguel Boton 
5134d022e35SMiguel Boton 	/* Make certain I only run on the appropriate processor */
5140bc3cc03SMike Travis 	set_cpus_allowed_ptr(current, &cpumask_of_cpu(reboot_cpu_id));
5154d022e35SMiguel Boton 
5164d022e35SMiguel Boton 	/* O.K Now that I'm on the appropriate processor,
5174d022e35SMiguel Boton 	 * stop all of the others.
5184d022e35SMiguel Boton 	 */
5194d022e35SMiguel Boton 	smp_send_stop();
5204d022e35SMiguel Boton #endif
5214d022e35SMiguel Boton 
5224d022e35SMiguel Boton 	lapic_shutdown();
5234d022e35SMiguel Boton 
5244d022e35SMiguel Boton #ifdef CONFIG_X86_IO_APIC
5254d022e35SMiguel Boton 	disable_IO_APIC();
5264d022e35SMiguel Boton #endif
5274d022e35SMiguel Boton 
5284d022e35SMiguel Boton #ifdef CONFIG_HPET_TIMER
5294d022e35SMiguel Boton 	hpet_disable();
5304d022e35SMiguel Boton #endif
5314d022e35SMiguel Boton 
5324d022e35SMiguel Boton #ifdef CONFIG_X86_64
5334d022e35SMiguel Boton 	pci_iommu_shutdown();
5344d022e35SMiguel Boton #endif
5354d022e35SMiguel Boton }
5364d022e35SMiguel Boton 
537*d176720dSEduardo Habkost static void __machine_emergency_restart(int emergency)
538*d176720dSEduardo Habkost {
539*d176720dSEduardo Habkost 	reboot_emergency = emergency;
540*d176720dSEduardo Habkost 	machine_ops.emergency_restart();
541*d176720dSEduardo Habkost }
542*d176720dSEduardo Habkost 
543416e2d63SJody Belka static void native_machine_restart(char *__unused)
5444d022e35SMiguel Boton {
5454d022e35SMiguel Boton 	printk("machine restart\n");
5464d022e35SMiguel Boton 
5474d022e35SMiguel Boton 	if (!reboot_force)
5484d022e35SMiguel Boton 		machine_shutdown();
549*d176720dSEduardo Habkost 	__machine_emergency_restart(0);
5504d022e35SMiguel Boton }
5514d022e35SMiguel Boton 
552416e2d63SJody Belka static void native_machine_halt(void)
5534d022e35SMiguel Boton {
554d3ec5caeSIvan Vecera 	/* stop other cpus and apics */
555d3ec5caeSIvan Vecera 	machine_shutdown();
556d3ec5caeSIvan Vecera 
557d3ec5caeSIvan Vecera 	/* stop this cpu */
558d3ec5caeSIvan Vecera 	stop_this_cpu(NULL);
5594d022e35SMiguel Boton }
5604d022e35SMiguel Boton 
561416e2d63SJody Belka static void native_machine_power_off(void)
5624d022e35SMiguel Boton {
5634d022e35SMiguel Boton 	if (pm_power_off) {
5644d022e35SMiguel Boton 		if (!reboot_force)
5654d022e35SMiguel Boton 			machine_shutdown();
5664d022e35SMiguel Boton 		pm_power_off();
5674d022e35SMiguel Boton 	}
5684d022e35SMiguel Boton }
5694d022e35SMiguel Boton 
5704d022e35SMiguel Boton struct machine_ops machine_ops = {
571416e2d63SJody Belka 	.power_off = native_machine_power_off,
572416e2d63SJody Belka 	.shutdown = native_machine_shutdown,
573416e2d63SJody Belka 	.emergency_restart = native_machine_emergency_restart,
574416e2d63SJody Belka 	.restart = native_machine_restart,
575ed23dc6fSGlauber Costa 	.halt = native_machine_halt,
576ed23dc6fSGlauber Costa #ifdef CONFIG_KEXEC
577ed23dc6fSGlauber Costa 	.crash_shutdown = native_machine_crash_shutdown,
578ed23dc6fSGlauber Costa #endif
5794d022e35SMiguel Boton };
580416e2d63SJody Belka 
581416e2d63SJody Belka void machine_power_off(void)
582416e2d63SJody Belka {
583416e2d63SJody Belka 	machine_ops.power_off();
584416e2d63SJody Belka }
585416e2d63SJody Belka 
586416e2d63SJody Belka void machine_shutdown(void)
587416e2d63SJody Belka {
588416e2d63SJody Belka 	machine_ops.shutdown();
589416e2d63SJody Belka }
590416e2d63SJody Belka 
591416e2d63SJody Belka void machine_emergency_restart(void)
592416e2d63SJody Belka {
593*d176720dSEduardo Habkost 	__machine_emergency_restart(1);
594416e2d63SJody Belka }
595416e2d63SJody Belka 
596416e2d63SJody Belka void machine_restart(char *cmd)
597416e2d63SJody Belka {
598416e2d63SJody Belka 	machine_ops.restart(cmd);
599416e2d63SJody Belka }
600416e2d63SJody Belka 
601416e2d63SJody Belka void machine_halt(void)
602416e2d63SJody Belka {
603416e2d63SJody Belka 	machine_ops.halt();
604416e2d63SJody Belka }
605416e2d63SJody Belka 
606ed23dc6fSGlauber Costa #ifdef CONFIG_KEXEC
607ed23dc6fSGlauber Costa void machine_crash_shutdown(struct pt_regs *regs)
608ed23dc6fSGlauber Costa {
609ed23dc6fSGlauber Costa 	machine_ops.crash_shutdown(regs);
610ed23dc6fSGlauber Costa }
611ed23dc6fSGlauber Costa #endif
6122ddded21SEduardo Habkost 
6132ddded21SEduardo Habkost 
614bb8dd270SEduardo Habkost #if defined(CONFIG_SMP)
6152ddded21SEduardo Habkost 
6162ddded21SEduardo Habkost /* This keeps a track of which one is crashing cpu. */
6172ddded21SEduardo Habkost static int crashing_cpu;
6182ddded21SEduardo Habkost static nmi_shootdown_cb shootdown_callback;
6192ddded21SEduardo Habkost 
6202ddded21SEduardo Habkost static atomic_t waiting_for_crash_ipi;
6212ddded21SEduardo Habkost 
6222ddded21SEduardo Habkost static int crash_nmi_callback(struct notifier_block *self,
6232ddded21SEduardo Habkost 			unsigned long val, void *data)
6242ddded21SEduardo Habkost {
6252ddded21SEduardo Habkost 	int cpu;
6262ddded21SEduardo Habkost 
6272ddded21SEduardo Habkost 	if (val != DIE_NMI_IPI)
6282ddded21SEduardo Habkost 		return NOTIFY_OK;
6292ddded21SEduardo Habkost 
6302ddded21SEduardo Habkost 	cpu = raw_smp_processor_id();
6312ddded21SEduardo Habkost 
6322ddded21SEduardo Habkost 	/* Don't do anything if this handler is invoked on crashing cpu.
6332ddded21SEduardo Habkost 	 * Otherwise, system will completely hang. Crashing cpu can get
6342ddded21SEduardo Habkost 	 * an NMI if system was initially booted with nmi_watchdog parameter.
6352ddded21SEduardo Habkost 	 */
6362ddded21SEduardo Habkost 	if (cpu == crashing_cpu)
6372ddded21SEduardo Habkost 		return NOTIFY_STOP;
6382ddded21SEduardo Habkost 	local_irq_disable();
6392ddded21SEduardo Habkost 
6402ddded21SEduardo Habkost 	shootdown_callback(cpu, (struct die_args *)data);
6412ddded21SEduardo Habkost 
6422ddded21SEduardo Habkost 	atomic_dec(&waiting_for_crash_ipi);
6432ddded21SEduardo Habkost 	/* Assume hlt works */
6442ddded21SEduardo Habkost 	halt();
6452ddded21SEduardo Habkost 	for (;;)
6462ddded21SEduardo Habkost 		cpu_relax();
6472ddded21SEduardo Habkost 
6482ddded21SEduardo Habkost 	return 1;
6492ddded21SEduardo Habkost }
6502ddded21SEduardo Habkost 
6512ddded21SEduardo Habkost static void smp_send_nmi_allbutself(void)
6522ddded21SEduardo Habkost {
6532ddded21SEduardo Habkost 	cpumask_t mask = cpu_online_map;
6542ddded21SEduardo Habkost 	cpu_clear(safe_smp_processor_id(), mask);
6552ddded21SEduardo Habkost 	if (!cpus_empty(mask))
6562ddded21SEduardo Habkost 		send_IPI_mask(mask, NMI_VECTOR);
6572ddded21SEduardo Habkost }
6582ddded21SEduardo Habkost 
6592ddded21SEduardo Habkost static struct notifier_block crash_nmi_nb = {
6602ddded21SEduardo Habkost 	.notifier_call = crash_nmi_callback,
6612ddded21SEduardo Habkost };
6622ddded21SEduardo Habkost 
663bb8dd270SEduardo Habkost /* Halt all other CPUs, calling the specified function on each of them
664bb8dd270SEduardo Habkost  *
665bb8dd270SEduardo Habkost  * This function can be used to halt all other CPUs on crash
666bb8dd270SEduardo Habkost  * or emergency reboot time. The function passed as parameter
667bb8dd270SEduardo Habkost  * will be called inside a NMI handler on all CPUs.
668bb8dd270SEduardo Habkost  */
6692ddded21SEduardo Habkost void nmi_shootdown_cpus(nmi_shootdown_cb callback)
6702ddded21SEduardo Habkost {
6712ddded21SEduardo Habkost 	unsigned long msecs;
672c415b3dcSEduardo Habkost 	local_irq_disable();
6732ddded21SEduardo Habkost 
6742ddded21SEduardo Habkost 	/* Make a note of crashing cpu. Will be used in NMI callback.*/
6752ddded21SEduardo Habkost 	crashing_cpu = safe_smp_processor_id();
6762ddded21SEduardo Habkost 
6772ddded21SEduardo Habkost 	shootdown_callback = callback;
6782ddded21SEduardo Habkost 
6792ddded21SEduardo Habkost 	atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
6802ddded21SEduardo Habkost 	/* Would it be better to replace the trap vector here? */
6812ddded21SEduardo Habkost 	if (register_die_notifier(&crash_nmi_nb))
6822ddded21SEduardo Habkost 		return;		/* return what? */
6832ddded21SEduardo Habkost 	/* Ensure the new callback function is set before sending
6842ddded21SEduardo Habkost 	 * out the NMI
6852ddded21SEduardo Habkost 	 */
6862ddded21SEduardo Habkost 	wmb();
6872ddded21SEduardo Habkost 
6882ddded21SEduardo Habkost 	smp_send_nmi_allbutself();
6892ddded21SEduardo Habkost 
6902ddded21SEduardo Habkost 	msecs = 1000; /* Wait at most a second for the other cpus to stop */
6912ddded21SEduardo Habkost 	while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
6922ddded21SEduardo Habkost 		mdelay(1);
6932ddded21SEduardo Habkost 		msecs--;
6942ddded21SEduardo Habkost 	}
6952ddded21SEduardo Habkost 
6962ddded21SEduardo Habkost 	/* Leave the nmi callback set */
6972ddded21SEduardo Habkost }
698bb8dd270SEduardo Habkost #else /* !CONFIG_SMP */
699bb8dd270SEduardo Habkost void nmi_shootdown_cpus(nmi_shootdown_cb callback)
700bb8dd270SEduardo Habkost {
701bb8dd270SEduardo Habkost 	/* No other CPUs to shoot down */
702bb8dd270SEduardo Habkost }
7032ddded21SEduardo Habkost #endif
704