xref: /linux/arch/x86/kernel/reboot.c (revision 4d022e35fd7e07c522c7863fee6f07e53cf3fc14)
1*4d022e35SMiguel Boton #include <linux/module.h>
2*4d022e35SMiguel Boton #include <linux/init.h>
3*4d022e35SMiguel Boton #include <linux/reboot.h>
4*4d022e35SMiguel Boton #include <linux/init.h>
5*4d022e35SMiguel Boton #include <linux/pm.h>
6*4d022e35SMiguel Boton #include <linux/efi.h>
7*4d022e35SMiguel Boton #include <acpi/reboot.h>
8*4d022e35SMiguel Boton #include <asm/io.h>
9*4d022e35SMiguel Boton #include <asm/apic.h>
10*4d022e35SMiguel Boton #include <asm/desc.h>
11*4d022e35SMiguel Boton #include <asm/hpet.h>
12*4d022e35SMiguel Boton #include <asm/reboot_fixups.h>
13*4d022e35SMiguel Boton #include <asm/reboot.h>
14*4d022e35SMiguel Boton 
15*4d022e35SMiguel Boton #ifdef CONFIG_X86_32
16*4d022e35SMiguel Boton # include <linux/dmi.h>
17*4d022e35SMiguel Boton # include <linux/ctype.h>
18*4d022e35SMiguel Boton # include <linux/mc146818rtc.h>
19*4d022e35SMiguel Boton # include <asm/pgtable.h>
20*4d022e35SMiguel Boton #else
21*4d022e35SMiguel Boton # include <asm/iommu.h>
22*4d022e35SMiguel Boton #endif
23*4d022e35SMiguel Boton 
24*4d022e35SMiguel Boton /*
25*4d022e35SMiguel Boton  * Power off function, if any
26*4d022e35SMiguel Boton  */
27*4d022e35SMiguel Boton void (*pm_power_off)(void);
28*4d022e35SMiguel Boton EXPORT_SYMBOL(pm_power_off);
29*4d022e35SMiguel Boton 
30*4d022e35SMiguel Boton static long no_idt[3];
31*4d022e35SMiguel Boton static int reboot_mode;
32*4d022e35SMiguel Boton enum reboot_type reboot_type = BOOT_KBD;
33*4d022e35SMiguel Boton int reboot_force;
34*4d022e35SMiguel Boton 
35*4d022e35SMiguel Boton #if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
36*4d022e35SMiguel Boton static int reboot_cpu = -1;
37*4d022e35SMiguel Boton #endif
38*4d022e35SMiguel Boton 
39*4d022e35SMiguel Boton /* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old]
40*4d022e35SMiguel Boton    warm   Don't set the cold reboot flag
41*4d022e35SMiguel Boton    cold   Set the cold reboot flag
42*4d022e35SMiguel Boton    bios   Reboot by jumping through the BIOS (only for X86_32)
43*4d022e35SMiguel Boton    smp    Reboot by executing reset on BSP or other CPU (only for X86_32)
44*4d022e35SMiguel Boton    triple Force a triple fault (init)
45*4d022e35SMiguel Boton    kbd    Use the keyboard controller. cold reset (default)
46*4d022e35SMiguel Boton    acpi   Use the RESET_REG in the FADT
47*4d022e35SMiguel Boton    efi    Use efi reset_system runtime service
48*4d022e35SMiguel Boton    force  Avoid anything that could hang.
49*4d022e35SMiguel Boton  */
50*4d022e35SMiguel Boton static int __init reboot_setup(char *str)
51*4d022e35SMiguel Boton {
52*4d022e35SMiguel Boton 	for (;;) {
53*4d022e35SMiguel Boton 		switch (*str) {
54*4d022e35SMiguel Boton 		case 'w':
55*4d022e35SMiguel Boton 			reboot_mode = 0x1234;
56*4d022e35SMiguel Boton 			break;
57*4d022e35SMiguel Boton 
58*4d022e35SMiguel Boton 		case 'c':
59*4d022e35SMiguel Boton 			reboot_mode = 0;
60*4d022e35SMiguel Boton 			break;
61*4d022e35SMiguel Boton 
62*4d022e35SMiguel Boton #ifdef CONFIG_X86_32
63*4d022e35SMiguel Boton #ifdef CONFIG_SMP
64*4d022e35SMiguel Boton 		case 's':
65*4d022e35SMiguel Boton 			if (isdigit(*(str+1))) {
66*4d022e35SMiguel Boton 				reboot_cpu = (int) (*(str+1) - '0');
67*4d022e35SMiguel Boton 				if (isdigit(*(str+2)))
68*4d022e35SMiguel Boton 					reboot_cpu = reboot_cpu*10 + (int)(*(str+2) - '0');
69*4d022e35SMiguel Boton 			}
70*4d022e35SMiguel Boton 				/* we will leave sorting out the final value
71*4d022e35SMiguel Boton 				   when we are ready to reboot, since we might not
72*4d022e35SMiguel Boton 				   have set up boot_cpu_id or smp_num_cpu */
73*4d022e35SMiguel Boton 			break;
74*4d022e35SMiguel Boton #endif /* CONFIG_SMP */
75*4d022e35SMiguel Boton 
76*4d022e35SMiguel Boton 		case 'b':
77*4d022e35SMiguel Boton #endif
78*4d022e35SMiguel Boton 		case 'a':
79*4d022e35SMiguel Boton 		case 'k':
80*4d022e35SMiguel Boton 		case 't':
81*4d022e35SMiguel Boton 		case 'e':
82*4d022e35SMiguel Boton 			reboot_type = *str;
83*4d022e35SMiguel Boton 			break;
84*4d022e35SMiguel Boton 
85*4d022e35SMiguel Boton 		case 'f':
86*4d022e35SMiguel Boton 			reboot_force = 1;
87*4d022e35SMiguel Boton 			break;
88*4d022e35SMiguel Boton 		}
89*4d022e35SMiguel Boton 
90*4d022e35SMiguel Boton 		str = strchr(str, ',');
91*4d022e35SMiguel Boton 		if (str)
92*4d022e35SMiguel Boton 			str++;
93*4d022e35SMiguel Boton 		else
94*4d022e35SMiguel Boton 			break;
95*4d022e35SMiguel Boton 	}
96*4d022e35SMiguel Boton 	return 1;
97*4d022e35SMiguel Boton }
98*4d022e35SMiguel Boton 
99*4d022e35SMiguel Boton __setup("reboot=", reboot_setup);
100*4d022e35SMiguel Boton 
101*4d022e35SMiguel Boton 
102*4d022e35SMiguel Boton #ifdef CONFIG_X86_32
103*4d022e35SMiguel Boton /*
104*4d022e35SMiguel Boton  * Reboot options and system auto-detection code provided by
105*4d022e35SMiguel Boton  * Dell Inc. so their systems "just work". :-)
106*4d022e35SMiguel Boton  */
107*4d022e35SMiguel Boton 
108*4d022e35SMiguel Boton /*
109*4d022e35SMiguel Boton  * Some machines require the "reboot=b"  commandline option,
110*4d022e35SMiguel Boton  * this quirk makes that automatic.
111*4d022e35SMiguel Boton  */
112*4d022e35SMiguel Boton static int __init set_bios_reboot(const struct dmi_system_id *d)
113*4d022e35SMiguel Boton {
114*4d022e35SMiguel Boton 	if (reboot_type != BOOT_BIOS) {
115*4d022e35SMiguel Boton 		reboot_type = BOOT_BIOS;
116*4d022e35SMiguel Boton 		printk(KERN_INFO "%s series board detected. Selecting BIOS-method for reboots.\n", d->ident);
117*4d022e35SMiguel Boton 	}
118*4d022e35SMiguel Boton 	return 0;
119*4d022e35SMiguel Boton }
120*4d022e35SMiguel Boton 
121*4d022e35SMiguel Boton static struct dmi_system_id __initdata reboot_dmi_table[] = {
122*4d022e35SMiguel Boton 	{	/* Handle problems with rebooting on Dell E520's */
123*4d022e35SMiguel Boton 		.callback = set_bios_reboot,
124*4d022e35SMiguel Boton 		.ident = "Dell E520",
125*4d022e35SMiguel Boton 		.matches = {
126*4d022e35SMiguel Boton 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
127*4d022e35SMiguel Boton 			DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM061"),
128*4d022e35SMiguel Boton 		},
129*4d022e35SMiguel Boton 	},
130*4d022e35SMiguel Boton 	{	/* Handle problems with rebooting on Dell 1300's */
131*4d022e35SMiguel Boton 		.callback = set_bios_reboot,
132*4d022e35SMiguel Boton 		.ident = "Dell PowerEdge 1300",
133*4d022e35SMiguel Boton 		.matches = {
134*4d022e35SMiguel Boton 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
135*4d022e35SMiguel Boton 			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
136*4d022e35SMiguel Boton 		},
137*4d022e35SMiguel Boton 	},
138*4d022e35SMiguel Boton 	{	/* Handle problems with rebooting on Dell 300's */
139*4d022e35SMiguel Boton 		.callback = set_bios_reboot,
140*4d022e35SMiguel Boton 		.ident = "Dell PowerEdge 300",
141*4d022e35SMiguel Boton 		.matches = {
142*4d022e35SMiguel Boton 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
143*4d022e35SMiguel Boton 			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
144*4d022e35SMiguel Boton 		},
145*4d022e35SMiguel Boton 	},
146*4d022e35SMiguel Boton 	{       /* Handle problems with rebooting on Dell Optiplex 745's SFF*/
147*4d022e35SMiguel Boton 		.callback = set_bios_reboot,
148*4d022e35SMiguel Boton 		.ident = "Dell OptiPlex 745",
149*4d022e35SMiguel Boton 		.matches = {
150*4d022e35SMiguel Boton 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
151*4d022e35SMiguel Boton 			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
152*4d022e35SMiguel Boton 			DMI_MATCH(DMI_BOARD_NAME, "0WF810"),
153*4d022e35SMiguel Boton 		},
154*4d022e35SMiguel Boton 	},
155*4d022e35SMiguel Boton 	{	/* Handle problems with rebooting on Dell 2400's */
156*4d022e35SMiguel Boton 		.callback = set_bios_reboot,
157*4d022e35SMiguel Boton 		.ident = "Dell PowerEdge 2400",
158*4d022e35SMiguel Boton 		.matches = {
159*4d022e35SMiguel Boton 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
160*4d022e35SMiguel Boton 			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
161*4d022e35SMiguel Boton 		},
162*4d022e35SMiguel Boton 	},
163*4d022e35SMiguel Boton 	{	/* Handle problems with rebooting on HP laptops */
164*4d022e35SMiguel Boton 		.callback = set_bios_reboot,
165*4d022e35SMiguel Boton 		.ident = "HP Compaq Laptop",
166*4d022e35SMiguel Boton 		.matches = {
167*4d022e35SMiguel Boton 			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
168*4d022e35SMiguel Boton 			DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"),
169*4d022e35SMiguel Boton 		},
170*4d022e35SMiguel Boton 	},
171*4d022e35SMiguel Boton 	{ }
172*4d022e35SMiguel Boton };
173*4d022e35SMiguel Boton 
174*4d022e35SMiguel Boton static int __init reboot_init(void)
175*4d022e35SMiguel Boton {
176*4d022e35SMiguel Boton 	dmi_check_system(reboot_dmi_table);
177*4d022e35SMiguel Boton 	return 0;
178*4d022e35SMiguel Boton }
179*4d022e35SMiguel Boton core_initcall(reboot_init);
180*4d022e35SMiguel Boton 
181*4d022e35SMiguel Boton /* The following code and data reboots the machine by switching to real
182*4d022e35SMiguel Boton    mode and jumping to the BIOS reset entry point, as if the CPU has
183*4d022e35SMiguel Boton    really been reset.  The previous version asked the keyboard
184*4d022e35SMiguel Boton    controller to pulse the CPU reset line, which is more thorough, but
185*4d022e35SMiguel Boton    doesn't work with at least one type of 486 motherboard.  It is easy
186*4d022e35SMiguel Boton    to stop this code working; hence the copious comments. */
187*4d022e35SMiguel Boton static unsigned long long
188*4d022e35SMiguel Boton real_mode_gdt_entries [3] =
189*4d022e35SMiguel Boton {
190*4d022e35SMiguel Boton 	0x0000000000000000ULL,	/* Null descriptor */
191*4d022e35SMiguel Boton 	0x00009a000000ffffULL,	/* 16-bit real-mode 64k code at 0x00000000 */
192*4d022e35SMiguel Boton 	0x000092000100ffffULL	/* 16-bit real-mode 64k data at 0x00000100 */
193*4d022e35SMiguel Boton };
194*4d022e35SMiguel Boton 
195*4d022e35SMiguel Boton static struct desc_ptr
196*4d022e35SMiguel Boton real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, (long)real_mode_gdt_entries },
197*4d022e35SMiguel Boton real_mode_idt = { 0x3ff, 0 };
198*4d022e35SMiguel Boton 
199*4d022e35SMiguel Boton /* This is 16-bit protected mode code to disable paging and the cache,
200*4d022e35SMiguel Boton    switch to real mode and jump to the BIOS reset code.
201*4d022e35SMiguel Boton 
202*4d022e35SMiguel Boton    The instruction that switches to real mode by writing to CR0 must be
203*4d022e35SMiguel Boton    followed immediately by a far jump instruction, which set CS to a
204*4d022e35SMiguel Boton    valid value for real mode, and flushes the prefetch queue to avoid
205*4d022e35SMiguel Boton    running instructions that have already been decoded in protected
206*4d022e35SMiguel Boton    mode.
207*4d022e35SMiguel Boton 
208*4d022e35SMiguel Boton    Clears all the flags except ET, especially PG (paging), PE
209*4d022e35SMiguel Boton    (protected-mode enable) and TS (task switch for coprocessor state
210*4d022e35SMiguel Boton    save).  Flushes the TLB after paging has been disabled.  Sets CD and
211*4d022e35SMiguel Boton    NW, to disable the cache on a 486, and invalidates the cache.  This
212*4d022e35SMiguel Boton    is more like the state of a 486 after reset.  I don't know if
213*4d022e35SMiguel Boton    something else should be done for other chips.
214*4d022e35SMiguel Boton 
215*4d022e35SMiguel Boton    More could be done here to set up the registers as if a CPU reset had
216*4d022e35SMiguel Boton    occurred; hopefully real BIOSs don't assume much. */
217*4d022e35SMiguel Boton static unsigned char real_mode_switch [] =
218*4d022e35SMiguel Boton {
219*4d022e35SMiguel Boton 	0x66, 0x0f, 0x20, 0xc0,			/*    movl  %cr0,%eax        */
220*4d022e35SMiguel Boton 	0x66, 0x83, 0xe0, 0x11,			/*    andl  $0x00000011,%eax */
221*4d022e35SMiguel Boton 	0x66, 0x0d, 0x00, 0x00, 0x00, 0x60,	/*    orl   $0x60000000,%eax */
222*4d022e35SMiguel Boton 	0x66, 0x0f, 0x22, 0xc0,			/*    movl  %eax,%cr0        */
223*4d022e35SMiguel Boton 	0x66, 0x0f, 0x22, 0xd8,			/*    movl  %eax,%cr3        */
224*4d022e35SMiguel Boton 	0x66, 0x0f, 0x20, 0xc3,			/*    movl  %cr0,%ebx        */
225*4d022e35SMiguel Boton 	0x66, 0x81, 0xe3, 0x00, 0x00, 0x00, 0x60,	/*    andl  $0x60000000,%ebx */
226*4d022e35SMiguel Boton 	0x74, 0x02,				/*    jz    f                */
227*4d022e35SMiguel Boton 	0x0f, 0x09,				/*    wbinvd                 */
228*4d022e35SMiguel Boton 	0x24, 0x10,				/* f: andb  $0x10,al         */
229*4d022e35SMiguel Boton 	0x66, 0x0f, 0x22, 0xc0			/*    movl  %eax,%cr0        */
230*4d022e35SMiguel Boton };
231*4d022e35SMiguel Boton static unsigned char jump_to_bios [] =
232*4d022e35SMiguel Boton {
233*4d022e35SMiguel Boton 	0xea, 0x00, 0x00, 0xff, 0xff		/*    ljmp  $0xffff,$0x0000  */
234*4d022e35SMiguel Boton };
235*4d022e35SMiguel Boton 
236*4d022e35SMiguel Boton /*
237*4d022e35SMiguel Boton  * Switch to real mode and then execute the code
238*4d022e35SMiguel Boton  * specified by the code and length parameters.
239*4d022e35SMiguel Boton  * We assume that length will aways be less that 100!
240*4d022e35SMiguel Boton  */
241*4d022e35SMiguel Boton void machine_real_restart(unsigned char *code, int length)
242*4d022e35SMiguel Boton {
243*4d022e35SMiguel Boton 	local_irq_disable();
244*4d022e35SMiguel Boton 
245*4d022e35SMiguel Boton 	/* Write zero to CMOS register number 0x0f, which the BIOS POST
246*4d022e35SMiguel Boton 	   routine will recognize as telling it to do a proper reboot.  (Well
247*4d022e35SMiguel Boton 	   that's what this book in front of me says -- it may only apply to
248*4d022e35SMiguel Boton 	   the Phoenix BIOS though, it's not clear).  At the same time,
249*4d022e35SMiguel Boton 	   disable NMIs by setting the top bit in the CMOS address register,
250*4d022e35SMiguel Boton 	   as we're about to do peculiar things to the CPU.  I'm not sure if
251*4d022e35SMiguel Boton 	   `outb_p' is needed instead of just `outb'.  Use it to be on the
252*4d022e35SMiguel Boton 	   safe side.  (Yes, CMOS_WRITE does outb_p's. -  Paul G.)
253*4d022e35SMiguel Boton 	 */
254*4d022e35SMiguel Boton 	spin_lock(&rtc_lock);
255*4d022e35SMiguel Boton 	CMOS_WRITE(0x00, 0x8f);
256*4d022e35SMiguel Boton 	spin_unlock(&rtc_lock);
257*4d022e35SMiguel Boton 
258*4d022e35SMiguel Boton 	/* Remap the kernel at virtual address zero, as well as offset zero
259*4d022e35SMiguel Boton 	   from the kernel segment.  This assumes the kernel segment starts at
260*4d022e35SMiguel Boton 	   virtual address PAGE_OFFSET. */
261*4d022e35SMiguel Boton 	memcpy(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
262*4d022e35SMiguel Boton 		sizeof(swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
263*4d022e35SMiguel Boton 
264*4d022e35SMiguel Boton 	/*
265*4d022e35SMiguel Boton 	 * Use `swapper_pg_dir' as our page directory.
266*4d022e35SMiguel Boton 	 */
267*4d022e35SMiguel Boton 	load_cr3(swapper_pg_dir);
268*4d022e35SMiguel Boton 
269*4d022e35SMiguel Boton 	/* Write 0x1234 to absolute memory location 0x472.  The BIOS reads
270*4d022e35SMiguel Boton 	   this on booting to tell it to "Bypass memory test (also warm
271*4d022e35SMiguel Boton 	   boot)".  This seems like a fairly standard thing that gets set by
272*4d022e35SMiguel Boton 	   REBOOT.COM programs, and the previous reset routine did this
273*4d022e35SMiguel Boton 	   too. */
274*4d022e35SMiguel Boton 	*((unsigned short *)0x472) = reboot_mode;
275*4d022e35SMiguel Boton 
276*4d022e35SMiguel Boton 	/* For the switch to real mode, copy some code to low memory.  It has
277*4d022e35SMiguel Boton 	   to be in the first 64k because it is running in 16-bit mode, and it
278*4d022e35SMiguel Boton 	   has to have the same physical and virtual address, because it turns
279*4d022e35SMiguel Boton 	   off paging.  Copy it near the end of the first page, out of the way
280*4d022e35SMiguel Boton 	   of BIOS variables. */
281*4d022e35SMiguel Boton 	memcpy((void *)(0x1000 - sizeof(real_mode_switch) - 100),
282*4d022e35SMiguel Boton 		real_mode_switch, sizeof (real_mode_switch));
283*4d022e35SMiguel Boton 	memcpy((void *)(0x1000 - 100), code, length);
284*4d022e35SMiguel Boton 
285*4d022e35SMiguel Boton 	/* Set up the IDT for real mode. */
286*4d022e35SMiguel Boton 	load_idt(&real_mode_idt);
287*4d022e35SMiguel Boton 
288*4d022e35SMiguel Boton 	/* Set up a GDT from which we can load segment descriptors for real
289*4d022e35SMiguel Boton 	   mode.  The GDT is not used in real mode; it is just needed here to
290*4d022e35SMiguel Boton 	   prepare the descriptors. */
291*4d022e35SMiguel Boton 	load_gdt(&real_mode_gdt);
292*4d022e35SMiguel Boton 
293*4d022e35SMiguel Boton 	/* Load the data segment registers, and thus the descriptors ready for
294*4d022e35SMiguel Boton 	   real mode.  The base address of each segment is 0x100, 16 times the
295*4d022e35SMiguel Boton 	   selector value being loaded here.  This is so that the segment
296*4d022e35SMiguel Boton 	   registers don't have to be reloaded after switching to real mode:
297*4d022e35SMiguel Boton 	   the values are consistent for real mode operation already. */
298*4d022e35SMiguel Boton 	__asm__ __volatile__ ("movl $0x0010,%%eax\n"
299*4d022e35SMiguel Boton 				"\tmovl %%eax,%%ds\n"
300*4d022e35SMiguel Boton 				"\tmovl %%eax,%%es\n"
301*4d022e35SMiguel Boton 				"\tmovl %%eax,%%fs\n"
302*4d022e35SMiguel Boton 				"\tmovl %%eax,%%gs\n"
303*4d022e35SMiguel Boton 				"\tmovl %%eax,%%ss" : : : "eax");
304*4d022e35SMiguel Boton 
305*4d022e35SMiguel Boton 	/* Jump to the 16-bit code that we copied earlier.  It disables paging
306*4d022e35SMiguel Boton 	   and the cache, switches to real mode, and jumps to the BIOS reset
307*4d022e35SMiguel Boton 	   entry point. */
308*4d022e35SMiguel Boton 	__asm__ __volatile__ ("ljmp $0x0008,%0"
309*4d022e35SMiguel Boton 				:
310*4d022e35SMiguel Boton 				: "i" ((void *)(0x1000 - sizeof (real_mode_switch) - 100)));
311*4d022e35SMiguel Boton }
312*4d022e35SMiguel Boton #ifdef CONFIG_APM_MODULE
313*4d022e35SMiguel Boton EXPORT_SYMBOL(machine_real_restart);
314*4d022e35SMiguel Boton #endif
315*4d022e35SMiguel Boton 
316*4d022e35SMiguel Boton #endif /* CONFIG_X86_32 */
317*4d022e35SMiguel Boton 
318*4d022e35SMiguel Boton static inline void kb_wait(void)
319*4d022e35SMiguel Boton {
320*4d022e35SMiguel Boton 	int i;
321*4d022e35SMiguel Boton 
322*4d022e35SMiguel Boton 	for (i = 0; i < 0x10000; i++)
323*4d022e35SMiguel Boton 		if ((inb_p(0x64) & 0x02) == 0)
324*4d022e35SMiguel Boton 			break;
325*4d022e35SMiguel Boton }
326*4d022e35SMiguel Boton 
327*4d022e35SMiguel Boton void machine_emergency_restart(void)
328*4d022e35SMiguel Boton {
329*4d022e35SMiguel Boton 	int i;
330*4d022e35SMiguel Boton 
331*4d022e35SMiguel Boton 	/* Tell the BIOS if we want cold or warm reboot */
332*4d022e35SMiguel Boton 	*((unsigned short *)__va(0x472)) = reboot_mode;
333*4d022e35SMiguel Boton 
334*4d022e35SMiguel Boton 	for (;;) {
335*4d022e35SMiguel Boton 		/* Could also try the reset bit in the Hammer NB */
336*4d022e35SMiguel Boton 		switch (reboot_type) {
337*4d022e35SMiguel Boton 		case BOOT_KBD:
338*4d022e35SMiguel Boton 			for (i = 0; i < 10; i++) {
339*4d022e35SMiguel Boton 				kb_wait();
340*4d022e35SMiguel Boton 				udelay(50);
341*4d022e35SMiguel Boton 				outb(0xfe, 0x64); /* pulse reset low */
342*4d022e35SMiguel Boton 				udelay(50);
343*4d022e35SMiguel Boton 			}
344*4d022e35SMiguel Boton 
345*4d022e35SMiguel Boton 		case BOOT_TRIPLE:
346*4d022e35SMiguel Boton 			load_idt((const struct desc_ptr *)&no_idt);
347*4d022e35SMiguel Boton 			__asm__ __volatile__("int3");
348*4d022e35SMiguel Boton 
349*4d022e35SMiguel Boton 			reboot_type = BOOT_KBD;
350*4d022e35SMiguel Boton 			break;
351*4d022e35SMiguel Boton 
352*4d022e35SMiguel Boton #ifdef CONFIG_X86_32
353*4d022e35SMiguel Boton 		case BOOT_BIOS:
354*4d022e35SMiguel Boton 			machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
355*4d022e35SMiguel Boton 
356*4d022e35SMiguel Boton 			reboot_type = BOOT_KBD;
357*4d022e35SMiguel Boton 			break;
358*4d022e35SMiguel Boton #endif
359*4d022e35SMiguel Boton 
360*4d022e35SMiguel Boton 		case BOOT_ACPI:
361*4d022e35SMiguel Boton 			acpi_reboot();
362*4d022e35SMiguel Boton 			reboot_type = BOOT_KBD;
363*4d022e35SMiguel Boton 			break;
364*4d022e35SMiguel Boton 
365*4d022e35SMiguel Boton 
366*4d022e35SMiguel Boton 		case BOOT_EFI:
367*4d022e35SMiguel Boton 			if (efi_enabled)
368*4d022e35SMiguel Boton 				efi.reset_system(reboot_mode ? EFI_RESET_WARM : EFI_RESET_COLD,
369*4d022e35SMiguel Boton 						 EFI_SUCCESS, 0, NULL);
370*4d022e35SMiguel Boton 
371*4d022e35SMiguel Boton 			reboot_type = BOOT_KBD;
372*4d022e35SMiguel Boton 			break;
373*4d022e35SMiguel Boton 		}
374*4d022e35SMiguel Boton 	}
375*4d022e35SMiguel Boton }
376*4d022e35SMiguel Boton 
377*4d022e35SMiguel Boton void machine_shutdown(void)
378*4d022e35SMiguel Boton {
379*4d022e35SMiguel Boton 	/* Stop the cpus and apics */
380*4d022e35SMiguel Boton #ifdef CONFIG_SMP
381*4d022e35SMiguel Boton 	int reboot_cpu_id;
382*4d022e35SMiguel Boton 
383*4d022e35SMiguel Boton 	/* The boot cpu is always logical cpu 0 */
384*4d022e35SMiguel Boton 	reboot_cpu_id = 0;
385*4d022e35SMiguel Boton 
386*4d022e35SMiguel Boton #ifdef CONFIG_X86_32
387*4d022e35SMiguel Boton 	/* See if there has been given a command line override */
388*4d022e35SMiguel Boton 	if ((reboot_cpu != -1) && (reboot_cpu < NR_CPUS) &&
389*4d022e35SMiguel Boton 		cpu_isset(reboot_cpu, cpu_online_map))
390*4d022e35SMiguel Boton 		reboot_cpu_id = reboot_cpu;
391*4d022e35SMiguel Boton #endif
392*4d022e35SMiguel Boton 
393*4d022e35SMiguel Boton 	/* Make certain the cpu I'm about to reboot on is online */
394*4d022e35SMiguel Boton 	if (!cpu_isset(reboot_cpu_id, cpu_online_map))
395*4d022e35SMiguel Boton 		reboot_cpu_id = smp_processor_id();
396*4d022e35SMiguel Boton 
397*4d022e35SMiguel Boton 	/* Make certain I only run on the appropriate processor */
398*4d022e35SMiguel Boton 	set_cpus_allowed(current, cpumask_of_cpu(reboot_cpu_id));
399*4d022e35SMiguel Boton 
400*4d022e35SMiguel Boton 	/* O.K Now that I'm on the appropriate processor,
401*4d022e35SMiguel Boton 	 * stop all of the others.
402*4d022e35SMiguel Boton 	 */
403*4d022e35SMiguel Boton 	smp_send_stop();
404*4d022e35SMiguel Boton #endif
405*4d022e35SMiguel Boton 
406*4d022e35SMiguel Boton 	lapic_shutdown();
407*4d022e35SMiguel Boton 
408*4d022e35SMiguel Boton #ifdef CONFIG_X86_IO_APIC
409*4d022e35SMiguel Boton 	disable_IO_APIC();
410*4d022e35SMiguel Boton #endif
411*4d022e35SMiguel Boton 
412*4d022e35SMiguel Boton #ifdef CONFIG_HPET_TIMER
413*4d022e35SMiguel Boton 	hpet_disable();
414*4d022e35SMiguel Boton #endif
415*4d022e35SMiguel Boton 
416*4d022e35SMiguel Boton #ifdef CONFIG_X86_64
417*4d022e35SMiguel Boton 	pci_iommu_shutdown();
418*4d022e35SMiguel Boton #endif
419*4d022e35SMiguel Boton }
420*4d022e35SMiguel Boton 
421*4d022e35SMiguel Boton void machine_restart(char *__unused)
422*4d022e35SMiguel Boton {
423*4d022e35SMiguel Boton 	printk("machine restart\n");
424*4d022e35SMiguel Boton 
425*4d022e35SMiguel Boton 	if (!reboot_force)
426*4d022e35SMiguel Boton 		machine_shutdown();
427*4d022e35SMiguel Boton 	machine_emergency_restart();
428*4d022e35SMiguel Boton }
429*4d022e35SMiguel Boton 
430*4d022e35SMiguel Boton void machine_halt(void)
431*4d022e35SMiguel Boton {
432*4d022e35SMiguel Boton }
433*4d022e35SMiguel Boton 
434*4d022e35SMiguel Boton void machine_power_off(void)
435*4d022e35SMiguel Boton {
436*4d022e35SMiguel Boton 	if (pm_power_off) {
437*4d022e35SMiguel Boton 		if (!reboot_force)
438*4d022e35SMiguel Boton 			machine_shutdown();
439*4d022e35SMiguel Boton 		pm_power_off();
440*4d022e35SMiguel Boton 	}
441*4d022e35SMiguel Boton }
442*4d022e35SMiguel Boton 
443*4d022e35SMiguel Boton struct machine_ops machine_ops = {
444*4d022e35SMiguel Boton 	.power_off = machine_power_off,
445*4d022e35SMiguel Boton 	.shutdown = machine_shutdown,
446*4d022e35SMiguel Boton 	.emergency_restart = machine_emergency_restart,
447*4d022e35SMiguel Boton 	.restart = machine_restart,
448*4d022e35SMiguel Boton 	.halt = machine_halt
449*4d022e35SMiguel Boton };
450