> Nikunj A Dadhania <nikunj@xxxxxxx> writes: > > Zheyun Shen <szy0127@xxxxxxxxxxx> writes: > >> On AMD CPUs without ensuring cache consistency, each memory page >> reclamation in an SEV guest triggers a call to wbinvd_on_all_cpus(), >> thereby affecting the performance of other programs on the host. >> >> Typically, an AMD server may have 128 cores or more, while the SEV guest >> might only utilize 8 of these cores. Meanwhile, host can use qemu-affinity >> to bind these 8 vCPUs to specific physical CPUs. >> >> Therefore, keeping a record of the physical core numbers each time a vCPU >> runs can help avoid flushing the cache for all CPUs every time. >> >> Suggested-by: Sean Christopherson <seanjc@xxxxxxxxxx> >> Signed-off-by: Zheyun Shen <szy0127@xxxxxxxxxxx> >> --- >> arch/x86/kvm/svm/sev.c | 39 ++++++++++++++++++++++++++++++++++++--- >> arch/x86/kvm/svm/svm.c | 2 ++ >> arch/x86/kvm/svm/svm.h | 5 ++++- >> 3 files changed, 42 insertions(+), 4 deletions(-) >> >> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c >> index 1ce67de9d..91469edd1 100644 >> --- a/arch/x86/kvm/svm/sev.c >> +++ b/arch/x86/kvm/svm/sev.c >> @@ -252,6 +252,36 @@ static void sev_asid_free(struct kvm_sev_info *sev) >> sev->misc_cg = NULL; >> } >> >> +static struct cpumask *sev_get_wbinvd_dirty_mask(struct kvm *kvm) >> +{ >> + struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info; > > There is a helper to get sev_info: to_kvm_sev_info(), if you use that, > sev_get_wbinvd_dirty_mask() helper will not be needed. > >> + >> + return sev->wbinvd_dirty_mask; >> +} >> + >> +void sev_vcpu_load(struct kvm_vcpu *vcpu, int cpu) >> +{ >> + /* >> + * To optimize cache flushes when memory is reclaimed from an SEV VM, >> + * track physical CPUs that enter the guest for SEV VMs and thus can >> + * have encrypted, dirty data in the cache, and flush caches only for >> + * CPUs that have entered the guest. >> + */ >> + cpumask_set_cpu(cpu, sev_get_wbinvd_dirty_mask(vcpu->kvm)); >> +} >> + >> +static void sev_do_wbinvd(struct kvm *kvm) >> +{ >> + struct cpumask *dirty_mask = sev_get_wbinvd_dirty_mask(kvm); >> + >> + /* >> + * TODO: Clear CPUs from the bitmap prior to flushing. Doing so >> + * requires serializing multiple calls and having CPUs mark themselves >> + * "dirty" if they are currently running a vCPU for the VM. >> + */ >> + wbinvd_on_many_cpus(dirty_mask); >> +} > > Something like the below > > void sev_vcpu_load(struct kvm_vcpu *vcpu, int cpu) > { > /* ... */ > cpumask_set_cpu(cpu, to_kvm_sev_info(kvm)->wbinvd_dirty_mask); > } > > static void sev_do_wbinvd(struct kvm *kvm) > { > /* ... */ > wbinvd_on_many_cpus(to_kvm_sev_info(kvm)->wbinvd_dirty_mask); > } > > Regards, > Nikunj > Got it, thanks. Regards, Zheyun Shen