@@ -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;
}