On Thu, Sep 01, 2022 at 07:17:36PM -0700, isaku.yamahata@xxxxxxxxx wrote: > From: Sean Christopherson <seanjc@xxxxxxxxxx> > > KVM/X86 uses user return notifier to switch MSR for guest or user space. > Snapshot host values on CPU online, change MSR values for guest, and > restore them on returning to user space. The current code abuses > kvm_arch_hardware_enable() which is called on kvm module initialization or > CPU online. > > Remove such the abuse of kvm_arch_hardware_enable() by capturing the host > value on the first change of the MSR value to guest VM instead of CPU > online. > > Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx> > Signed-off-by: Isaku Yamahata <isaku.yamahata@xxxxxxxxx> Reviewed-by: Yuan Yao <yuan.yao@xxxxxxxxx> > --- > arch/x86/kvm/x86.c | 19 ++++++++++++++----- > 1 file changed, 14 insertions(+), 5 deletions(-) > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 205ebdc2b11b..0e200fe44b35 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -196,6 +196,7 @@ module_param(eager_page_split, bool, 0644); > > struct kvm_user_return_msrs { > struct user_return_notifier urn; > + bool initialized; > bool registered; > struct kvm_user_return_msr_values { > u64 host; > @@ -409,18 +410,20 @@ int kvm_find_user_return_msr(u32 msr) > } > EXPORT_SYMBOL_GPL(kvm_find_user_return_msr); > > -static void kvm_user_return_msr_cpu_online(void) > +static void kvm_user_return_msr_init_cpu(struct kvm_user_return_msrs *msrs) > { > - unsigned int cpu = smp_processor_id(); > - struct kvm_user_return_msrs *msrs = per_cpu_ptr(user_return_msrs, cpu); > u64 value; > int i; > > + if (msrs->initialized) > + return; > + > for (i = 0; i < kvm_nr_uret_msrs; ++i) { > rdmsrl_safe(kvm_uret_msrs_list[i], &value); > msrs->values[i].host = value; > msrs->values[i].curr = value; > } > + msrs->initialized = true; > } > > int kvm_set_user_return_msr(unsigned slot, u64 value, u64 mask) > @@ -429,6 +432,8 @@ int kvm_set_user_return_msr(unsigned slot, u64 value, u64 mask) > struct kvm_user_return_msrs *msrs = per_cpu_ptr(user_return_msrs, cpu); > int err; > > + kvm_user_return_msr_init_cpu(msrs); > + > value = (value & mask) | (msrs->values[slot].host & ~mask); > if (value == msrs->values[slot].curr) > return 0; > @@ -9212,7 +9217,12 @@ int kvm_arch_init(void *opaque) > return -ENOMEM; > } > > - user_return_msrs = alloc_percpu(struct kvm_user_return_msrs); > + /* > + * __GFP_ZERO to ensure user_return_msrs.values[].initialized = false. > + * See kvm_user_return_msr_init_cpu(). > + */ > + user_return_msrs = alloc_percpu_gfp(struct kvm_user_return_msrs, > + GFP_KERNEL | __GFP_ZERO); > if (!user_return_msrs) { > printk(KERN_ERR "kvm: failed to allocate percpu kvm_user_return_msrs\n"); > r = -ENOMEM; > @@ -11836,7 +11846,6 @@ int kvm_arch_hardware_enable(void) > u64 max_tsc = 0; > bool stable, backwards_tsc = false; > > - kvm_user_return_msr_cpu_online(); > ret = static_call(kvm_x86_hardware_enable)(); > if (ret != 0) > return ret; > -- > 2.25.1 >