On 11/26/24 02:17, Chao Gao wrote: > From: Yang Weijiang <weijiang.yang@xxxxxxxxx> > > Use fpu_guest_cfg to calculate guest fpstate settings, open code for > __fpstate_reset() to avoid using kernel FPU config. > > Below configuration steps are currently enforced to get guest fpstate: > 1) Kernel sets up guest FPU settings in fpu__init_system_xstate(). > 2) User space sets vCPU thread group xstate permits via arch_prctl(). > 3) User space creates guest fpstate via __fpu_alloc_init_guest_fpstate() > for vcpu thread. > 4) User space enables guest dynamic xfeatures and re-allocate guest > fpstate. > > By adding kernel dynamic xfeatures in above #1 and #2, guest xstate area > size is expanded to hold (fpu_kernel_cfg.default_features | kernel dynamic > xfeatures | user dynamic xfeatures), then host xsaves/xrstors can operate > for all guest xfeatures. These changelogs have a lot of content, but they're honestly not helping my along here very much. > arch/x86/kernel/fpu/core.c | 39 +++++++++++++++++++++++++++++--------- > 1 file changed, 30 insertions(+), 9 deletions(-) > > diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c > index 9e2e5c46cf28..00d7dcf45b34 100644 > --- a/arch/x86/kernel/fpu/core.c > +++ b/arch/x86/kernel/fpu/core.c > @@ -194,8 +194,6 @@ void fpu_reset_from_exception_fixup(void) > } > > #if IS_ENABLED(CONFIG_KVM) > -static void __fpstate_reset(struct fpstate *fpstate, u64 xfd); > - > static void fpu_init_guest_permissions(struct fpu_guest *gfpu) > { > struct fpu_state_perm *fpuperm; > @@ -216,25 +214,48 @@ static void fpu_init_guest_permissions(struct fpu_guest *gfpu) > gfpu->perm = perm & ~FPU_GUEST_PERM_LOCKED; > } > > -bool fpu_alloc_guest_fpstate(struct fpu_guest *gfpu) > +static struct fpstate *__fpu_alloc_init_guest_fpstate(struct fpu_guest *gfpu) > { > struct fpstate *fpstate; > unsigned int size; > > - size = fpu_user_cfg.default_size + ALIGN(offsetof(struct fpstate, regs), 64); > + /* > + * fpu_guest_cfg.default_size is initialized to hold all enabled > + * xfeatures except the user dynamic xfeatures. If the user dynamic > + * xfeatures are enabled, the guest fpstate will be re-allocated to > + * hold all guest enabled xfeatures, so omit user dynamic xfeatures > + * here. > + */ > + size = fpu_guest_cfg.default_size + ALIGN(offsetof(struct fpstate, regs), 64); > + > fpstate = vzalloc(size); > if (!fpstate) > - return false; > + return NULL; > + /* > + * Initialize sizes and feature masks, use fpu_user_cfg.* > + * for user_* settings for compatibility of exiting uAPIs. > + */ > + fpstate->size = fpu_guest_cfg.default_size; > + fpstate->xfeatures = fpu_guest_cfg.default_features; > + fpstate->user_size = fpu_user_cfg.default_size; > + fpstate->user_xfeatures = fpu_user_cfg.default_features; > + fpstate->xfd = 0; > > - /* Leave xfd to 0 (the reset value defined by spec) */ > - __fpstate_reset(fpstate, 0); > fpstate_init_user(fpstate); > fpstate->is_valloc = true; > fpstate->is_guest = true; > > gfpu->fpstate = fpstate; > - gfpu->xfeatures = fpu_user_cfg.default_features; > - gfpu->perm = fpu_user_cfg.default_features; > + gfpu->xfeatures = fpu_guest_cfg.default_features; > + gfpu->perm = fpu_guest_cfg.default_features; > + > + return fpstate; > +} > + > +bool fpu_alloc_guest_fpstate(struct fpu_guest *gfpu) > +{ > + if (!__fpu_alloc_init_guest_fpstate(gfpu)) > + return false; > > /* > * KVM sets the FP+SSE bits in the XSAVE header when copying FPU state This series is starting to look backward to me. The normal way you do these things is that you introduce new abstractions and refactor the code. Then you go adding features. For instance, this series should spend a few patches introducing 'fpu_guest_cfg' and using it before ever introducing the concept of a dynamic xfeature.