aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2012-06-17 00:47:37 -0400
committerH. Peter Anvin <hpa@zytor.com>2012-06-17 13:51:01 -0400
commit650513979a437c32d7a0a84f0ed952a55bbb5583 (patch)
treeb831bcbfdfce6abb31573e67669272f368626b5b /arch/x86/kernel
parentcfaf025112d3856637ff34a767ef785ef5cf2ca9 (diff)
x86-64, reboot: Allow reboot=bios and reboot-cpu override on x86-64
With the revamped realmode trampoline code, it is trivial to extend support for reboot=bios to x86-64. Furthermore, while we are at it, remove the restriction that only we can only override the reboot CPU on 32 bits. Signed-off-by: H. Peter Anvin <hpa@zytor.com> Link: http://lkml.kernel.org/n/tip-jopx7y6g6dbcx4tpal8q0jlr@git.kernel.org
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/reboot.c52
1 files changed, 24 insertions, 28 deletions
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 25b48edb847..6ddb9cd0ced 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -20,14 +20,12 @@
20#include <asm/virtext.h> 20#include <asm/virtext.h>
21#include <asm/cpu.h> 21#include <asm/cpu.h>
22#include <asm/nmi.h> 22#include <asm/nmi.h>
23#include <asm/smp.h>
23 24
24#ifdef CONFIG_X86_32 25#include <linux/ctype.h>
25# include <linux/ctype.h> 26#include <linux/mc146818rtc.h>
26# include <linux/mc146818rtc.h> 27#include <asm/realmode.h>
27# include <asm/realmode.h> 28#include <asm/x86_init.h>
28#else
29# include <asm/x86_init.h>
30#endif
31 29
32/* 30/*
33 * Power off function, if any 31 * Power off function, if any
@@ -49,7 +47,7 @@ int reboot_force;
49 */ 47 */
50static int reboot_default = 1; 48static int reboot_default = 1;
51 49
52#if defined(CONFIG_X86_32) && defined(CONFIG_SMP) 50#ifdef CONFIG_SMP
53static int reboot_cpu = -1; 51static int reboot_cpu = -1;
54#endif 52#endif
55 53
@@ -67,8 +65,8 @@ bool port_cf9_safe = false;
67 * reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci] 65 * reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci]
68 * warm Don't set the cold reboot flag 66 * warm Don't set the cold reboot flag
69 * cold Set the cold reboot flag 67 * cold Set the cold reboot flag
70 * bios Reboot by jumping through the BIOS (only for X86_32) 68 * bios Reboot by jumping through the BIOS
71 * smp Reboot by executing reset on BSP or other CPU (only for X86_32) 69 * smp Reboot by executing reset on BSP or other CPU
72 * triple Force a triple fault (init) 70 * triple Force a triple fault (init)
73 * kbd Use the keyboard controller. cold reset (default) 71 * kbd Use the keyboard controller. cold reset (default)
74 * acpi Use the RESET_REG in the FADT 72 * acpi Use the RESET_REG in the FADT
@@ -95,7 +93,6 @@ static int __init reboot_setup(char *str)
95 reboot_mode = 0; 93 reboot_mode = 0;
96 break; 94 break;
97 95
98#ifdef CONFIG_X86_32
99#ifdef CONFIG_SMP 96#ifdef CONFIG_SMP
100 case 's': 97 case 's':
101 if (isdigit(*(str+1))) { 98 if (isdigit(*(str+1))) {
@@ -112,7 +109,6 @@ static int __init reboot_setup(char *str)
112#endif /* CONFIG_SMP */ 109#endif /* CONFIG_SMP */
113 110
114 case 'b': 111 case 'b':
115#endif
116 case 'a': 112 case 'a':
117 case 'k': 113 case 'k':
118 case 't': 114 case 't':
@@ -138,7 +134,6 @@ static int __init reboot_setup(char *str)
138__setup("reboot=", reboot_setup); 134__setup("reboot=", reboot_setup);
139 135
140 136
141#ifdef CONFIG_X86_32
142/* 137/*
143 * Reboot options and system auto-detection code provided by 138 * Reboot options and system auto-detection code provided by
144 * Dell Inc. so their systems "just work". :-) 139 * Dell Inc. so their systems "just work". :-)
@@ -157,11 +152,8 @@ static int __init set_bios_reboot(const struct dmi_system_id *d)
157 return 0; 152 return 0;
158} 153}
159 154
160void machine_real_restart(unsigned int type) 155void __noreturn machine_real_restart(unsigned int type)
161{ 156{
162 void (*restart_lowmem)(unsigned int) = (void (*)(unsigned int))
163 real_mode_header->machine_real_restart_asm;
164
165 local_irq_disable(); 157 local_irq_disable();
166 158
167 /* 159 /*
@@ -181,7 +173,11 @@ void machine_real_restart(unsigned int type)
181 /* 173 /*
182 * Switch back to the initial page table. 174 * Switch back to the initial page table.
183 */ 175 */
176#ifdef CONFIG_X86_32
184 load_cr3(initial_page_table); 177 load_cr3(initial_page_table);
178#else
179 write_cr3(real_mode_header->trampoline_pgd);
180#endif
185 181
186 /* 182 /*
187 * Write 0x1234 to absolute memory location 0x472. The BIOS reads 183 * Write 0x1234 to absolute memory location 0x472. The BIOS reads
@@ -192,14 +188,21 @@ void machine_real_restart(unsigned int type)
192 *((unsigned short *)0x472) = reboot_mode; 188 *((unsigned short *)0x472) = reboot_mode;
193 189
194 /* Jump to the identity-mapped low memory code */ 190 /* Jump to the identity-mapped low memory code */
195 restart_lowmem(type); 191#ifdef CONFIG_X86_32
192 asm volatile("jmpl *%0" : :
193 "rm" (real_mode_header->machine_real_restart_asm),
194 "a" (type));
195#else
196 asm volatile("ljmpl *%0" : :
197 "m" (real_mode_header->machine_real_restart_asm),
198 "D" (type));
199#endif
200 unreachable();
196} 201}
197#ifdef CONFIG_APM_MODULE 202#ifdef CONFIG_APM_MODULE
198EXPORT_SYMBOL(machine_real_restart); 203EXPORT_SYMBOL(machine_real_restart);
199#endif 204#endif
200 205
201#endif /* CONFIG_X86_32 */
202
203/* 206/*
204 * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot 207 * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
205 */ 208 */
@@ -223,11 +226,9 @@ static int __init set_kbd_reboot(const struct dmi_system_id *d)
223} 226}
224 227
225/* 228/*
226 * This is a single dmi_table handling all reboot quirks. Note that 229 * This is a single dmi_table handling all reboot quirks.
227 * REBOOT_BIOS is only available for 32bit
228 */ 230 */
229static struct dmi_system_id __initdata reboot_dmi_table[] = { 231static struct dmi_system_id __initdata reboot_dmi_table[] = {
230#ifdef CONFIG_X86_32
231 { /* Handle problems with rebooting on Dell E520's */ 232 { /* Handle problems with rebooting on Dell E520's */
232 .callback = set_bios_reboot, 233 .callback = set_bios_reboot,
233 .ident = "Dell E520", 234 .ident = "Dell E520",
@@ -377,7 +378,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
377 DMI_MATCH(DMI_BOARD_NAME, "P4S800"), 378 DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
378 }, 379 },
379 }, 380 },
380#endif /* CONFIG_X86_32 */
381 381
382 { /* Handle reboot issue on Acer Aspire one */ 382 { /* Handle reboot issue on Acer Aspire one */
383 .callback = set_kbd_reboot, 383 .callback = set_kbd_reboot,
@@ -576,13 +576,11 @@ static void native_machine_emergency_restart(void)
576 reboot_type = BOOT_KBD; 576 reboot_type = BOOT_KBD;
577 break; 577 break;
578 578
579#ifdef CONFIG_X86_32
580 case BOOT_BIOS: 579 case BOOT_BIOS:
581 machine_real_restart(MRR_BIOS); 580 machine_real_restart(MRR_BIOS);
582 581
583 reboot_type = BOOT_KBD; 582 reboot_type = BOOT_KBD;
584 break; 583 break;
585#endif
586 584
587 case BOOT_ACPI: 585 case BOOT_ACPI:
588 acpi_reboot(); 586 acpi_reboot();
@@ -624,12 +622,10 @@ void native_machine_shutdown(void)
624 /* The boot cpu is always logical cpu 0 */ 622 /* The boot cpu is always logical cpu 0 */
625 int reboot_cpu_id = 0; 623 int reboot_cpu_id = 0;
626 624
627#ifdef CONFIG_X86_32
628 /* See if there has been given a command line override */ 625 /* See if there has been given a command line override */
629 if ((reboot_cpu != -1) && (reboot_cpu < nr_cpu_ids) && 626 if ((reboot_cpu != -1) && (reboot_cpu < nr_cpu_ids) &&
630 cpu_online(reboot_cpu)) 627 cpu_online(reboot_cpu))
631 reboot_cpu_id = reboot_cpu; 628 reboot_cpu_id = reboot_cpu;
632#endif
633 629
634 /* Make certain the cpu I'm about to reboot on is online */ 630 /* Make certain the cpu I'm about to reboot on is online */
635 if (!cpu_online(reboot_cpu_id)) 631 if (!cpu_online(reboot_cpu_id))