diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-12 23:09:25 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-12 23:09:25 -0500 |
commit | 2f51c8204ab3ea211ac92f3b7b88a38595ed6412 (patch) | |
tree | b872e12090ea271ea951f2446e840dc4d0f52e43 | |
parent | fda604a4daa19ead458ce5471892fa1d4b382d82 (diff) | |
parent | 452308de61056a539352a9306c46716d7af8a1f1 (diff) |
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Ingo Molnar:
"This fixes 3 FPU handling related bugs, an EFI boot crash and a
runtime warning.
The EFI fix arrived late but I didn't want to delay it to after v4.5
because the effects are pretty bad for the systems that are affected
by it"
[ Actually, I don't think the EFI fix really matters yet, because we
haven't switched to the separate EFI page tables in mainline yet ]
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/efi: Fix boot crash by always mapping boot service regions into new EFI page tables
x86/fpu: Fix eager-FPU handling on legacy FPU machines
x86/delay: Avoid preemptible context checks in delay_mwaitx()
x86/fpu: Revert ("x86/fpu: Disable AVX when eagerfpu is off")
x86/fpu: Fix 'no387' regression
-rw-r--r-- | arch/x86/include/asm/fpu/xstate.h | 9 | ||||
-rw-r--r-- | arch/x86/kernel/fpu/core.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/fpu/init.c | 22 | ||||
-rw-r--r-- | arch/x86/lib/delay.c | 2 | ||||
-rw-r--r-- | arch/x86/platform/efi/quirks.c | 79 |
5 files changed, 79 insertions, 37 deletions
diff --git a/arch/x86/include/asm/fpu/xstate.h b/arch/x86/include/asm/fpu/xstate.h index af30fdeb140d..f23cd8c80b1c 100644 --- a/arch/x86/include/asm/fpu/xstate.h +++ b/arch/x86/include/asm/fpu/xstate.h | |||
@@ -20,16 +20,15 @@ | |||
20 | 20 | ||
21 | /* Supported features which support lazy state saving */ | 21 | /* Supported features which support lazy state saving */ |
22 | #define XFEATURE_MASK_LAZY (XFEATURE_MASK_FP | \ | 22 | #define XFEATURE_MASK_LAZY (XFEATURE_MASK_FP | \ |
23 | XFEATURE_MASK_SSE) | 23 | XFEATURE_MASK_SSE | \ |
24 | |||
25 | /* Supported features which require eager state saving */ | ||
26 | #define XFEATURE_MASK_EAGER (XFEATURE_MASK_BNDREGS | \ | ||
27 | XFEATURE_MASK_BNDCSR | \ | ||
28 | XFEATURE_MASK_YMM | \ | 24 | XFEATURE_MASK_YMM | \ |
29 | XFEATURE_MASK_OPMASK | \ | 25 | XFEATURE_MASK_OPMASK | \ |
30 | XFEATURE_MASK_ZMM_Hi256 | \ | 26 | XFEATURE_MASK_ZMM_Hi256 | \ |
31 | XFEATURE_MASK_Hi16_ZMM) | 27 | XFEATURE_MASK_Hi16_ZMM) |
32 | 28 | ||
29 | /* Supported features which require eager state saving */ | ||
30 | #define XFEATURE_MASK_EAGER (XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR) | ||
31 | |||
33 | /* All currently supported features */ | 32 | /* All currently supported features */ |
34 | #define XCNTXT_MASK (XFEATURE_MASK_LAZY | XFEATURE_MASK_EAGER) | 33 | #define XCNTXT_MASK (XFEATURE_MASK_LAZY | XFEATURE_MASK_EAGER) |
35 | 34 | ||
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index d25097c3fc1d..d5804adfa6da 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c | |||
@@ -409,8 +409,10 @@ static inline void copy_init_fpstate_to_fpregs(void) | |||
409 | { | 409 | { |
410 | if (use_xsave()) | 410 | if (use_xsave()) |
411 | copy_kernel_to_xregs(&init_fpstate.xsave, -1); | 411 | copy_kernel_to_xregs(&init_fpstate.xsave, -1); |
412 | else | 412 | else if (static_cpu_has(X86_FEATURE_FXSR)) |
413 | copy_kernel_to_fxregs(&init_fpstate.fxsave); | 413 | copy_kernel_to_fxregs(&init_fpstate.fxsave); |
414 | else | ||
415 | copy_kernel_to_fregs(&init_fpstate.fsave); | ||
414 | } | 416 | } |
415 | 417 | ||
416 | /* | 418 | /* |
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c index 6d9f0a7ef4c8..bd08fb77073d 100644 --- a/arch/x86/kernel/fpu/init.c +++ b/arch/x86/kernel/fpu/init.c | |||
@@ -78,13 +78,15 @@ static void fpu__init_system_early_generic(struct cpuinfo_x86 *c) | |||
78 | cr0 &= ~(X86_CR0_TS | X86_CR0_EM); | 78 | cr0 &= ~(X86_CR0_TS | X86_CR0_EM); |
79 | write_cr0(cr0); | 79 | write_cr0(cr0); |
80 | 80 | ||
81 | asm volatile("fninit ; fnstsw %0 ; fnstcw %1" | 81 | if (!test_bit(X86_FEATURE_FPU, (unsigned long *)cpu_caps_cleared)) { |
82 | : "+m" (fsw), "+m" (fcw)); | 82 | asm volatile("fninit ; fnstsw %0 ; fnstcw %1" |
83 | : "+m" (fsw), "+m" (fcw)); | ||
83 | 84 | ||
84 | if (fsw == 0 && (fcw & 0x103f) == 0x003f) | 85 | if (fsw == 0 && (fcw & 0x103f) == 0x003f) |
85 | set_cpu_cap(c, X86_FEATURE_FPU); | 86 | set_cpu_cap(c, X86_FEATURE_FPU); |
86 | else | 87 | else |
87 | clear_cpu_cap(c, X86_FEATURE_FPU); | 88 | clear_cpu_cap(c, X86_FEATURE_FPU); |
89 | } | ||
88 | 90 | ||
89 | #ifndef CONFIG_MATH_EMULATION | 91 | #ifndef CONFIG_MATH_EMULATION |
90 | if (!cpu_has_fpu) { | 92 | if (!cpu_has_fpu) { |
@@ -132,7 +134,7 @@ static void __init fpu__init_system_generic(void) | |||
132 | * Set up the legacy init FPU context. (xstate init might overwrite this | 134 | * Set up the legacy init FPU context. (xstate init might overwrite this |
133 | * with a more modern format, if the CPU supports it.) | 135 | * with a more modern format, if the CPU supports it.) |
134 | */ | 136 | */ |
135 | fpstate_init_fxstate(&init_fpstate.fxsave); | 137 | fpstate_init(&init_fpstate); |
136 | 138 | ||
137 | fpu__init_system_mxcsr(); | 139 | fpu__init_system_mxcsr(); |
138 | } | 140 | } |
@@ -300,12 +302,6 @@ u64 __init fpu__get_supported_xfeatures_mask(void) | |||
300 | static void __init fpu__clear_eager_fpu_features(void) | 302 | static void __init fpu__clear_eager_fpu_features(void) |
301 | { | 303 | { |
302 | setup_clear_cpu_cap(X86_FEATURE_MPX); | 304 | setup_clear_cpu_cap(X86_FEATURE_MPX); |
303 | setup_clear_cpu_cap(X86_FEATURE_AVX); | ||
304 | setup_clear_cpu_cap(X86_FEATURE_AVX2); | ||
305 | setup_clear_cpu_cap(X86_FEATURE_AVX512F); | ||
306 | setup_clear_cpu_cap(X86_FEATURE_AVX512PF); | ||
307 | setup_clear_cpu_cap(X86_FEATURE_AVX512ER); | ||
308 | setup_clear_cpu_cap(X86_FEATURE_AVX512CD); | ||
309 | } | 305 | } |
310 | 306 | ||
311 | /* | 307 | /* |
diff --git a/arch/x86/lib/delay.c b/arch/x86/lib/delay.c index e912b2f6d36e..2f07c291dcc8 100644 --- a/arch/x86/lib/delay.c +++ b/arch/x86/lib/delay.c | |||
@@ -102,7 +102,7 @@ static void delay_mwaitx(unsigned long __loops) | |||
102 | * Use cpu_tss as a cacheline-aligned, seldomly | 102 | * Use cpu_tss as a cacheline-aligned, seldomly |
103 | * accessed per-cpu variable as the monitor target. | 103 | * accessed per-cpu variable as the monitor target. |
104 | */ | 104 | */ |
105 | __monitorx(this_cpu_ptr(&cpu_tss), 0, 0); | 105 | __monitorx(raw_cpu_ptr(&cpu_tss), 0, 0); |
106 | 106 | ||
107 | /* | 107 | /* |
108 | * AMD, like Intel, supports the EAX hint and EAX=0xf | 108 | * AMD, like Intel, supports the EAX hint and EAX=0xf |
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index 2d66db8f80f9..ed30e79347e8 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c | |||
@@ -131,6 +131,27 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size) | |||
131 | EXPORT_SYMBOL_GPL(efi_query_variable_store); | 131 | EXPORT_SYMBOL_GPL(efi_query_variable_store); |
132 | 132 | ||
133 | /* | 133 | /* |
134 | * Helper function for efi_reserve_boot_services() to figure out if we | ||
135 | * can free regions in efi_free_boot_services(). | ||
136 | * | ||
137 | * Use this function to ensure we do not free regions owned by somebody | ||
138 | * else. We must only reserve (and then free) regions: | ||
139 | * | ||
140 | * - Not within any part of the kernel | ||
141 | * - Not the BIOS reserved area (E820_RESERVED, E820_NVS, etc) | ||
142 | */ | ||
143 | static bool can_free_region(u64 start, u64 size) | ||
144 | { | ||
145 | if (start + size > __pa_symbol(_text) && start <= __pa_symbol(_end)) | ||
146 | return false; | ||
147 | |||
148 | if (!e820_all_mapped(start, start+size, E820_RAM)) | ||
149 | return false; | ||
150 | |||
151 | return true; | ||
152 | } | ||
153 | |||
154 | /* | ||
134 | * The UEFI specification makes it clear that the operating system is free to do | 155 | * The UEFI specification makes it clear that the operating system is free to do |
135 | * whatever it wants with boot services code after ExitBootServices() has been | 156 | * whatever it wants with boot services code after ExitBootServices() has been |
136 | * called. Ignoring this recommendation a significant bunch of EFI implementations | 157 | * called. Ignoring this recommendation a significant bunch of EFI implementations |
@@ -147,26 +168,50 @@ void __init efi_reserve_boot_services(void) | |||
147 | efi_memory_desc_t *md = p; | 168 | efi_memory_desc_t *md = p; |
148 | u64 start = md->phys_addr; | 169 | u64 start = md->phys_addr; |
149 | u64 size = md->num_pages << EFI_PAGE_SHIFT; | 170 | u64 size = md->num_pages << EFI_PAGE_SHIFT; |
171 | bool already_reserved; | ||
150 | 172 | ||
151 | if (md->type != EFI_BOOT_SERVICES_CODE && | 173 | if (md->type != EFI_BOOT_SERVICES_CODE && |
152 | md->type != EFI_BOOT_SERVICES_DATA) | 174 | md->type != EFI_BOOT_SERVICES_DATA) |
153 | continue; | 175 | continue; |
154 | /* Only reserve where possible: | 176 | |
155 | * - Not within any already allocated areas | 177 | already_reserved = memblock_is_region_reserved(start, size); |
156 | * - Not over any memory area (really needed, if above?) | 178 | |
157 | * - Not within any part of the kernel | 179 | /* |
158 | * - Not the bios reserved area | 180 | * Because the following memblock_reserve() is paired |
159 | */ | 181 | * with free_bootmem_late() for this region in |
160 | if ((start + size > __pa_symbol(_text) | 182 | * efi_free_boot_services(), we must be extremely |
161 | && start <= __pa_symbol(_end)) || | 183 | * careful not to reserve, and subsequently free, |
162 | !e820_all_mapped(start, start+size, E820_RAM) || | 184 | * critical regions of memory (like the kernel image) or |
163 | memblock_is_region_reserved(start, size)) { | 185 | * those regions that somebody else has already |
164 | /* Could not reserve, skip it */ | 186 | * reserved. |
165 | md->num_pages = 0; | 187 | * |
166 | memblock_dbg("Could not reserve boot range [0x%010llx-0x%010llx]\n", | 188 | * A good example of a critical region that must not be |
167 | start, start+size-1); | 189 | * freed is page zero (first 4Kb of memory), which may |
168 | } else | 190 | * contain boot services code/data but is marked |
191 | * E820_RESERVED by trim_bios_range(). | ||
192 | */ | ||
193 | if (!already_reserved) { | ||
169 | memblock_reserve(start, size); | 194 | memblock_reserve(start, size); |
195 | |||
196 | /* | ||
197 | * If we are the first to reserve the region, no | ||
198 | * one else cares about it. We own it and can | ||
199 | * free it later. | ||
200 | */ | ||
201 | if (can_free_region(start, size)) | ||
202 | continue; | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * We don't own the region. We must not free it. | ||
207 | * | ||
208 | * Setting this bit for a boot services region really | ||
209 | * doesn't make sense as far as the firmware is | ||
210 | * concerned, but it does provide us with a way to tag | ||
211 | * those regions that must not be paired with | ||
212 | * free_bootmem_late(). | ||
213 | */ | ||
214 | md->attribute |= EFI_MEMORY_RUNTIME; | ||
170 | } | 215 | } |
171 | } | 216 | } |
172 | 217 | ||
@@ -183,8 +228,8 @@ void __init efi_free_boot_services(void) | |||
183 | md->type != EFI_BOOT_SERVICES_DATA) | 228 | md->type != EFI_BOOT_SERVICES_DATA) |
184 | continue; | 229 | continue; |
185 | 230 | ||
186 | /* Could not reserve boot area */ | 231 | /* Do not free, someone else owns it: */ |
187 | if (!size) | 232 | if (md->attribute & EFI_MEMORY_RUNTIME) |
188 | continue; | 233 | continue; |
189 | 234 | ||
190 | free_bootmem_late(start, size); | 235 | free_bootmem_late(start, size); |