Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2f51c820 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents fda604a4 452308de
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -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)

+3 −1
Original line number Diff line number Diff line
@@ -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);
}

/*
+9 −13
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
	cr0 &= ~(X86_CR0_TS | X86_CR0_EM);
	write_cr0(cr0);

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

@@ -85,6 +86,7 @@ static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
			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);
}

/*
+1 −1
Original line number Diff line number Diff line
@@ -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
+62 −17
Original line number Diff line number Diff line
@@ -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

		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 ((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
		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);