diff mbox series

[RFC,6/8] x86/fpu: update xstate size calculations for non-XSAVE-managed features

Message ID 20210622222506.487B6DF3@viggo.jf.intel.com (mailing list archive)
State New
Headers show
Series x86/pkeys: remove PKRU from kernel XSAVE buffer | expand

Commit Message

Dave Hansen June 22, 2021, 10:25 p.m. UTC
From: Dave Hansen <dave.hansen@linux.intel.com>

Now that PKRU will no longer be XSAVE-managed, it needs to be removed
from the XSAVE size calculations.  get_xsaves_size_no_independent()
currently masks independent supervisor features out of XSS, but PKRU
must be masked out of XCR0 instead.

Also, instead of recalculating XSS (and XCR0), just save and restore
them.  This will be more durable in case there are any future changes
to how they are calculated.  The way it is now, the values must be
recalculated exactly in two separate places.

The save/restore approach also makes the code more obvious.  For
instance, the old code does:

	/* Disable independent features. */
	wrmsrl(MSR_IA32_XSS, xfeatures_mask_supervisor());

but the new code does:

	/* Disable independent features. */
	wrmsrl(MSR_IA32_XSS, old_xss & ~xfeatures_mask_independent());

The second is much more obviously correct and the comment could
probably even be removed; it's basically self-documenting.

There is a minor, temporary hack in here.  PKRU is currently not in
xfeatures_mask_fpstate(), even though it is allocated in the fpstate.
To avoid size mismatch warnings, hack it into XCR0 for the size

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: x86@kernel.org
Cc: Andy Lutomirski <luto@kernel.org>

 b/arch/x86/kernel/fpu/xstate.c |   25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)
diff mbox series


diff -puN arch/x86/kernel/fpu/xstate.c~xsave-checks arch/x86/kernel/fpu/xstate.c
--- a/arch/x86/kernel/fpu/xstate.c~xsave-checks	2021-06-22 14:49:12.547051748 -0700
+++ b/arch/x86/kernel/fpu/xstate.c	2021-06-22 14:49:12.556051748 -0700
@@ -643,14 +643,26 @@  static unsigned int __init get_xsaves_si
 static unsigned int __init get_xsaves_size_no_independent(void)
-	u64 mask = xfeatures_mask_independent();
 	unsigned int size;
+	u64 xfeatures_in_xcr0;
+	u64 old_xss;
+	u64 old_xcr0;
-	if (!mask)
-		return get_xsaves_size();
+	/* Stash the old XSAVE control register values: */
+	rdmsrl(MSR_IA32_XSS, old_xss);
+	old_xcr0 = xgetbv(0);
 	/* Disable independent features. */
-	wrmsrl(MSR_IA32_XSS, xfeatures_mask_supervisor());
+	wrmsrl(MSR_IA32_XSS, old_xss & ~xfeatures_mask_independent());
+	/*
+	 * *Temporarily* (to be removed in a later patch), ennsure there
+	 * is still space for PKRU in the fpstate buffer even though it's
+	 * essentially unused.
+	 */
+	xfeatures_in_xcr0 = xfeatures_mask_fpstate() | XFEATURE_MASK_PKRU;
+	/* Disable user features which are not kept in the fpstate: */
+	xsetbv(XCR_XFEATURE_ENABLED_MASK, old_xcr0 & xfeatures_in_xcr0);
 	 * Ask the hardware what size is required of the buffer.
@@ -658,8 +670,9 @@  static unsigned int __init get_xsaves_si
 	size = get_xsaves_size();
-	/* Re-enable independent features so XSAVES will work on them again. */
-	wrmsrl(MSR_IA32_XSS, xfeatures_mask_supervisor() | mask);
+	/* Re-enable original features so XSAVES will work on them again. */
+	wrmsrl(MSR_IA32_XSS, old_xss);
+	xsetbv(XCR_XFEATURE_ENABLED_MASK, old_xcr0);
 	return size;