Commit 2848ff28 authored by Mitchell Levy's avatar Mitchell Levy Committed by Thomas Gleixner
Browse files

x86/fpu: Avoid writing LBR bit to IA32_XSS unless supported



There are two distinct CPU features related to the use of XSAVES and LBR:
whether LBR is itself supported and whether XSAVES supports LBR. The LBR
subsystem correctly checks both in intel_pmu_arch_lbr_init(), but the
XSTATE subsystem does not.

The LBR bit is only removed from xfeatures_mask_independent when LBR is not
supported by the CPU, but there is no validation of XSTATE support.

If XSAVES does not support LBR the write to IA32_XSS causes a #GP fault,
leaving the state of IA32_XSS unchanged, i.e. zero. The fault is handled
with a warning and the boot continues.

Consequently the next XRSTORS which tries to restore supervisor state fails
with #GP because the RFBM has zero for all supervisor features, which does
not match the XCOMP_BV field.

As XFEATURE_MASK_FPSTATE includes supervisor features setting up the FPU
causes a #GP, which ends up in fpu_reset_from_exception_fixup(). That fails
due to the same problem resulting in recursive #GPs until the kernel runs
out of stack space and double faults.

Prevent this by storing the supported independent features in
fpu_kernel_cfg during XSTATE initialization and use that cached value for
retrieving the independent feature bits to be written into IA32_XSS.

[ tglx: Massaged change log ]

Fixes: f0dccc9d ("x86/fpu/xstate: Support dynamic supervisor feature for LBR")
Suggested-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarMitchell Levy <levymitchell0@gmail.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/all/20240812-xsave-lbr-fix-v3-1-95bac1bf62f4@gmail.com
parent 0ecc5be2
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -591,6 +591,13 @@ struct fpu_state_config {
	 * even without XSAVE support, i.e. legacy features FP + SSE
	 */
	u64 legacy_features;
	/*
	 * @independent_features:
	 *
	 * Features that are supported by XSAVES, but not managed as part of
	 * the FPU core, such as LBR
	 */
	u64 independent_features;
};

/* FPU state configuration information */
+3 −0
Original line number Diff line number Diff line
@@ -788,6 +788,9 @@ void __init fpu__init_system_xstate(unsigned int legacy_size)
		goto out_disable;
	}

	fpu_kernel_cfg.independent_features = fpu_kernel_cfg.max_features &
					      XFEATURE_MASK_INDEPENDENT;

	/*
	 * Clear XSAVE features that are disabled in the normal CPUID.
	 */
+2 −2
Original line number Diff line number Diff line
@@ -62,9 +62,9 @@ static inline u64 xfeatures_mask_supervisor(void)
static inline u64 xfeatures_mask_independent(void)
{
	if (!cpu_feature_enabled(X86_FEATURE_ARCH_LBR))
		return XFEATURE_MASK_INDEPENDENT & ~XFEATURE_MASK_LBR;
		return fpu_kernel_cfg.independent_features & ~XFEATURE_MASK_LBR;

	return XFEATURE_MASK_INDEPENDENT;
	return fpu_kernel_cfg.independent_features;
}

/* XSAVE/XRSTOR wrapper functions */