On Sun, 28 May 2023 21:18:45 -0700 isaku.yamahata@xxxxxxxxx wrote: > From: Isaku Yamahata <isaku.yamahata@xxxxxxxxx> > > Currently, KVM VMX module initialization/exit functions are a single > function each. Refactor KVM VMX module initialization functions into KVM > common part and VMX part so that TDX specific part can be added cleanly. > Opportunistically refactor module exit function as well. > > The current module initialization flow is, > 0.) Check if VMX is supported, > 1.) hyper-v specific initialization, > 2.) system-wide x86 specific and vendor specific initialization, > 3.) Final VMX specific system-wide initialization, > 4.) calculate the sizes of VMX kvm structure and VMX vcpu structure, > 5.) report those sizes to the KVM common layer and KVM common > initialization > > Refactor the KVM VMX module initialization function into functions with a > wrapper function to separate VMX logic in vmx.c from a file, main.c, common > among VMX and TDX. Introduce a wrapper function for vmx_init(). > > The KVM architecture common layer allocates struct kvm with reported size > for architecture-specific code. The KVM VMX module defines its structure > as struct vmx_kvm { struct kvm; VMX specific members;} and uses it as > struct vmx kvm. Similar for vcpu structure. TDX KVM patches will define > TDX specific kvm and vcpu structures. > > The current module exit function is also a single function, a combination > of VMX specific logic and common KVM logic. Refactor it into VMX specific > logic and KVM common logic. This is just refactoring to keep the VMX > specific logic in vmx.c from main.c. > > Signed-off-by: Isaku Yamahata <isaku.yamahata@xxxxxxxxx> > --- > arch/x86/kvm/vmx/main.c | 50 +++++++++++++++++++++++++++++++++++ > arch/x86/kvm/vmx/vmx.c | 54 +++++--------------------------------- > arch/x86/kvm/vmx/x86_ops.h | 13 ++++++++- > 3 files changed, 68 insertions(+), 49 deletions(-) > > diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c > index a59559ff140e..791ee271393d 100644 > --- a/arch/x86/kvm/vmx/main.c > +++ b/arch/x86/kvm/vmx/main.c > @@ -165,3 +165,53 @@ struct kvm_x86_init_ops vt_init_ops __initdata = { > .runtime_ops = &vt_x86_ops, > .pmu_ops = &intel_pmu_ops, > }; > + > +static int __init vt_init(void) > +{ > + unsigned int vcpu_size, vcpu_align; > + int r; > + > + if (!kvm_is_vmx_supported()) > + return -EOPNOTSUPP; > + > + /* > + * Note, hv_init_evmcs() touches only VMX knobs, i.e. there's nothing > + * to unwind if a later step fails. > + */ > + hv_init_evmcs(); > + > + r = kvm_x86_vendor_init(&vt_init_ops); > + if (r) > + return r; > + > + r = vmx_init(); > + if (r) > + goto err_vmx_init; > + > + /* > + * Common KVM initialization _must_ come last, after this, /dev/kvm is > + * exposed to userspace! > + */ > + vcpu_size = sizeof(struct vcpu_vmx); > + vcpu_align = __alignof__(struct vcpu_vmx); > + r = kvm_init(vcpu_size, vcpu_align, THIS_MODULE); > + if (r) > + goto err_kvm_init; > + > + return 0; > + --------------------------------- > +err_kvm_init: > + vmx_exit(); > +err_vmx_init: > + kvm_x86_vendor_exit(); > + return r; > +} > +module_init(vt_init); > + ---------------------------------- > +static void vt_exit(void) > +{ > + kvm_exit(); > + kvm_x86_vendor_exit(); > + vmx_exit(); ---------------------------------- It seems the exiting sequences above are a little bit different with each other (PS: It is not a prob introduced in this patch): vmx_exit() kvm_x86_vendor_exit() .... and ... kvm_x86_vnedor_exit() vmx_exit() I was wondering which one should be correct. Literally, the exiting sequence would be in reversing order of the initialization sequence. > +} > +module_exit(vt_exit); > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c > index ed7bf8fc55a8..9e4def64495b 100644 > --- a/arch/x86/kvm/vmx/vmx.c > +++ b/arch/x86/kvm/vmx/vmx.c > @@ -554,7 +554,7 @@ static int hv_enable_l2_tlb_flush(struct kvm_vcpu *vcpu) > return 0; > } > > -static __init void hv_init_evmcs(void) > +__init void hv_init_evmcs(void) > { > int cpu; > > @@ -590,7 +590,7 @@ static __init void hv_init_evmcs(void) > } > } > > -static void hv_reset_evmcs(void) > +void hv_reset_evmcs(void) > { > struct hv_vp_assist_page *vp_ap; > > @@ -614,10 +614,6 @@ static void hv_reset_evmcs(void) > vp_ap->current_nested_vmcs = 0; > vp_ap->enlighten_vmentry = 0; > } > - > -#else /* IS_ENABLED(CONFIG_HYPERV) */ > -static void hv_init_evmcs(void) {} > -static void hv_reset_evmcs(void) {} > #endif /* IS_ENABLED(CONFIG_HYPERV) */ > > /* > @@ -2715,7 +2711,7 @@ static int setup_vmcs_config(struct vmcs_config *vmcs_conf, > return 0; > } > > -static bool kvm_is_vmx_supported(void) > +bool kvm_is_vmx_supported(void) > { > int cpu = raw_smp_processor_id(); > > @@ -8381,7 +8377,7 @@ static void vmx_cleanup_l1d_flush(void) > l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO; > } > > -static void __vmx_exit(void) > +void vmx_exit(void) > { > allow_smaller_maxphyaddr = false; > > @@ -8392,32 +8388,10 @@ static void __vmx_exit(void) > vmx_cleanup_l1d_flush(); > } > > -static void vmx_exit(void) > -{ > - kvm_exit(); > - kvm_x86_vendor_exit(); > - > - __vmx_exit(); > -} > -module_exit(vmx_exit); > - > -static int __init vmx_init(void) > +int __init vmx_init(void) > { > int r, cpu; > > - if (!kvm_is_vmx_supported()) > - return -EOPNOTSUPP; > - > - /* > - * Note, hv_init_evmcs() touches only VMX knobs, i.e. there's nothing > - * to unwind if a later step fails. > - */ > - hv_init_evmcs(); > - > - r = kvm_x86_vendor_init(&vt_init_ops); > - if (r) > - return r; > - > /* > * Must be called after common x86 init so enable_ept is properly set > * up. Hand the parameter mitigation value in which was stored in > @@ -8427,7 +8401,7 @@ static int __init vmx_init(void) > */ > r = vmx_setup_l1d_flush(vmentry_l1d_flush_param); > if (r) > - goto err_l1d_flush; > + return r; > > vmx_setup_fb_clear_ctrl(); > > @@ -8448,21 +8422,5 @@ static int __init vmx_init(void) > if (!enable_ept) > allow_smaller_maxphyaddr = true; > > - /* > - * Common KVM initialization _must_ come last, after this, /dev/kvm is > - * exposed to userspace! > - */ > - r = kvm_init(sizeof(struct vcpu_vmx), __alignof__(struct vcpu_vmx), > - THIS_MODULE); > - if (r) > - goto err_kvm_init; > - > return 0; > - > -err_kvm_init: > - __vmx_exit(); > -err_l1d_flush: > - kvm_x86_vendor_exit(); > - return r; > } > -module_init(vmx_init); > diff --git a/arch/x86/kvm/vmx/x86_ops.h b/arch/x86/kvm/vmx/x86_ops.h > index e9ec4d259ff5..051b5c4b5c2f 100644 > --- a/arch/x86/kvm/vmx/x86_ops.h > +++ b/arch/x86/kvm/vmx/x86_ops.h > @@ -8,11 +8,22 @@ > > #include "x86.h" > > -__init int vmx_hardware_setup(void); > +#if IS_ENABLED(CONFIG_HYPERV) > +__init void hv_init_evmcs(void); > +void hv_reset_evmcs(void); > +#else /* IS_ENABLED(CONFIG_HYPERV) */ > +static inline void hv_init_evmcs(void) {} > +static inline void hv_reset_evmcs(void) {} > +#endif /* IS_ENABLED(CONFIG_HYPERV) */ > + > +bool kvm_is_vmx_supported(void); > +int __init vmx_init(void); > +void vmx_exit(void); > > extern struct kvm_x86_ops vt_x86_ops __initdata; > extern struct kvm_x86_init_ops vt_init_ops __initdata; > > +__init int vmx_hardware_setup(void); > void vmx_hardware_unsetup(void); > int vmx_check_processor_compat(void); > int vmx_hardware_enable(void);