Skip to content

Commit 7bc4ed7

Browse files
gaochaointelhansendc
authored andcommitted
x86/fpu/xstate: Differentiate default features for host and guest FPUs
Currently, guest and host FPUs share the same default features. However, the CET supervisor xstate is the first feature that needs to be enabled exclusively for guest FPUs. Enabling it for host FPUs leads to a waste of 24 bytes in the XSAVE buffer. To support "guest-only" features, add a new structure to hold the default features and sizes for guest FPUs to clearly differentiate them from those for host FPUs. Add two helpers to provide the default feature masks for guest and host FPUs. Default features are derived by applying the masks to the maximum supported features. Note that, 1) for now, guest_default_mask() and host_default_mask() are identical. This will change in a follow-up patch once guest permissions, default xfeatures, and fpstate size are all converted to use the guest defaults. 2) only supervisor features will diverge between guest FPUs and host FPUs, while user features will remain the same [1][2]. So, the new vcpu_fpu_config struct does not include default user features and size for the UABI buffer. An alternative approach is adding a guest_only_xfeatures member to fpu_kernel_cfg and adding two helper functions to calculate the guest default xfeatures and size. However, calculating these defaults at runtime would introduce unnecessary overhead. Suggested-by: Chang S. Bae <[email protected]> Suggested-by: Sean Christopherson <[email protected]> Signed-off-by: Chao Gao <[email protected]> Signed-off-by: Dave Hansen <[email protected]> Reviewed-by: John Allen <[email protected]> Link: https://lore.kernel.org/kvm/[email protected]/ [1] Link: https://lore.kernel.org/kvm/[email protected]/ [2] Link: https://lore.kernel.org/all/20250522151031.426788-2-chao.gao%40intel.com
1 parent 86731a2 commit 7bc4ed7

File tree

4 files changed

+54
-6
lines changed

4 files changed

+54
-6
lines changed

arch/x86/include/asm/fpu/types.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,31 @@ struct fpu_guest {
551551
struct fpstate *fpstate;
552552
};
553553

554+
/*
555+
* FPU state configuration data for fpu_guest.
556+
* Initialized at boot time. Read only after init.
557+
*/
558+
struct vcpu_fpu_config {
559+
/*
560+
* @size:
561+
*
562+
* The default size of the register state buffer in guest FPUs.
563+
* Includes all supported features except independent managed
564+
* features and features which have to be requested by user space
565+
* before usage.
566+
*/
567+
unsigned int size;
568+
569+
/*
570+
* @features:
571+
*
572+
* The default supported features bitmap in guest FPUs. Does not
573+
* include independent managed features and features which have to
574+
* be requested by user space before usage.
575+
*/
576+
u64 features;
577+
};
578+
554579
/*
555580
* FPU state configuration data. Initialized at boot time. Read only after init.
556581
*/
@@ -606,5 +631,6 @@ struct fpu_state_config {
606631

607632
/* FPU state configuration information */
608633
extern struct fpu_state_config fpu_kernel_cfg, fpu_user_cfg;
634+
extern struct vcpu_fpu_config guest_default_cfg;
609635

610636
#endif /* _ASM_X86_FPU_TYPES_H */

arch/x86/kernel/fpu/core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ DEFINE_PER_CPU(u64, xfd_state);
3737
/* The FPU state configuration data for kernel and user space */
3838
struct fpu_state_config fpu_kernel_cfg __ro_after_init;
3939
struct fpu_state_config fpu_user_cfg __ro_after_init;
40+
struct vcpu_fpu_config guest_default_cfg __ro_after_init;
4041

4142
/*
4243
* Represents the initial FPU state. It's mostly (but not completely) zeroes,

arch/x86/kernel/fpu/init.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ static void __init fpu__init_system_xstate_size_legacy(void)
205205
fpu_kernel_cfg.default_size = size;
206206
fpu_user_cfg.max_size = size;
207207
fpu_user_cfg.default_size = size;
208+
guest_default_cfg.size = size;
208209
}
209210

210211
/*

arch/x86/kernel/fpu/xstate.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,9 @@ static int __init init_xstate_size(void)
743743
fpu_user_cfg.default_size =
744744
xstate_calculate_size(fpu_user_cfg.default_features, false);
745745

746+
guest_default_cfg.size =
747+
xstate_calculate_size(guest_default_cfg.features, compacted);
748+
746749
return 0;
747750
}
748751

@@ -763,6 +766,7 @@ static void __init fpu__init_disable_system_xstate(unsigned int legacy_size)
763766
fpu_kernel_cfg.default_size = legacy_size;
764767
fpu_user_cfg.max_size = legacy_size;
765768
fpu_user_cfg.default_size = legacy_size;
769+
guest_default_cfg.size = legacy_size;
766770

767771
/*
768772
* Prevent enabling the static branch which enables writes to the
@@ -773,6 +777,21 @@ static void __init fpu__init_disable_system_xstate(unsigned int legacy_size)
773777
fpstate_reset(x86_task_fpu(current));
774778
}
775779

780+
static u64 __init host_default_mask(void)
781+
{
782+
/* Exclude dynamic features, which require userspace opt-in. */
783+
return ~(u64)XFEATURE_MASK_USER_DYNAMIC;
784+
}
785+
786+
static u64 __init guest_default_mask(void)
787+
{
788+
/*
789+
* Exclude dynamic features, which require userspace opt-in even
790+
* for KVM guests.
791+
*/
792+
return ~(u64)XFEATURE_MASK_USER_DYNAMIC;
793+
}
794+
776795
/*
777796
* Enable and initialize the xsave feature.
778797
* Called once per system bootup.
@@ -855,12 +874,13 @@ void __init fpu__init_system_xstate(unsigned int legacy_size)
855874
fpu_user_cfg.max_features = fpu_kernel_cfg.max_features;
856875
fpu_user_cfg.max_features &= XFEATURE_MASK_USER_SUPPORTED;
857876

858-
/* Clean out dynamic features from default */
859-
fpu_kernel_cfg.default_features = fpu_kernel_cfg.max_features;
860-
fpu_kernel_cfg.default_features &= ~XFEATURE_MASK_USER_DYNAMIC;
861-
862-
fpu_user_cfg.default_features = fpu_user_cfg.max_features;
863-
fpu_user_cfg.default_features &= ~XFEATURE_MASK_USER_DYNAMIC;
877+
/*
878+
* Now, given maximum feature set, determine default values by
879+
* applying default masks.
880+
*/
881+
fpu_kernel_cfg.default_features = fpu_kernel_cfg.max_features & host_default_mask();
882+
fpu_user_cfg.default_features = fpu_user_cfg.max_features & host_default_mask();
883+
guest_default_cfg.features = fpu_kernel_cfg.max_features & guest_default_mask();
864884

865885
/* Store it for paranoia check at the end */
866886
xfeatures = fpu_kernel_cfg.max_features;

0 commit comments

Comments
 (0)