* Non-compacted format and legacy features use the cached fixed
         * offsets.
         */
-       if (!cpu_feature_enabled(X86_FEATURE_XSAVES) || xfeature <= XFEATURE_SSE)
+       if (!cpu_feature_enabled(X86_FEATURE_XCOMPACTED) ||
+           xfeature <= XFEATURE_SSE)
                return xstate_offsets[xfeature];
 
        /*
        /*
         * All components are now in init state. Read the state back so
         * that init_fpstate contains all non-zero init state. This only
-        * works with XSAVE, but not with XSAVEOPT and XSAVES because
+        * works with XSAVE, but not with XSAVEOPT and XSAVEC/S because
         * those use the init optimization which skips writing data for
         * components in init state.
         *
         * XSAVE could be used, but that would require to reshuffle the
-        * data when XSAVES is available because XSAVES uses xstate
+        * data when XSAVEC/S is available because XSAVEC/S uses xstate
         * compaction. But doing so is a pointless exercise because most
         * components have an all zeros init state except for the legacy
         * ones (FP and SSE). Those can be saved with FXSAVE into the
  */
 static bool __init paranoid_xstate_size_valid(unsigned int kernel_size)
 {
-       bool compacted = cpu_feature_enabled(X86_FEATURE_XSAVES);
+       bool compacted = cpu_feature_enabled(X86_FEATURE_XCOMPACTED);
+       bool xsaves = cpu_feature_enabled(X86_FEATURE_XSAVES);
        unsigned int size = FXSAVE_SIZE + XSAVE_HDR_SIZE;
        int i;
 
                 * Supervisor state components can be managed only by
                 * XSAVES.
                 */
-               if (!compacted && xfeature_is_supervisor(i)) {
+               if (!xsaves && xfeature_is_supervisor(i)) {
                        XSTATE_WARN_ON(1);
                        return false;
                }
  * the size of the *user* states.  If we use it to size a buffer
  * that we use 'XSAVES' on, we could potentially overflow the
  * buffer because 'XSAVES' saves system states too.
+ *
+ * This also takes compaction into account. So this works for
+ * XSAVEC as well.
  */
-static unsigned int __init get_xsaves_size(void)
+static unsigned int __init get_compacted_size(void)
 {
        unsigned int eax, ebx, ecx, edx;
        /*
         *    containing all the state components
         *    corresponding to bits currently set in
         *    XCR0 | IA32_XSS.
+        *
+        * When XSAVES is not available but XSAVEC is (virt), then there
+        * are no supervisor states, but XSAVEC still uses compacted
+        * format.
         */
        cpuid_count(XSTATE_CPUID, 1, &eax, &ebx, &ecx, &edx);
        return ebx;
  * Get the total size of the enabled xstates without the independent supervisor
  * features.
  */
-static unsigned int __init get_xsaves_size_no_independent(void)
+static unsigned int __init get_xsave_compacted_size(void)
 {
        u64 mask = xfeatures_mask_independent();
        unsigned int size;
 
        if (!mask)
-               return get_xsaves_size();
+               return get_compacted_size();
 
        /* Disable independent features. */
        wrmsrl(MSR_IA32_XSS, xfeatures_mask_supervisor());
         * Ask the hardware what size is required of the buffer.
         * This is the size required for the task->fpu buffer.
         */
-       size = get_xsaves_size();
+       size = get_compacted_size();
 
        /* Re-enable independent features so XSAVES will work on them again. */
        wrmsrl(MSR_IA32_XSS, xfeatures_mask_supervisor() | mask);
 {
        /* Recompute the context size for enabled features: */
        unsigned int user_size, kernel_size, kernel_default_size;
-       bool compacted = cpu_feature_enabled(X86_FEATURE_XSAVES);
+       bool compacted = cpu_feature_enabled(X86_FEATURE_XCOMPACTED);
 
        /* Uncompacted user space size */
        user_size = get_xsave_size_user();
 
        /*
-        * XSAVES kernel size includes supervisor states and
-        * uses compacted format when available.
+        * XSAVES kernel size includes supervisor states and uses compacted
+        * format. XSAVEC uses compacted format, but does not save
+        * supervisor states.
         *
-        * XSAVE does not support supervisor states so
-        * kernel and user size is identical.
+        * XSAVE[OPT] do not support supervisor states so kernel and user
+        * size is identical.
         */
        if (compacted)
-               kernel_size = get_xsaves_size_no_independent();
+               kernel_size = get_xsave_compacted_size();
        else
                kernel_size = user_size;
 
        if (!cpu_feature_enabled(X86_FEATURE_XFD))
                fpu_kernel_cfg.max_features &= ~XFEATURE_MASK_USER_DYNAMIC;
 
-       fpu_kernel_cfg.max_features &= XFEATURE_MASK_USER_SUPPORTED |
-                             XFEATURE_MASK_SUPERVISOR_SUPPORTED;
+       if (!cpu_feature_enabled(X86_FEATURE_XSAVES))
+               fpu_kernel_cfg.max_features &= XFEATURE_MASK_USER_SUPPORTED;
+       else
+               fpu_kernel_cfg.max_features &= XFEATURE_MASK_USER_SUPPORTED |
+                                       XFEATURE_MASK_SUPERVISOR_SUPPORTED;
 
        fpu_user_cfg.max_features = fpu_kernel_cfg.max_features;
        fpu_user_cfg.max_features &= XFEATURE_MASK_USER_SUPPORTED;
         */
        init_fpstate.xfd = fpu_user_cfg.max_features & XFEATURE_MASK_USER_DYNAMIC;
 
+       /* Set up compaction feature bit */
+       if (cpu_feature_enabled(X86_FEATURE_XSAVEC) ||
+           cpu_feature_enabled(X86_FEATURE_XSAVES))
+               setup_force_cpu_cap(X86_FEATURE_XCOMPACTED);
+
        /* Enable xstate instructions to be able to continue with initialization: */
        fpu__init_cpu_xstate();
 
        pr_info("x86/fpu: Enabled xstate features 0x%llx, context size is %d bytes, using '%s' format.\n",
                fpu_kernel_cfg.max_features,
                fpu_kernel_cfg.max_size,
-               boot_cpu_has(X86_FEATURE_XSAVES) ? "compacted" : "standard");
+               boot_cpu_has(X86_FEATURE_XCOMPACTED) ? "compacted" : "standard");
        return;
 
 out_disable:
        if (WARN_ON_ONCE(!xfeature_enabled(xfeature_nr)))
                return NULL;
 
-       if (cpu_feature_enabled(X86_FEATURE_XSAVES)) {
+       if (cpu_feature_enabled(X86_FEATURE_XCOMPACTED)) {
                if (WARN_ON_ONCE(!(xcomp_bv & BIT_ULL(xfeature_nr))))
                        return NULL;
        }
         * vendors into extending XFD for the pre AMX states, especially
         * AVX512.
         */
-       bool compacted = cpu_feature_enabled(X86_FEATURE_XSAVES);
+       bool compacted = cpu_feature_enabled(X86_FEATURE_XCOMPACTED);
        struct fpu *fpu = ¤t->group_leader->thread.fpu;
        struct fpu_state_perm *perm;
        unsigned int ksize, usize;
 
         * XRSTORS requires these bits set in xcomp_bv, or it will
         * trigger #GP:
         */
-       if (cpu_feature_enabled(X86_FEATURE_XSAVES))
+       if (cpu_feature_enabled(X86_FEATURE_XCOMPACTED))
                xsave->header.xcomp_bv = mask | XCOMP_BV_COMPACTED_FORMAT;
 }
 
 /* These macros all use (%edi)/(%rdi) as the single memory argument. */
 #define XSAVE          ".byte " REX_PREFIX "0x0f,0xae,0x27"
 #define XSAVEOPT       ".byte " REX_PREFIX "0x0f,0xae,0x37"
+#define XSAVEC         ".byte " REX_PREFIX "0x0f,0xc7,0x27"
 #define XSAVES         ".byte " REX_PREFIX "0x0f,0xc7,0x2f"
 #define XRSTOR         ".byte " REX_PREFIX "0x0f,0xae,0x2f"
 #define XRSTORS                ".byte " REX_PREFIX "0x0f,0xc7,0x1f"
                     : "memory")
 
 /*
- * If XSAVES is enabled, it replaces XSAVEOPT because it supports a compact
- * format and supervisor states in addition to modified optimization in
- * XSAVEOPT.
+ * If XSAVES is enabled, it replaces XSAVEC because it supports supervisor
+ * states in addition to XSAVEC.
+ *
+ * Otherwise if XSAVEC is enabled, it replaces XSAVEOPT because it supports
+ * compacted storage format in addition to XSAVEOPT.
  *
  * Otherwise, if XSAVEOPT is enabled, XSAVEOPT replaces XSAVE because XSAVEOPT
  * supports modified optimization which is not supported by XSAVE.
  * address of the instruction where we might get an exception at.
  */
 #define XSTATE_XSAVE(st, lmask, hmask, err)                            \
-       asm volatile(ALTERNATIVE_2(XSAVE,                               \
+       asm volatile(ALTERNATIVE_3(XSAVE,                               \
                                   XSAVEOPT, X86_FEATURE_XSAVEOPT,      \
+                                  XSAVEC,   X86_FEATURE_XSAVEC,        \
                                   XSAVES,   X86_FEATURE_XSAVES)        \
                     "\n"                                               \
                     "xor %[err], %[err]\n"                             \