mirror of https://gitee.com/openkylin/linux.git
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
This commit is contained in:
commit
2f51c8204a
|
@ -20,16 +20,15 @@
|
|||
|
||||
/* Supported features which support lazy state saving */
|
||||
#define XFEATURE_MASK_LAZY (XFEATURE_MASK_FP | \
|
||||
XFEATURE_MASK_SSE)
|
||||
|
||||
/* Supported features which require eager state saving */
|
||||
#define XFEATURE_MASK_EAGER (XFEATURE_MASK_BNDREGS | \
|
||||
XFEATURE_MASK_BNDCSR | \
|
||||
XFEATURE_MASK_SSE | \
|
||||
XFEATURE_MASK_YMM | \
|
||||
XFEATURE_MASK_OPMASK | \
|
||||
XFEATURE_MASK_ZMM_Hi256 | \
|
||||
XFEATURE_MASK_Hi16_ZMM)
|
||||
|
||||
/* Supported features which require eager state saving */
|
||||
#define XFEATURE_MASK_EAGER (XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR)
|
||||
|
||||
/* All currently supported features */
|
||||
#define XCNTXT_MASK (XFEATURE_MASK_LAZY | XFEATURE_MASK_EAGER)
|
||||
|
||||
|
|
|
@ -409,8 +409,10 @@ static inline void copy_init_fpstate_to_fpregs(void)
|
|||
{
|
||||
if (use_xsave())
|
||||
copy_kernel_to_xregs(&init_fpstate.xsave, -1);
|
||||
else
|
||||
else if (static_cpu_has(X86_FEATURE_FXSR))
|
||||
copy_kernel_to_fxregs(&init_fpstate.fxsave);
|
||||
else
|
||||
copy_kernel_to_fregs(&init_fpstate.fsave);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -78,13 +78,15 @@ static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
|
|||
cr0 &= ~(X86_CR0_TS | X86_CR0_EM);
|
||||
write_cr0(cr0);
|
||||
|
||||
asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
|
||||
: "+m" (fsw), "+m" (fcw));
|
||||
if (!test_bit(X86_FEATURE_FPU, (unsigned long *)cpu_caps_cleared)) {
|
||||
asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
|
||||
: "+m" (fsw), "+m" (fcw));
|
||||
|
||||
if (fsw == 0 && (fcw & 0x103f) == 0x003f)
|
||||
set_cpu_cap(c, X86_FEATURE_FPU);
|
||||
else
|
||||
clear_cpu_cap(c, X86_FEATURE_FPU);
|
||||
if (fsw == 0 && (fcw & 0x103f) == 0x003f)
|
||||
set_cpu_cap(c, X86_FEATURE_FPU);
|
||||
else
|
||||
clear_cpu_cap(c, X86_FEATURE_FPU);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_MATH_EMULATION
|
||||
if (!cpu_has_fpu) {
|
||||
|
@ -132,7 +134,7 @@ static void __init fpu__init_system_generic(void)
|
|||
* Set up the legacy init FPU context. (xstate init might overwrite this
|
||||
* with a more modern format, if the CPU supports it.)
|
||||
*/
|
||||
fpstate_init_fxstate(&init_fpstate.fxsave);
|
||||
fpstate_init(&init_fpstate);
|
||||
|
||||
fpu__init_system_mxcsr();
|
||||
}
|
||||
|
@ -300,12 +302,6 @@ u64 __init fpu__get_supported_xfeatures_mask(void)
|
|||
static void __init fpu__clear_eager_fpu_features(void)
|
||||
{
|
||||
setup_clear_cpu_cap(X86_FEATURE_MPX);
|
||||
setup_clear_cpu_cap(X86_FEATURE_AVX);
|
||||
setup_clear_cpu_cap(X86_FEATURE_AVX2);
|
||||
setup_clear_cpu_cap(X86_FEATURE_AVX512F);
|
||||
setup_clear_cpu_cap(X86_FEATURE_AVX512PF);
|
||||
setup_clear_cpu_cap(X86_FEATURE_AVX512ER);
|
||||
setup_clear_cpu_cap(X86_FEATURE_AVX512CD);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -102,7 +102,7 @@ static void delay_mwaitx(unsigned long __loops)
|
|||
* Use cpu_tss as a cacheline-aligned, seldomly
|
||||
* accessed per-cpu variable as the monitor target.
|
||||
*/
|
||||
__monitorx(this_cpu_ptr(&cpu_tss), 0, 0);
|
||||
__monitorx(raw_cpu_ptr(&cpu_tss), 0, 0);
|
||||
|
||||
/*
|
||||
* AMD, like Intel, supports the EAX hint and EAX=0xf
|
||||
|
|
|
@ -130,6 +130,27 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(efi_query_variable_store);
|
||||
|
||||
/*
|
||||
* Helper function for efi_reserve_boot_services() to figure out if we
|
||||
* can free regions in efi_free_boot_services().
|
||||
*
|
||||
* Use this function to ensure we do not free regions owned by somebody
|
||||
* else. We must only reserve (and then free) regions:
|
||||
*
|
||||
* - Not within any part of the kernel
|
||||
* - Not the BIOS reserved area (E820_RESERVED, E820_NVS, etc)
|
||||
*/
|
||||
static bool can_free_region(u64 start, u64 size)
|
||||
{
|
||||
if (start + size > __pa_symbol(_text) && start <= __pa_symbol(_end))
|
||||
return false;
|
||||
|
||||
if (!e820_all_mapped(start, start+size, E820_RAM))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The UEFI specification makes it clear that the operating system is free to do
|
||||
* whatever it wants with boot services code after ExitBootServices() has been
|
||||
|
@ -147,26 +168,50 @@ void __init efi_reserve_boot_services(void)
|
|||
efi_memory_desc_t *md = p;
|
||||
u64 start = md->phys_addr;
|
||||
u64 size = md->num_pages << EFI_PAGE_SHIFT;
|
||||
bool already_reserved;
|
||||
|
||||
if (md->type != EFI_BOOT_SERVICES_CODE &&
|
||||
md->type != EFI_BOOT_SERVICES_DATA)
|
||||
continue;
|
||||
/* Only reserve where possible:
|
||||
* - Not within any already allocated areas
|
||||
* - Not over any memory area (really needed, if above?)
|
||||
* - Not within any part of the kernel
|
||||
* - Not the bios reserved area
|
||||
*/
|
||||
if ((start + size > __pa_symbol(_text)
|
||||
&& start <= __pa_symbol(_end)) ||
|
||||
!e820_all_mapped(start, start+size, E820_RAM) ||
|
||||
memblock_is_region_reserved(start, size)) {
|
||||
/* Could not reserve, skip it */
|
||||
md->num_pages = 0;
|
||||
memblock_dbg("Could not reserve boot range [0x%010llx-0x%010llx]\n",
|
||||
start, start+size-1);
|
||||
} else
|
||||
|
||||
already_reserved = memblock_is_region_reserved(start, size);
|
||||
|
||||
/*
|
||||
* Because the following memblock_reserve() is paired
|
||||
* with free_bootmem_late() for this region in
|
||||
* efi_free_boot_services(), we must be extremely
|
||||
* careful not to reserve, and subsequently free,
|
||||
* critical regions of memory (like the kernel image) or
|
||||
* those regions that somebody else has already
|
||||
* reserved.
|
||||
*
|
||||
* A good example of a critical region that must not be
|
||||
* freed is page zero (first 4Kb of memory), which may
|
||||
* contain boot services code/data but is marked
|
||||
* E820_RESERVED by trim_bios_range().
|
||||
*/
|
||||
if (!already_reserved) {
|
||||
memblock_reserve(start, size);
|
||||
|
||||
/*
|
||||
* If we are the first to reserve the region, no
|
||||
* one else cares about it. We own it and can
|
||||
* free it later.
|
||||
*/
|
||||
if (can_free_region(start, size))
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't own the region. We must not free it.
|
||||
*
|
||||
* Setting this bit for a boot services region really
|
||||
* doesn't make sense as far as the firmware is
|
||||
* concerned, but it does provide us with a way to tag
|
||||
* those regions that must not be paired with
|
||||
* free_bootmem_late().
|
||||
*/
|
||||
md->attribute |= EFI_MEMORY_RUNTIME;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,8 +228,8 @@ void __init efi_free_boot_services(void)
|
|||
md->type != EFI_BOOT_SERVICES_DATA)
|
||||
continue;
|
||||
|
||||
/* Could not reserve boot area */
|
||||
if (!size)
|
||||
/* Do not free, someone else owns it: */
|
||||
if (md->attribute & EFI_MEMORY_RUNTIME)
|
||||
continue;
|
||||
|
||||
free_bootmem_late(start, size);
|
||||
|
|
Loading…
Reference in New Issue