[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <Zwy7dMTMR2bIDtzM@yzhao56-desk.sh.intel.com>
Date: Mon, 14 Oct 2024 14:34:28 +0800
From: Yan Zhao <yan.y.zhao@...el.com>
To: Paolo Bonzini <pbonzini@...hat.com>
CC: Rick Edgecombe <rick.p.edgecombe@...el.com>, <seanjc@...gle.com>,
<kvm@...r.kernel.org>, <kai.huang@...el.com>, <dmatlack@...gle.com>,
<isaku.yamahata@...il.com>, <nik.borisov@...e.com>,
<linux-kernel@...r.kernel.org>
Subject: Re: [PATCH 13/21] KVM: TDX: Handle TLB tracking for TDX
On Tue, Sep 10, 2024 at 10:16:27AM +0200, Paolo Bonzini wrote:
> On 9/4/24 05:07, Rick Edgecombe wrote:
> > +static void vt_flush_tlb_all(struct kvm_vcpu *vcpu)
> > +{
> > + /*
> > + * TDX calls tdx_track() in tdx_sept_remove_private_spte() to ensure
> > + * private EPT will be flushed on the next TD enter.
> > + * No need to call tdx_track() here again even when this callback is as
> > + * a result of zapping private EPT.
> > + * Just invoke invept() directly here to work for both shared EPT and
> > + * private EPT.
> > + */
> > + if (is_td_vcpu(vcpu)) {
> > + ept_sync_global();
> > + return;
> > + }
> > +
> > + vmx_flush_tlb_all(vcpu);
> > +}
> > +
> > +static void vt_flush_tlb_current(struct kvm_vcpu *vcpu)
> > +{
> > + if (is_td_vcpu(vcpu)) {
> > + tdx_flush_tlb_current(vcpu);
> > + return;
> > + }
> > +
> > + vmx_flush_tlb_current(vcpu);
> > +}
> > +
>
> I'd do it slightly different:
>
> static void vt_flush_tlb_all(struct kvm_vcpu *vcpu)
> {
> if (is_td_vcpu(vcpu)) {
> tdx_flush_tlb_all(vcpu);
> return;
> }
>
> vmx_flush_tlb_all(vcpu);
> }
Thanks!
This is better.
>
> static void vt_flush_tlb_current(struct kvm_vcpu *vcpu)
> {
> if (is_td_vcpu(vcpu)) {
> /*
> * flush_tlb_current() is used only the first time for
> * the vcpu runs, since TDX supports neither shadow
> * nested paging nor SMM. Keep this function simple.
> */
> tdx_flush_tlb_all(vcpu);
Could we still keep tdx_flush_tlb_current()?
Though both tdx_flush_tlb_all() and tdx_flush_tlb_current() simply invoke
ept_sync_global(), their purposes are different:
- The ept_sync_global() in tdx_flush_tlb_current() is intended to avoid
retrieving private EPTP required for the single-context invalidation for
shared EPT;
- while the ept_sync_global() in tdx_flush_tlb_all() is right for shared EPT.
Adding a tdx_flush_tlb_current() can help document the differences in tdx.c.
like this:
void tdx_flush_tlb_current(struct kvm_vcpu *vcpu)
{
/*
* flush_tlb_current() is invoked when the first time for the vcpu to
* run or when root of shared EPT is invalidated.
* KVM only needs to flush the TLB for shared EPT because the TDX module
* handles TLB invalidation for private EPT in tdh_vp_enter();
*
* A single context invalidation for shared EPT can be performed here.
* However, this single context invalidation requires the private EPTP
* rather than the shared EPTP to flush TLB for shared EPT, as shared
* EPT uses private EPTP as its ASID for TLB invalidation.
*
* To avoid reading back private EPTP, perform a global invalidation for
* shared EPT instead to keep this function simple.
*/
ept_sync_global();
}
void tdx_flush_tlb_all(struct kvm_vcpu *vcpu)
{
/*
* TDX has called tdx_track() in tdx_sept_remove_private_spte() to
* ensure that private EPT will be flushed on the next TD enter. No need
* to call tdx_track() here again even when this callback is a result of
* zapping private EPT.
*
* Due to the lack of the context to determine which EPT has been
* affected by zapping, invoke invept() directly here for both shared
* EPT and private EPT for simplicity, though it's not necessary for
* private EPT. *
*/
ept_sync_global();
}
> return;
> }
>
> vmx_flush_tlb_current(vcpu);
> }
>
> and put the implementation details close to tdx_track:
> void tdx_flush_tlb_all(struct kvm_vcpu *vcpu)
> {
> /*
> * TDX calls tdx_track() in tdx_sept_remove_private_spte() to
> * ensure private EPT will be flushed on the next TD enter.
> * No need to call tdx_track() here again, even when this
> * callback is a result of zapping private EPT. Just
> * invoke invept() directly here, which works for both shared
> * EPT and private EPT.
> */
> ept_sync_global();
> }
Got it!
Powered by blists - more mailing lists