Commit d5d96ed2d89ea228bdc27980b8ee4c94422ddef5

Authored by Linus Torvalds

Merge branch 'x86-reboot-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86/reboot changes from Ingo Molnar:
 "Now that the revampted x86 real-mode trampoline code is upstream and
  seems to be working well, we can extend the 64-bit reboot code to be
  as capable as the 32-bit one."

* 'x86-reboot-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86-64, reboot: Be more paranoid in 64-bit reboot=bios
  x86, reboot: Drop redundant write of reboot_mode
  x86-64, reboot: Allow reboot=bios and reboot-cpu override on x86-64

Showing 8 changed files Side-by-side Diff

arch/x86/include/asm/emergency-restart.h
... ... @@ -4,9 +4,7 @@
4 4 enum reboot_type {
5 5 BOOT_TRIPLE = 't',
6 6 BOOT_KBD = 'k',
7   -#ifdef CONFIG_X86_32
8 7 BOOT_BIOS = 'b',
9   -#endif
10 8 BOOT_ACPI = 'a',
11 9 BOOT_EFI = 'e',
12 10 BOOT_CF9 = 'p',
arch/x86/include/asm/realmode.h
... ... @@ -21,8 +21,9 @@
21 21 u32 wakeup_header;
22 22 #endif
23 23 /* APM/BIOS reboot */
24   -#ifdef CONFIG_X86_32
25 24 u32 machine_real_restart_asm;
  25 +#ifdef CONFIG_X86_64
  26 + u32 machine_real_restart_seg;
26 27 #endif
27 28 };
28 29  
arch/x86/include/asm/reboot.h
... ... @@ -18,8 +18,8 @@
18 18  
19 19 void native_machine_crash_shutdown(struct pt_regs *regs);
20 20 void native_machine_shutdown(void);
21   -void machine_real_restart(unsigned int type);
22   -/* These must match dispatch_table in reboot_32.S */
  21 +void __noreturn machine_real_restart(unsigned int type);
  22 +/* These must match dispatch in arch/x86/realmore/rm/reboot.S */
23 23 #define MRR_BIOS 0
24 24 #define MRR_APM 1
25 25  
arch/x86/kernel/reboot.c
... ... @@ -22,14 +22,12 @@
22 22 #include <asm/virtext.h>
23 23 #include <asm/cpu.h>
24 24 #include <asm/nmi.h>
  25 +#include <asm/smp.h>
25 26  
26   -#ifdef CONFIG_X86_32
27   -# include <linux/ctype.h>
28   -# include <linux/mc146818rtc.h>
29   -# include <asm/realmode.h>
30   -#else
31   -# include <asm/x86_init.h>
32   -#endif
  27 +#include <linux/ctype.h>
  28 +#include <linux/mc146818rtc.h>
  29 +#include <asm/realmode.h>
  30 +#include <asm/x86_init.h>
33 31  
34 32 /*
35 33 * Power off function, if any
... ... @@ -51,7 +49,7 @@
51 49 */
52 50 static int reboot_default = 1;
53 51  
54   -#if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
  52 +#ifdef CONFIG_SMP
55 53 static int reboot_cpu = -1;
56 54 #endif
57 55  
... ... @@ -69,8 +67,8 @@
69 67 * reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci]
70 68 * warm Don't set the cold reboot flag
71 69 * cold Set the cold reboot flag
72   - * bios Reboot by jumping through the BIOS (only for X86_32)
73   - * smp Reboot by executing reset on BSP or other CPU (only for X86_32)
  70 + * bios Reboot by jumping through the BIOS
  71 + * smp Reboot by executing reset on BSP or other CPU
