diff --git a/arch/x86/include/asm/fpu/types.h b/arch/x86/include/asm/fpu/types.h
index c6fd13a17205..306825ad6bc0 100644
--- a/arch/x86/include/asm/fpu/types.h
+++ b/arch/x86/include/asm/fpu/types.h
@@ -602,6 +602,6 @@ struct fpu_state_config {
 };
 
 /* FPU state configuration information */
-extern struct fpu_state_config fpu_kernel_cfg, fpu_user_cfg;
+extern struct fpu_state_config fpu_kernel_cfg, fpu_user_cfg, fpu_guest_cfg;
 
 #endif /* _ASM_X86_FPU_H */
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index a21a4d0ecc34..976f519721e2 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -33,10 +33,67 @@ DEFINE_STATIC_KEY_FALSE(__fpu_state_size_dynamic);
 DEFINE_PER_CPU(u64, xfd_state);
 #endif
 
-/* The FPU state configuration data for kernel and user space */
+/* The FPU state configuration data for kernel, user space and guest. */
+/*
+ * kernel FPU config:
+ *
+ * all known and CPU supported user and supervisor features except
+ *  - independent kernel features (XFEATURE_LBR)
+ * @fpu_kernel_cfg.max_features;
+ *
+ * all known and CPU supported user and supervisor features except
+ *  - dynamic kernel features (CET_S)
+ *  - independent kernel features (XFEATURE_LBR)
+ *  - dynamic userspace features (AMX state)
+ * @fpu_kernel_cfg.default_features;
+ *
+ * size of compacted buffer with 'fpu_kernel_cfg.max_features'
+ * @fpu_kernel_cfg.max_size;
+ *
+ * size of compacted buffer with 'fpu_kernel_cfg.default_features'
+ * @fpu_kernel_cfg.default_size;
+ */
 struct fpu_state_config	fpu_kernel_cfg __ro_after_init;
+
+/*
+ * user FPU config:
+ *
+ * all known and CPU supported user features
+ * @fpu_user_cfg.max_features;
+ *
+ * all known and CPU supported user features except
+ *  - dynamic userspace features (AMX state)
+ * @fpu_user_cfg.default_features;
+ *
+ * size of non-compacted buffer with 'fpu_user_cfg.max_features'
+ * @fpu_user_cfg.max_size;
+ *
+ * size of non-compacted buffer with 'fpu_user_cfg.default_features'
+ * @fpu_user_cfg.default_size;
+ */
 struct fpu_state_config fpu_user_cfg __ro_after_init;
 
+/*
+ * guest FPU config:
+ *
+ * all known and CPU supported user and supervisor features except
+ *  - independent  kernel features (XFEATURE_LBR)
+ * @fpu_guest_cfg.max_features;
+ *
+ * all known and CPU supported user and supervisor features except
+ *  - independent kernel features (XFEATURE_LBR)
+ *  - dynamic userspace features (AMX state)
+ * @fpu_guest_cfg.default_features;
+ *
+ * size of compacted buffer with 'fpu_guest_cfg.max_features'
+ * @fpu_guest_cfg.max_size;
+ *
+ * size of compacted buffer with 'fpu_guest_cfg.default_features'
+ * @fpu_guest_cfg.default_size;
+ */
+
+struct fpu_state_config fpu_guest_cfg __ro_after_init;
+
 /*
  * Represents the initial FPU state. It's mostly (but not completely) zeroes,
  * depending on the FPU hardware format:
@@ -536,8 +593,15 @@ void fpstate_reset(struct fpu *fpu)
 	fpu->perm.__state_perm		= fpu_kernel_cfg.default_features;
 	fpu->perm.__state_size		= fpu_kernel_cfg.default_size;
 	fpu->perm.__user_state_size	= fpu_user_cfg.default_size;
-	/* Same defaults for guests */
-	fpu->guest_perm = fpu->perm;
+
+	/* Guest permission settings */
+	fpu->guest_perm.__state_perm	= fpu_guest_cfg.default_features;
+	fpu->guest_perm.__state_size	= fpu_guest_cfg.default_size;
+	/*
+	 * Set guest's __user_state_size to fpu_user_cfg.default_size so that
+	 * existing uAPIs can still work.
+	 */
+	fpu->guest_perm.__user_state_size = fpu_user_cfg.default_size;
 }
 
 static inline void fpu_inherit_perms(struct fpu *dst_fpu)
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index ca4b83c142eb..9cbdc83d1eab 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -681,6 +681,7 @@ static int __init init_xstate_size(void)
 {
 	/* Recompute the context size for enabled features: */
 	unsigned int user_size, kernel_size, kernel_default_size;
+	unsigned int guest_default_size;
 	bool compacted = cpu_feature_enabled(X86_FEATURE_XCOMPACTED);
 
 	/* Uncompacted user space size */
@@ -702,13 +703,18 @@ static int __init init_xstate_size(void)
 	kernel_default_size =
 		xstate_calculate_size(fpu_kernel_cfg.default_features, compacted);
 
+	guest_default_size =
+		xstate_calculate_size(fpu_guest_cfg.default_features, compacted);
+
 	if (!paranoid_xstate_size_valid(kernel_size))
 		return -EINVAL;
 
 	fpu_kernel_cfg.max_size = kernel_size;
 	fpu_user_cfg.max_size = user_size;
+	fpu_guest_cfg.max_size = kernel_size;
 
 	fpu_kernel_cfg.default_size = kernel_default_size;
+	fpu_guest_cfg.default_size = guest_default_size;
 	fpu_user_cfg.default_size =
 		xstate_calculate_size(fpu_user_cfg.default_features, false);
 
@@ -829,6 +835,10 @@ void __init fpu__init_system_xstate(unsigned int legacy_size)
 	fpu_user_cfg.default_features = fpu_user_cfg.max_features;
 	fpu_user_cfg.default_features &= ~XFEATURE_MASK_USER_DYNAMIC;
 
+	fpu_guest_cfg.max_features = fpu_kernel_cfg.max_features;
+	fpu_guest_cfg.default_features = fpu_guest_cfg.max_features;
+	fpu_guest_cfg.default_features &= ~XFEATURE_MASK_USER_DYNAMIC;
+
 	/* Store it for paranoia check at the end */
 	xfeatures = fpu_kernel_cfg.max_features;
 
