Re: [PATCH 13/15] KVM: SVM: Add and use svm_register_cache_reset()

Paolo Bonzini
2021-11-18T15:37:50Z

On 11/8/21 13:44, Lai Jiangshan wrote:
> From: Lai Jiangshan <laijs@linux.alibaba.com>
>
> It resets all the appropriate bits like vmx.
>
> Signed-off-by: Lai Jiangshan <laijs@linux.alibaba.com>
> ---
> arch/x86/kvm/svm/svm.c | 3 +--
> arch/x86/kvm/svm/svm.h | 26 ++++++++++++++++++++++++++
> 2 files changed, 27 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index b7da66935e72..ba9cfddd2875 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -3969,8 +3969,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
>
> svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
> vmcb_mark_all_clean(svm->vmcb);
> -
> - kvm_register_clear_available(vcpu, VCPU_EXREG_PDPTR);
> + svm_register_cache_reset(vcpu);
>
> /*
> * We need to handle MC intercepts here before the vcpu has a chance to
> diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
> index 0d7bbe548ac3..1cf5d5e2d0cd 100644
> --- a/arch/x86/kvm/svm/svm.h
> +++ b/arch/x86/kvm/svm/svm.h
> @@ -274,6 +274,32 @@ static inline bool vmcb_is_dirty(struct vmcb *vmcb, int bit)
> return !test_bit(bit, (unsigned long *)&vmcb->control.clean);
> }
>
> +static inline void svm_register_cache_reset(struct kvm_vcpu *vcpu)
> +{
> +/*
> + * SVM_REGS_AVAIL_SET - The set of registers that will be updated in cache on
> + * demand. Other registers not listed here are synced to
> + * the cache immediately after VM-Exit.
> + *
> + * SVM_REGS_DIRTY_SET - The set of registers that might be outdated in
> + * architecture. Other registers not listed here are synced
> + * to the architecture immediately when modifying.
> + *
> + * Special case: VCPU_EXREG_CR3 should be in this set due
> + * to the fact. But KVM_REQ_LOAD_MMU_PGD is always
> + * requested when the cache vcpu->arch.cr3 is changed and
> + * svm_load_mmu_pgd() always syncs the new CR3 value into
> + * the architecture. So the dirty information of
> + * VCPU_EXREG_CR3 is not used which means VCPU_EXREG_CR3
> + * isn't required to be put in this set.
> + */
> +#define SVM_REGS_AVAIL_SET (1 << VCPU_EXREG_PDPTR)
> +#define SVM_REGS_DIRTY_SET (0)
> +
> + vcpu->arch.regs_avail &= ~SVM_REGS_AVAIL_SET;
> + vcpu->arch.regs_dirty &= ~SVM_REGS_DIRTY_SET;
> +}

I think touching regs_dirty is confusing here, so I'd go with this:

vcpu->arch.regs_avail &= ~SVM_REGS_LAZY_LOAD_SET;

/*
* SVM does not use vcpu->arch.regs_dirty. The only register that
* might be out of date in the VMCB is CR3, but KVM_REQ_LOAD_MMU_PGD
* is always requested when the cache vcpu->arch.cr3 is changed and
* svm_load_mmu_pgd() always syncs the new CR3 value into the VMCB.
*/

(VMX instead needs VCPU_EXREG_CR3 mostly because it does not want to
update it unconditionally on exit).

Paolo