74 72 * triple Force a triple fault (init)
75 73 * kbd Use the keyboard controller. cold reset (default)
76 74 * acpi Use the RESET_REG in the FADT
... ... @@ -97,7 +95,6 @@
97 95 reboot_mode = 0;
98 96 break;
99 97  
100   -#ifdef CONFIG_X86_32
101 98 #ifdef CONFIG_SMP
102 99 case 's':
103 100 if (isdigit(*(str+1))) {
... ... @@ -114,7 +111,6 @@
114 111 #endif /* CONFIG_SMP */
115 112  
116 113 case 'b':
117   -#endif
118 114 case 'a':
119 115 case 'k':
120 116 case 't':
... ... @@ -140,7 +136,6 @@
140 136 __setup("reboot=", reboot_setup);
141 137  
142 138  
143   -#ifdef CONFIG_X86_32
144 139 /*
145 140 * Reboot options and system auto-detection code provided by
146 141 * Dell Inc. so their systems "just work". :-)
147 142  
... ... @@ -160,11 +155,8 @@
160 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 160 local_irq_disable();
169 161  
170 162 /*
171 163  
172 164  
173 165  
174 166  
... ... @@ -184,25 +176,28 @@
184 176 /*
185 177 * Switch back to the initial page table.
186 178 */
  179 +#ifdef CONFIG_X86_32
187 180 load_cr3(initial_page_table);
  181 +#else
  182 + write_cr3(real_mode_header->trampoline_pgd);
  183 +#endif
188 184  
189   - /*
190   - * Write 0x1234 to absolute memory location 0x472. The BIOS reads
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   -
197 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 197 #ifdef CONFIG_APM_MODULE
201 198 EXPORT_SYMBOL(machine_real_restart);
202 199 #endif
203 200  
204   -#endif /* CONFIG_X86_32 */
205   -
206 201 /*
207 202 * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
208 203 */
209 204  
... ... @@ -227,11 +222,9 @@
227 222 }
228 223  
229 224 /*
230   - * This is a single dmi_table handling all reboot quirks. Note that
231   - * REBOOT_BIOS is only available for 32bit
  225 + * This is a single dmi_table handling all reboot quirks.
232 226 */
233 227 static struct dmi_system_id __initdata reboot_dmi_table[] = {
234   -#ifdef CONFIG_X86_32
235 228 { /* Handle problems with rebooting on Dell E520's */
236 229 .callback = set_bios_reboot,
237 230 .ident = "Dell E520",
... ... @@ -381,7 +374,6 @@
381 374 DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
382 375 },
383 376 },
384   -#endif /* CONFIG_X86_32 */
385 377  
386 378 { /* Handle reboot issue on Acer Aspire one */
387 379 .callback = set_kbd_reboot,
388 380  
... ... @@ -588,13 +580,11 @@
588 580 reboot_type = BOOT_KBD;
589 581 break;
590 582  
591   -#ifdef CONFIG_X86_32
592 583 case BOOT_BIOS:
593 584 machine_real_restart(MRR_BIOS);
594 585  
595 586 reboot_type = BOOT_KBD;
596 587 break;
597   -#endif
598 588  
599 589 case BOOT_ACPI:
600 590 acpi_reboot();
601 591  
... ... @@ -636,12 +626,10 @@
636 626 /* The boot cpu is always logical cpu 0 */
637 627 int reboot_cpu_id = 0;
638 628  
639   -#ifdef CONFIG_X86_32
640 629 /* See if there has been given a command line override */
641 630 if ((reboot_cpu != -1) && (reboot_cpu < nr_cpu_ids) &&
642 631 cpu_online(reboot_cpu))
643 632 reboot_cpu_id = reboot_cpu;
644   -#endif
645 633  
646 634 /* Make certain the cpu I'm about to reboot on is online */
647 635 if (!cpu_online(reboot_cpu_id))
arch/x86/realmode/rm/Makefile
... ... @@ -22,7 +22,7 @@
22 22 realmode-y += header.o
23 23 realmode-y += trampoline_$(BITS).o
24 24 realmode-y += stack.o
25   -realmode-$(CONFIG_X86_32) += reboot_32.o
  25 +realmode-y += reboot.o
26 26 realmode-$(CONFIG_ACPI_SLEEP) += $(wakeup-objs)
27 27  
28 28 targets += $(realmode-y)
arch/x86/realmode/rm/header.S
... ... @@ -6,6 +6,7 @@
6 6  
7 7 #include <linux/linkage.h>
8 8 #include <asm/page_types.h>
  9 +#include <asm/segment.h>
9 10  
10 11 #include "realmode.h"
11 12  
12 13  
... ... @@ -28,8 +29,9 @@
28 29 .long pa_wakeup_header
29 30 #endif
30 31 /* APM/BIOS reboot */
31   -#ifdef CONFIG_X86_32
32 32 .long pa_machine_real_restart_asm
  33 +#ifdef CONFIG_X86_64
  34 + .long __KERNEL32_CS
33 35 #endif
34 36 END(real_mode_header)
35 37  
arch/x86/realmode/rm/reboot.S
  1 +#include <linux/linkage.h>
  2 +#include <linux/init.h>
  3 +#include <asm/segment.h>
  4 +#include <asm/page_types.h>
  5 +#include <asm/processor-flags.h>
  6 +#include <asm/msr-index.h>
  7 +#include "realmode.h"
  8 +
  9 +/*
  10 + * The following code and data reboots the machine by switching to real
  11 + * mode and jumping to the BIOS reset entry point, as if the CPU has
  12 + * really been reset. The previous version asked the keyboard
  13 + * controller to pulse the CPU reset line, which is more thorough, but
  14 + * doesn't work with at least one type of 486 motherboard. It is easy
  15 + * to stop this code working; hence the copious comments.
  16 + *
  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).
  19 + */
  20 + .section ".text32", "ax"
  21 + .code32
  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 +
  46 + /* Set up the IDT for real mode. */
  47 + lidtl pa_machine_real_restart_idt
  48 +
  49 + /*
  50 + * Set up a GDT from which we can load segment descriptors for real
  51 + * mode. The GDT is not used in real mode; it is just needed here to
  52 + * prepare the descriptors.
  53 + */
  54 + lgdtl pa_machine_real_restart_gdt
  55 +
  56 + /*
  57 + * Load the data segment registers with 16-bit compatible values
  58 + */
  59 + movl $16, %ecx
  60 + movl %ecx, %ds
  61 + movl %ecx, %es
  62 + movl %ecx, %fs
  63 + movl %ecx, %gs
  64 + movl %ecx, %ss
  65 + ljmpw $8, $1f
  66 +
  67 +/*
  68 + * This is 16-bit protected mode code to disable paging and the cache,
  69 + * switch to real mode and jump to the BIOS reset code.
  70 + *
  71 + * The instruction that switches to real mode by writing to CR0 must be
  72 + * followed immediately by a far jump instruction, which set CS to a
  73 + * valid value for real mode, and flushes the prefetch queue to avoid
  74 + * running instructions that have already been decoded in protected
  75 + * mode.
  76 + *
  77 + * Clears all the flags except ET, especially PG (paging), PE
  78 + * (protected-mode enable) and TS (task switch for coprocessor state
  79 + * save). Flushes the TLB after paging has been disabled. Sets CD and
  80 + * NW, to disable the cache on a 486, and invalidates the cache. This
  81 + * is more like the state of a 486 after reset. I don't know if
  82 + * something else should be done for other chips.
  83 + *
  84 + * More could be done here to set up the registers as if a CPU reset had
  85 + * occurred; hopefully real BIOSs don't assume much. This is not the
  86 + * actual BIOS entry point, anyway (that is at 0xfffffff0).
  87 + *
  88 + * Most of this work is probably excessive, but it is what is tested.
  89 + */
  90 + .text
  91 + .code16
  92 +
  93 + .balign 16
  94 +machine_real_restart_asm16:
  95 +1:
  96 + xorl %ecx, %ecx
  97 + movl %cr0, %edx
  98 + andl $0x00000011, %edx
  99 + orl $0x60000000, %edx
  100 + movl %edx, %cr0
  101 + movl %ecx, %cr3
  102 + movl %cr0, %edx
  103 + testl $0x60000000, %edx /* If no cache bits -> no wbinvd */
  104 + jz 2f
  105 + wbinvd
  106 +2:
  107 + andb $0x10, %dl
  108 + movl %edx, %cr0
  109 + LJMPW_RM(3f)
  110 +3:
  111 + andw %ax, %ax
  112 + jz bios
  113 +
  114 +apm:
  115 + movw $0x1000, %ax
  116 + movw %ax, %ss
  117 + movw $0xf000, %sp
  118 + movw $0x5307, %ax
  119 + movw $0x0001, %bx
  120 + movw $0x0003, %cx
  121 + int $0x15
  122 + /* This should never return... */
  123 +
  124 +bios:
  125 + ljmpw $0xf000, $0xfff0
  126 +
  127 + .section ".rodata", "a"
  128 +
  129 + .balign 16
  130 +GLOBAL(machine_real_restart_idt)
  131 + .word 0xffff /* Length - real mode default value */
  132 + .long 0 /* Base - real mode default value */
  133 +END(machine_real_restart_idt)
  134 +
  135 + .balign 16
  136 +GLOBAL(machine_real_restart_gdt)
  137 + /* Self-pointer */
  138 + .word 0xffff /* Length - real mode default value */
  139 + .long pa_machine_real_restart_gdt
  140 + .word 0
  141 +
  142 + /*
  143 + * 16-bit code segment pointing to real_mode_seg
  144 + * Selector value 8
  145 + */
  146 + .word 0xffff /* Limit */
  147 + .long 0x9b000000 + pa_real_mode_base
  148 + .word 0
  149 +
  150 + /*
  151 + * 16-bit data segment with the selector value 16 = 0x10 and
  152 + * base value 0x100; since this is consistent with real mode
  153 + * semantics we don't have to reload the segments once CR0.PE = 0.
  154 + */
  155 + .quad GDT_ENTRY(0x0093, 0x100, 0xffff)
  156 +END(machine_real_restart_gdt)
arch/x86/realmode/rm/reboot_32.S
1   -#include <linux/linkage.h>
2   -#include <linux/init.h>
3   -#include <asm/segment.h>
4   -#include <asm/page_types.h>
5   -#include "realmode.h"
6   -
7   -/*
8   - * The following code and data reboots the machine by switching to real
9   - * mode and jumping to the BIOS reset entry point, as if the CPU has
10   - * really been reset. The previous version asked the keyboard
11   - * controller to pulse the CPU reset line, which is more thorough, but
12   - * doesn't work with at least one type of 486 motherboard. It is easy
13   - * to stop this code working; hence the copious comments.
14   - *
15   - * This code is called with the restart type (0 = BIOS, 1 = APM) in %eax.
16   - */
17   - .section ".text32", "ax"
18   - .code32
19   -
20   - .balign 16
21   -ENTRY(machine_real_restart_asm)
22   - /* Set up the IDT for real mode. */
23   - lidtl pa_machine_real_restart_idt
24   -
25   - /*
26   - * Set up a GDT from which we can load segment descriptors for real
27   - * mode. The GDT is not used in real mode; it is just needed here to
28   - * prepare the descriptors.
29   - */
30   - lgdtl pa_machine_real_restart_gdt
31   -
32   - /*
33   - * Load the data segment registers with 16-bit compatible values
34   - */
35   - movl $16, %ecx
36   - movl %ecx, %ds
37   - movl %ecx, %es
38   - movl %ecx, %fs
39   - movl %ecx, %gs
40   - movl %ecx, %ss
41   - ljmpw $8, $1f
42   -
43   -/*
44   - * This is 16-bit protected mode code to disable paging and the cache,
45   - * switch to real mode and jump to the BIOS reset code.
46   - *
47   - * The instruction that switches to real mode by writing to CR0 must be
48   - * followed immediately by a far jump instruction, which set CS to a
49   - * valid value for real mode, and flushes the prefetch queue to avoid
50   - * running instructions that have already been decoded in protected
51   - * mode.
52   - *
53   - * Clears all the flags except ET, especially PG (paging), PE
54   - * (protected-mode enable) and TS (task switch for coprocessor state
55   - * save). Flushes the TLB after paging has been disabled. Sets CD and
56   - * NW, to disable the cache on a 486, and invalidates the cache. This
57   - * is more like the state of a 486 after reset. I don't know if
58   - * something else should be done for other chips.
59   - *
60   - * More could be done here to set up the registers as if a CPU reset had
61   - * occurred; hopefully real BIOSs don't assume much. This is not the
62   - * actual BIOS entry point, anyway (that is at 0xfffffff0).
63   - *
64   - * Most of this work is probably excessive, but it is what is tested.
65   - */
66   - .text
67   - .code16
68   -
69   - .balign 16
70   -machine_real_restart_asm16:
71   -1:
72   - xorl %ecx, %ecx
73   - movl %cr0, %edx
74   - andl $0x00000011, %edx
75   - orl $0x60000000, %edx
76   - movl %edx, %cr0
77   - movl %ecx, %cr3
78   - movl %cr0, %edx
79   - testl $0x60000000, %edx /* If no cache bits -> no wbinvd */
80   - jz 2f
81   - wbinvd
82   -2:
83   - andb $0x10, %dl
84   - movl %edx, %cr0
85   - LJMPW_RM(3f)
86   -3:
87   - andw %ax, %ax
88   - jz bios
89   -
90   -apm:
91   - movw $0x1000, %ax
92   - movw %ax, %ss
93   - movw $0xf000, %sp
94   - movw $0x5307, %ax
95   - movw $0x0001, %bx
96   - movw $0x0003, %cx
97   - int $0x15
98   - /* This should never return... */
99   -
100   -bios:
101   - ljmpw $0xf000, $0xfff0
102   -
103   - .section ".rodata", "a"
104   -
105   - .balign 16
106   -GLOBAL(machine_real_restart_idt)
107   - .word 0xffff /* Length - real mode default value */
108   - .long 0 /* Base - real mode default value */
109   -END(machine_real_restart_idt)
110   -
111   - .balign 16
112   -GLOBAL(machine_real_restart_gdt)
113   - /* Self-pointer */
114   - .word 0xffff /* Length - real mode default value */
115   - .long pa_machine_real_restart_gdt
116   - .word 0
117   -
118   - /*
119   - * 16-bit code segment pointing to real_mode_seg
120   - * Selector value 8
121   - */
122   - .word 0xffff /* Limit */
123   - .long 0x9b000000 + pa_real_mode_base
124   - .word 0
125   -
126   - /*
127   - * 16-bit data segment with the selector value 16 = 0x10 and
128   - * base value 0x100; since this is consistent with real mode
129   - * semantics we don't have to reload the segments once CR0.PE = 0.
130   - */
131   - .quad GDT_ENTRY(0x0093, 0x100, 0xffff)
132   -END(machine_real_restart_gdt)