* Guest pseudo FPU container
  */
 struct fpu_guest {
+       /*
+        * @xfeatures:                  xfeature bitmap of features which are
+        *                              currently enabled for the guest vCPU.
+        */
+       u64                             xfeatures;
+
+       /*
+        * @perm:                       xfeature bitmap of features which are
+        *                              permitted to be enabled for the guest
+        *                              vCPU.
+        */
+       u64                             perm;
+
        /*
         * @fpstate:                    Pointer to the allocated guest fpstate
         */
 
 #if IS_ENABLED(CONFIG_KVM)
 static void __fpstate_reset(struct fpstate *fpstate);
 
+static void fpu_init_guest_permissions(struct fpu_guest *gfpu)
+{
+       struct fpu_state_perm *fpuperm;
+       u64 perm;
+
+       if (!IS_ENABLED(CONFIG_X86_64))
+               return;
+
+       spin_lock_irq(¤t->sighand->siglock);
+       fpuperm = ¤t->group_leader->thread.fpu.guest_perm;
+       perm = fpuperm->__state_perm;
+
+       /* First fpstate allocation locks down permissions. */
+       WRITE_ONCE(fpuperm->__state_perm, perm | FPU_GUEST_PERM_LOCKED);
+
+       spin_unlock_irq(¤t->sighand->siglock);
+
+       gfpu->perm = perm & ~FPU_GUEST_PERM_LOCKED;
+}
+
 bool fpu_alloc_guest_fpstate(struct fpu_guest *gfpu)
 {
        struct fpstate *fpstate;
        fpstate->is_valloc      = true;
        fpstate->is_guest       = true;
 
-       gfpu->fpstate = fpstate;
+       gfpu->fpstate           = fpstate;
+       gfpu->xfeatures         = fpu_user_cfg.default_features;
+       gfpu->perm              = fpu_user_cfg.default_features;
+       fpu_init_guest_permissions(gfpu);
+
        return true;
 }
 EXPORT_SYMBOL_GPL(fpu_alloc_guest_fpstate);