Skip to content

Commit 2f51c82

Browse files
committed
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
2 parents fda604a + 452308d commit 2f51c82

File tree

5 files changed

+79
-37
lines changed

5 files changed

+79
-37
lines changed

arch/x86/include/asm/fpu/xstate.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,15 @@
2020

2121
/* Supported features which support lazy state saving */
2222
#define XFEATURE_MASK_LAZY (XFEATURE_MASK_FP | \
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 | \
23+
XFEATURE_MASK_SSE | \
2824
XFEATURE_MASK_YMM | \
2925
XFEATURE_MASK_OPMASK | \
3026
XFEATURE_MASK_ZMM_Hi256 | \
3127
XFEATURE_MASK_Hi16_ZMM)
3228

29+
/* Supported features which require eager state saving */
30+
#define XFEATURE_MASK_EAGER (XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR)
31+
3332
/* All currently supported features */
3433
#define XCNTXT_MASK (XFEATURE_MASK_LAZY | XFEATURE_MASK_EAGER)
3534

arch/x86/kernel/fpu/core.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,8 +409,10 @@ static inline void copy_init_fpstate_to_fpregs(void)
409409
{
410410
if (use_xsave())
411411
copy_kernel_to_xregs(&init_fpstate.xsave, -1);
412-
else
412+
else if (static_cpu_has(X86_FEATURE_FXSR))
413413
copy_kernel_to_fxregs(&init_fpstate.fxsave);
414+
else
415+
copy_kernel_to_fregs(&init_fpstate.fsave);
414416
}
415417

416418
/*

arch/x86/kernel/fpu/init.c

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,15 @@ static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
7878
cr0 &= ~(X86_CR0_TS | X86_CR0_EM);
7979
write_cr0(cr0);
8080

81-
asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
82-
: "+m" (fsw), "+m" (fcw));
81+
if (!test_bit(X86_FEATURE_FPU, (unsigned long *)cpu_caps_cleared)) {
82+
asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
83+
: "+m" (fsw), "+m" (fcw));
8384

84-
if (fsw == 0 && (fcw & 0x103f) == 0x003f)
85-
set_cpu_cap(c, X86_FEATURE_FPU);
86-
else
87-
clear_cpu_cap(c, X86_FEATURE_FPU);
85+
if (fsw == 0 && (fcw & 0x103f) == 0x003f)
86+
set_cpu_cap(c, X86_FEATURE_FPU);
87+
else
88+
clear_cpu_cap(c, X86_FEATURE_FPU);
89+
}
8890

8991
#ifndef CONFIG_MATH_EMULATION
9092
if (!cpu_has_fpu) {
@@ -132,7 +134,7 @@ static void __init fpu__init_system_generic(void)
132134
* Set up the legacy init FPU context. (xstate init might overwrite this
133135
* with a more modern format, if the CPU supports it.)
134136
*/
135-
fpstate_init_fxstate(&init_fpstate.fxsave);
137+
fpstate_init(&init_fpstate);
136138

137139
fpu__init_system_mxcsr();
138140
}
@@ -300,12 +302,6 @@ u64 __init fpu__get_supported_xfeatures_mask(void)
300302
static void __init fpu__clear_eager_fpu_features(void)
301303
{
302304
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);
309305
}
310306

311307
/*

arch/x86/lib/delay.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ static void delay_mwaitx(unsigned long __loops)
102102
* Use cpu_tss as a cacheline-aligned, seldomly
103103
* accessed per-cpu variable as the monitor target.
104104
*/
105-
__monitorx(this_cpu_ptr(&cpu_tss), 0, 0);
105+
__monitorx(raw_cpu_ptr(&cpu_tss), 0, 0);
106106

107107
/*
108108
* AMD, like Intel, supports the EAX hint and EAX=0xf

arch/x86/platform/efi/quirks.c

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,27 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
130130
}
131131
EXPORT_SYMBOL_GPL(efi_query_variable_store);
132132

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+
133154
/*
134155
* The UEFI specification makes it clear that the operating system is free to do
135156
* whatever it wants with boot services code after ExitBootServices() has been
@@ -147,26 +168,50 @@ void __init efi_reserve_boot_services(void)
147168
efi_memory_desc_t *md = p;
148169
u64 start = md->phys_addr;
149170
u64 size = md->num_pages << EFI_PAGE_SHIFT;
171+
bool already_reserved;
150172

151173
if (md->type != EFI_BOOT_SERVICES_CODE &&
152174
md->type != EFI_BOOT_SERVICES_DATA)
153175
continue;
154-
/* Only reserve where possible:
155-
* - Not within any already allocated areas
156-
* - Not over any memory area (really needed, if above?)
157-
* - Not within any part of the kernel
158-
* - Not the bios reserved area
159-
*/
160-
if ((start + size > __pa_symbol(_text)
161-
&& start <= __pa_symbol(_end)) ||
162-
!e820_all_mapped(start, start+size, E820_RAM) ||
163-
memblock_is_region_reserved(start, size)) {
164-
/* Could not reserve, skip it */
165-
md->num_pages = 0;
166-
memblock_dbg("Could not reserve boot range [0x%010llx-0x%010llx]\n",
167-
start, start+size-1);
168-
} else
176+
177+
already_reserved = memblock_is_region_reserved(start, size);
178+
179+
/*
180+
* Because the following memblock_reserve() is paired
181+
* with free_bootmem_late() for this region in
182+
* efi_free_boot_services(), we must be extremely
183+
* careful not to reserve, and subsequently free,
184+
* critical regions of memory (like the kernel image) or
185+
* those regions that somebody else has already
186+
* reserved.
187+
*
188+
* A good example of a critical region that must not be
189+
* freed is page zero (first 4Kb of memory), which may
190+
* contain boot services code/data but is marked
191+
* E820_RESERVED by trim_bios_range().
192+
*/
193+
if (!already_reserved) {
169194
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;
170215
}
171216
}
172217

@@ -183,8 +228,8 @@ void __init efi_free_boot_services(void)
183228
md->type != EFI_BOOT_SERVICES_DATA)
184229
continue;
185230

186-
/* Could not reserve boot area */
187-
if (!size)
231+
/* Do not free, someone else owns it: */
232+
if (md->attribute & EFI_MEMORY_RUNTIME)
188233
continue;
189234

190235
free_bootmem_late(start, size);

0 commit comments

Comments
 (0)