aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-03-12 23:09:25 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-03-12 23:09:25 -0500
commit2f51c8204ab3ea211ac92f3b7b88a38595ed6412 (patch)
treeb872e12090ea271ea951f2446e840dc4d0f52e43
parentfda604a4daa19ead458ce5471892fa1d4b382d82 (diff)
parent452308de61056a539352a9306c46716d7af8a1f1 (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.h9
-rw-r--r--arch/x86/kernel/fpu/core.c4
-rw-r--r--arch/x86/kernel/fpu/init.c22
-rw-r--r--arch/x86/lib/delay.c2
-rw-r--r--arch/x86/platform/efi/quirks.c79
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)
300static void __init fpu__clear_eager_fpu_features(void) 302static 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)
131EXPORT_SYMBOL_GPL(efi_query_variable_store); 131EXPORT_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 */
143static 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);