diff options
| -rw-r--r-- | arch/x86/include/asm/emergency-restart.h | 2 | ||||
| -rw-r--r-- | arch/x86/include/asm/realmode.h | 3 | ||||
| -rw-r--r-- | arch/x86/include/asm/reboot.h | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/reboot.c | 60 | ||||
| -rw-r--r-- | arch/x86/realmode/rm/Makefile | 2 | ||||
| -rw-r--r-- | arch/x86/realmode/rm/header.S | 4 | ||||
| -rw-r--r-- | arch/x86/realmode/rm/reboot.S (renamed from arch/x86/realmode/rm/reboot_32.S) | 30 |
7 files changed, 59 insertions, 46 deletions
diff --git a/arch/x86/include/asm/emergency-restart.h b/arch/x86/include/asm/emergency-restart.h index cc70c1c78ca4..75ce3f47d204 100644 --- a/arch/x86/include/asm/emergency-restart.h +++ b/arch/x86/include/asm/emergency-restart.h | |||
| @@ -4,9 +4,7 @@ | |||
| 4 | enum reboot_type { | 4 | enum reboot_type { |
| 5 | BOOT_TRIPLE = 't', | 5 | BOOT_TRIPLE = 't', |
| 6 | BOOT_KBD = 'k', | 6 | BOOT_KBD = 'k', |
| 7 | #ifdef CONFIG_X86_32 | ||
| 8 | BOOT_BIOS = 'b', | 7 | BOOT_BIOS = 'b', |
| 9 | #endif | ||
| 10 | BOOT_ACPI = 'a', | 8 | BOOT_ACPI = 'a', |
| 11 | BOOT_EFI = 'e', | 9 | BOOT_EFI = 'e', |
| 12 | BOOT_CF9 = 'p', | 10 | BOOT_CF9 = 'p', |
diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h index fce3f4ae5bd6..fe1ec5bcd846 100644 --- a/arch/x86/include/asm/realmode.h +++ b/arch/x86/include/asm/realmode.h | |||
| @@ -21,8 +21,9 @@ struct real_mode_header { | |||
| 21 | u32 wakeup_header; | 21 | u32 wakeup_header; |
| 22 | #endif | 22 | #endif |
| 23 | /* APM/BIOS reboot */ | 23 | /* APM/BIOS reboot */ |
| 24 | #ifdef CONFIG_X86_32 | ||
| 25 | u32 machine_real_restart_asm; | 24 | u32 machine_real_restart_asm; |
| 25 | #ifdef CONFIG_X86_64 | ||
| 26 | u32 machine_real_restart_seg; | ||
| 26 | #endif | 27 | #endif |
| 27 | }; | 28 | }; |
| 28 | 29 | ||
diff --git a/arch/x86/include/asm/reboot.h b/arch/x86/include/asm/reboot.h index 92f297069e87..a82c4f1b4d83 100644 --- a/arch/x86/include/asm/reboot.h +++ b/arch/x86/include/asm/reboot.h | |||
| @@ -18,8 +18,8 @@ extern struct machine_ops machine_ops; | |||
| 18 | 18 | ||
| 19 | void native_machine_crash_shutdown(struct pt_regs *regs); | 19 | void native_machine_crash_shutdown(struct pt_regs *regs); |
| 20 | void native_machine_shutdown(void); | 20 | void native_machine_shutdown(void); |
| 21 | void machine_real_restart(unsigned int type); | 21 | void __noreturn machine_real_restart(unsigned int type); |
| 22 | /* These must match dispatch_table in reboot_32.S */ | 22 | /* These must match dispatch in arch/x86/realmore/rm/reboot.S */ |
| 23 | #define MRR_BIOS 0 | 23 | #define MRR_BIOS 0 |
| 24 | #define MRR_APM 1 | 24 | #define MRR_APM 1 |
| 25 | 25 | ||
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index d0f81d3d388f..52190a938b4a 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c | |||
| @@ -22,14 +22,12 @@ | |||
| 22 | #include <asm/virtext.h> | 22 | #include <asm/virtext.h> |
| 23 | #include <asm/cpu.h> | 23 | #include <asm/cpu.h> |
| 24 | #include <asm/nmi.h> | 24 | #include <asm/nmi.h> |
| 25 | #include <asm/smp.h> | ||
| 25 | 26 | ||
| 26 | #ifdef CONFIG_X86_32 | 27 | #include <linux/ctype.h> |
| 27 | # include <linux/ctype.h> | 28 | #include <linux/mc146818rtc.h> |
| 28 | # include <linux/mc146818rtc.h> | 29 | #include <asm/realmode.h> |
| 29 | # include <asm/realmode.h> | 30 | #include <asm/x86_init.h> |
| 30 | #else | ||
| 31 | # include <asm/x86_init.h> | ||
| 32 | #endif | ||
| 33 | 31 | ||
| 34 | /* | 32 | /* |
| 35 | * Power off function, if any | 33 | * Power off function, if any |
| @@ -51,7 +49,7 @@ int reboot_force; | |||
| 51 | */ | 49 | */ |
| 52 | static int reboot_default = 1; | 50 | static int reboot_default = 1; |
| 53 | 51 | ||
| 54 | #if defined(CONFIG_X86_32) && defined(CONFIG_SMP) | 52 | #ifdef CONFIG_SMP |
| 55 | static int reboot_cpu = -1; | 53 | static int reboot_cpu = -1; |
| 56 | #endif | 54 | #endif |
| 57 | 55 | ||
| @@ -69,8 +67,8 @@ bool port_cf9_safe = false; | |||
| 69 | * reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci] | 67 | * reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci] |
| 70 | * warm Don't set the cold reboot flag | 68 | * warm Don't set the cold reboot flag |
| 71 | * cold Set the cold reboot flag | 69 | * cold Set the cold reboot flag |
| 72 | * bios Reboot by jumping through the BIOS (only for X86_32) | 70 | * bios Reboot by jumping through the BIOS |
| 73 | * smp Reboot by executing reset on BSP or other CPU (only for X86_32) | 71 | * smp Reboot by executing reset on BSP or other CPU |
| 74 | * triple Force a triple fault (init) | 72 | * triple Force a triple fault (init) |
| 75 | * kbd Use the keyboard controller. cold reset (default) | 73 | * kbd Use the keyboard controller. cold reset (default) |
| 76 | * acpi Use the RESET_REG in the FADT | 74 | * acpi Use the RESET_REG in the FADT |
| @@ -97,7 +95,6 @@ static int __init reboot_setup(char *str) | |||
| 97 | reboot_mode = 0; | 95 | reboot_mode = 0; |
| 98 | break; | 96 | break; |
| 99 | 97 | ||
| 100 | #ifdef CONFIG_X86_32 | ||
| 101 | #ifdef CONFIG_SMP | 98 | #ifdef CONFIG_SMP |
| 102 | case 's': | 99 | case 's': |
| 103 | if (isdigit(*(str+1))) { | 100 | if (isdigit(*(str+1))) { |
| @@ -114,7 +111,6 @@ static int __init reboot_setup(char *str) | |||
| 114 | #endif /* CONFIG_SMP */ | 111 | #endif /* CONFIG_SMP */ |
| 115 | 112 | ||
| 116 | case 'b': | 113 | case 'b': |
| 117 | #endif | ||
| 118 | case 'a': | 114 | case 'a': |
| 119 | case 'k': | 115 | case 'k': |
| 120 | case 't': | 116 | case 't': |
| @@ -140,7 +136,6 @@ static int __init reboot_setup(char *str) | |||
| 140 | __setup("reboot=", reboot_setup); | 136 | __setup("reboot=", reboot_setup); |
| 141 | 137 | ||
| 142 | 138 | ||
| 143 | #ifdef CONFIG_X86_32 | ||
| 144 | /* | 139 | /* |
| 145 | * Reboot options and system auto-detection code provided by | 140 | * Reboot options and system auto-detection code provided by |
| 146 | * Dell Inc. so their systems "just work". :-) | 141 | * Dell Inc. so their systems "just work". :-) |
| @@ -160,11 +155,8 @@ static int __init set_bios_reboot(const struct dmi_system_id *d) | |||
| 160 | return 0; | 155 | return 0; |
| 161 | } | 156 | } |
| 162 | 157 | ||
| 163 | void machine_real_restart(unsigned int type) | 158 | void __noreturn machine_real_restart(unsigned int type) |
| 164 | { | 159 | { |
| 165 | void (*restart_lowmem)(unsigned int) = (void (*)(unsigned int)) | ||
| 166 | real_mode_header->machine_real_restart_asm; | ||
| 167 | |||
| 168 | local_irq_disable(); | 160 | local_irq_disable(); |
| 169 | 161 | ||
| 170 | /* | 162 | /* |
| @@ -184,25 +176,28 @@ void machine_real_restart(unsigned int type) | |||
| 184 | /* | 176 | /* |
| 185 | * Switch back to the initial page table. | 177 | * Switch back to the initial page table. |
| 186 | */ | 178 | */ |
| 179 | #ifdef CONFIG_X86_32 | ||
| 187 | load_cr3(initial_page_table); | 180 | load_cr3(initial_page_table); |
| 188 | 181 | #else | |
| 189 | /* | 182 | write_cr3(real_mode_header->trampoline_pgd); |
| 190 | * Write 0x1234 to absolute memory location 0x472. The BIOS reads | 183 | #endif |
| 191 | * this on booting to tell it to "Bypass memory test (also warm | ||
| 192 | * boot)". This seems like a fairly standard thing that gets set by | ||
| 193 | * REBOOT.COM programs, and the previous reset routine did this | ||
| 194 | * too. */ | ||
| 195 | *((unsigned short *)0x472) = reboot_mode; | ||
| 196 | 184 | ||
| 197 | /* Jump to the identity-mapped low memory code */ | 185 | /* Jump to the identity-mapped low memory code */ |
| 198 | restart_lowmem(type); | 186 | #ifdef CONFIG_X86_32 |
| 187 | asm volatile("jmpl *%0" : : | ||
| 188 | "rm" (real_mode_header->machine_real_restart_asm), | ||
| 189 | "a" (type)); | ||
| 190 | #else | ||
| 191 | asm volatile("ljmpl *%0" : : | ||
| 192 | "m" (real_mode_header->machine_real_restart_asm), | ||
| 193 | "D" (type)); | ||
| 194 | #endif | ||
| 195 | unreachable(); | ||
| 199 | } | 196 | } |
| 200 | #ifdef CONFIG_APM_MODULE | 197 | #ifdef CONFIG_APM_MODULE |
| 201 | EXPORT_SYMBOL(machine_real_restart); | 198 | EXPORT_SYMBOL(machine_real_restart); |
| 202 | #endif | 199 | #endif |
| 203 | 200 | ||
| 204 | #endif /* CONFIG_X86_32 */ | ||
| 205 | |||
| 206 | /* | 201 | /* |
| 207 | * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot | 202 | * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot |
| 208 | */ | 203 | */ |
| @@ -227,11 +222,9 @@ static int __init set_kbd_reboot(const struct dmi_system_id *d) | |||
| 227 | } | 222 | } |
| 228 | 223 | ||
| 229 | /* | 224 | /* |
| 230 | * This is a single dmi_table handling all reboot quirks. Note that | 225 | * This is a single dmi_table handling all reboot quirks. |
| 231 | * REBOOT_BIOS is only available for 32bit | ||
| 232 | */ | 226 | */ |
| 233 | static struct dmi_system_id __initdata reboot_dmi_table[] = { | 227 | static struct dmi_system_id __initdata reboot_dmi_table[] = { |
| 234 | #ifdef CONFIG_X86_32 | ||
| 235 | { /* Handle problems with rebooting on Dell E520's */ | 228 | { /* Handle problems with rebooting on Dell E520's */ |
| 236 | .callback = set_bios_reboot, | 229 | .callback = set_bios_reboot, |
| 237 | .ident = "Dell E520", | 230 | .ident = "Dell E520", |
| @@ -381,7 +374,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { | |||
| 381 | DMI_MATCH(DMI_BOARD_NAME, "P4S800"), | 374 | DMI_MATCH(DMI_BOARD_NAME, "P4S800"), |
| 382 | }, | 375 | }, |
| 383 | }, | 376 | }, |
| 384 | #endif /* CONFIG_X86_32 */ | ||
| 385 | 377 | ||
| 386 | { /* Handle reboot issue on Acer Aspire one */ | 378 | { /* Handle reboot issue on Acer Aspire one */ |
| 387 | .callback = set_kbd_reboot, | 379 | .callback = set_kbd_reboot, |
| @@ -588,13 +580,11 @@ static void native_machine_emergency_restart(void) | |||
| 588 | reboot_type = BOOT_KBD; | 580 | reboot_type = BOOT_KBD; |
| 589 | break; | 581 | break; |
| 590 | 582 | ||
| 591 | #ifdef CONFIG_X86_32 | ||
| 592 | case BOOT_BIOS: | 583 | case BOOT_BIOS: |
| 593 | machine_real_restart(MRR_BIOS); | 584 | machine_real_restart(MRR_BIOS); |
| 594 | 585 | ||
| 595 | reboot_type = BOOT_KBD; | 586 | reboot_type = BOOT_KBD; |
| 596 | break; | 587 | break; |
| 597 | #endif | ||
| 598 | 588 | ||
| 599 | case BOOT_ACPI: | 589 | case BOOT_ACPI: |
| 600 | acpi_reboot(); | 590 | acpi_reboot(); |
| @@ -636,12 +626,10 @@ void native_machine_shutdown(void) | |||
| 636 | /* The boot cpu is always logical cpu 0 */ | 626 | /* The boot cpu is always logical cpu 0 */ |
| 637 | int reboot_cpu_id = 0; | 627 | int reboot_cpu_id = 0; |
| 638 | 628 | ||
| 639 | #ifdef CONFIG_X86_32 | ||
| 640 | /* See if there has been given a command line override */ | 629 | /* See if there has been given a command line override */ |
| 641 | if ((reboot_cpu != -1) && (reboot_cpu < nr_cpu_ids) && | 630 | if ((reboot_cpu != -1) && (reboot_cpu < nr_cpu_ids) && |
| 642 | cpu_online(reboot_cpu)) | 631 | cpu_online(reboot_cpu)) |
| 643 | reboot_cpu_id = reboot_cpu; | 632 | reboot_cpu_id = reboot_cpu; |
| 644 | #endif | ||
| 645 | 633 | ||
| 646 | /* Make certain the cpu I'm about to reboot on is online */ | 634 | /* Make certain the cpu I'm about to reboot on is online */ |
| 647 | if (!cpu_online(reboot_cpu_id)) | 635 | if (!cpu_online(reboot_cpu_id)) |
diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile index 5b84a2d30888..b2d534cab25f 100644 --- a/arch/x86/realmode/rm/Makefile +++ b/arch/x86/realmode/rm/Makefile | |||
| @@ -22,7 +22,7 @@ wakeup-objs += video-bios.o | |||
| 22 | realmode-y += header.o | 22 | realmode-y += header.o |
| 23 | realmode-y += trampoline_$(BITS).o | 23 | realmode-y += trampoline_$(BITS).o |
| 24 | realmode-y += stack.o | 24 | realmode-y += stack.o |
| 25 | realmode-$(CONFIG_X86_32) += reboot_32.o | 25 | realmode-y += reboot.o |
| 26 | realmode-$(CONFIG_ACPI_SLEEP) += $(wakeup-objs) | 26 | realmode-$(CONFIG_ACPI_SLEEP) += $(wakeup-objs) |
| 27 | 27 | ||
| 28 | targets += $(realmode-y) | 28 | targets += $(realmode-y) |
diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S index fadf48378ada..a28221d94e69 100644 --- a/arch/x86/realmode/rm/header.S +++ b/arch/x86/realmode/rm/header.S | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <linux/linkage.h> | 7 | #include <linux/linkage.h> |
| 8 | #include <asm/page_types.h> | 8 | #include <asm/page_types.h> |
| 9 | #include <asm/segment.h> | ||
| 9 | 10 | ||
| 10 | #include "realmode.h" | 11 | #include "realmode.h" |
| 11 | 12 | ||
| @@ -28,8 +29,9 @@ GLOBAL(real_mode_header) | |||
| 28 | .long pa_wakeup_header | 29 | .long pa_wakeup_header |
| 29 | #endif | 30 | #endif |
| 30 | /* APM/BIOS reboot */ | 31 | /* APM/BIOS reboot */ |
| 31 | #ifdef CONFIG_X86_32 | ||
| 32 | .long pa_machine_real_restart_asm | 32 | .long pa_machine_real_restart_asm |
| 33 | #ifdef CONFIG_X86_64 | ||
| 34 | .long __KERNEL32_CS | ||
| 33 | #endif | 35 | #endif |
| 34 | END(real_mode_header) | 36 | END(real_mode_header) |
| 35 | 37 | ||
diff --git a/arch/x86/realmode/rm/reboot_32.S b/arch/x86/realmode/rm/reboot.S index 114044876b3d..f932ea61d1c8 100644 --- a/arch/x86/realmode/rm/reboot_32.S +++ b/arch/x86/realmode/rm/reboot.S | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | #include <linux/init.h> | 2 | #include <linux/init.h> |
| 3 | #include <asm/segment.h> | 3 | #include <asm/segment.h> |
| 4 | #include <asm/page_types.h> | 4 | #include <asm/page_types.h> |
| 5 | #include <asm/processor-flags.h> | ||
| 6 | #include <asm/msr-index.h> | ||
| 5 | #include "realmode.h" | 7 | #include "realmode.h" |
| 6 | 8 | ||
| 7 | /* | 9 | /* |
| @@ -12,13 +14,35 @@ | |||
| 12 | * doesn't work with at least one type of 486 motherboard. It is easy | 14 | * doesn't work with at least one type of 486 motherboard. It is easy |
| 13 | * to stop this code working; hence the copious comments. | 15 | * to stop this code working; hence the copious comments. |
| 14 | * | 16 | * |
| 15 | * This code is called with the restart type (0 = BIOS, 1 = APM) in %eax. | 17 | * This code is called with the restart type (0 = BIOS, 1 = APM) in |
| 18 | * the primary argument register (%eax for 32 bit, %edi for 64 bit). | ||
| 16 | */ | 19 | */ |
| 17 | .section ".text32", "ax" | 20 | .section ".text32", "ax" |
| 18 | .code32 | 21 | .code32 |
| 19 | |||
| 20 | .balign 16 | ||
| 21 | ENTRY(machine_real_restart_asm) | 22 | ENTRY(machine_real_restart_asm) |
| 23 | |||
| 24 | #ifdef CONFIG_X86_64 | ||
| 25 | /* Switch to trampoline GDT as it is guaranteed < 4 GiB */ | ||
| 26 | movl $__KERNEL_DS, %eax | ||
| 27 | movl %eax, %ds | ||
| 28 | lgdtl pa_tr_gdt | ||
| 29 | |||
| 30 | /* Disable paging to drop us out of long mode */ | ||
| 31 | movl %cr0, %eax | ||
| 32 | andl $~X86_CR0_PG, %eax | ||
| 33 | movl %eax, %cr0 | ||
| 34 | ljmpl $__KERNEL32_CS, $pa_machine_real_restart_paging_off | ||
| 35 | |||
| 36 | GLOBAL(machine_real_restart_paging_off) | ||
| 37 | xorl %eax, %eax | ||
| 38 | xorl %edx, %edx | ||
| 39 | movl $MSR_EFER, %ecx | ||
| 40 | wrmsr | ||
| 41 | |||
| 42 | movl %edi, %eax | ||
| 43 | |||
| 44 | #endif /* CONFIG_X86_64 */ | ||
| 45 | |||
| 22 | /* Set up the IDT for real mode. */ | 46 | /* Set up the IDT for real mode. */ |
| 23 | lidtl pa_machine_real_restart_idt | 47 | lidtl pa_machine_real_restart_idt |
| 24 | 48 | ||
