All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sean Christopherson <seanjc@google.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>,
	Janosch Frank <frankja@linux.ibm.com>,
	David Hildenbrand <david@redhat.com>,
	Claudio Imbrenda <imbrenda@linux.ibm.com>,
	Vitaly Kuznetsov <vkuznets@redhat.com>,
	Wanpeng Li <wanpengli@tencent.com>,
	Jim Mattson <jmattson@google.com>, Joerg Roedel <joro@8bytes.org>,
	kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
	Ben Gardon <bgardon@google.com>,
	Lai Jiangshan <jiangshanlai@gmail.com>
Subject: Re: [PATCH v2 4/7] KVM: x86/mmu: Zap only obsolete roots if a root shadow page is zapped
Date: Thu, 3 Mar 2022 23:00:28 +0000	[thread overview]
Message-ID: <YiFIjNVPLVVnRatm@google.com> (raw)
In-Reply-To: <0c22b156-10c5-1988-7256-a9db7871989d@redhat.com>

On Thu, Mar 03, 2022, Paolo Bonzini wrote:
> On 3/2/22 23:53, Sean Christopherson wrote:
> > > 
> > > diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> > > index c5e3f219803e..7899ca4748c7 100644
> > > --- a/arch/x86/kvm/svm/svm.c
> > > +++ b/arch/x86/kvm/svm/svm.c
> > > @@ -3857,6 +3857,9 @@ static void svm_load_mmu_pgd(struct kvm_vcpu *vcpu,
> > > hpa_t root_hpa,
> > >          unsigned long cr3;
> > > 
> > >          if (npt_enabled) {
> > > +               if (is_tdp_mmu_root(root_hpa))
> > > +                       svm->current_vmcb->asid_generation = 0;
> > > +
> > >                  svm->vmcb->control.nested_cr3 = __sme_set(root_hpa);
> > >                  vmcb_mark_dirty(svm->vmcb, VMCB_NPT);
> > > 
> > > Why not just new_asid
> > My mental coin flip came up tails?  new_asid() is definitely more intuitive.
> > 
> 
> Can you submit a patch (seems like 5.17+stable material)?

After a lot more thinking, there's no bug.  If KVM unloads all roots, e.g. fast zap,
then all vCPUs are guaranteed to go through kvm_mmu_load(), and that will flush the
current ASID.

So the only problematic path is KVM_REQ_LOAD_MMU_PGD, which has two users,
kvm_mmu_new_pgd() and load_pdptrs().  load_pdptrs() is benign because it triggers
a "false" PGD load only top get PDPTRs updated on EPT, the actual PGD doesn't change
(or rather isn't forced to change by load_pdptrs().

Nested SVM's use of kvm_mmu_new_pgd() is "ok" because KVM currently flushes on
every transition.

That leaves kvm_set_cr3() via kvm_mmu_new_pgd().  For NPT, lack of a flush is
moot because KVM shouldn't be loading a new PGD in the first place (see our other
discussion about doing:

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index cf17af4d6904..f11199b41ca8 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1212,7 +1212,7 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
        if (is_pae_paging(vcpu) && !load_pdptrs(vcpu, cr3))
                return 1;

-       if (cr3 != kvm_read_cr3(vcpu))
+       if (!tdp_enabled && cr3 != kvm_read_cr3(vcpu))
                kvm_mmu_new_pgd(vcpu, cr3);

        vcpu->arch.cr3 = cr3;


Non-NPT shadow paging is ok because either the MOV CR3 will do a TLB flush, or the
guest explicitly says "don't do a TLB flush", in which case KVM is off the hook
from a correctness perspective (guest's responsibility to ensure MMU in sync'd),
and is ok from a safety perspective because the legacy MMU does a remote TLB flush
if it zaps any pages, i.e. the guest can't do use-after-free.

All that said, this is another argument against dropping kvm_mmu_unload() from
kvm_mmu_reset_context()[*]: SMM would theoretically be broken on AMD due to reusing
the same ASID for both non-SMM and SMM roots/memslots.

In practice, I don't think it can actually happen, but that's mostly dumb luck.
em_rsm() temporarily transitions back to Real Mode before loading the actual
non-SMM guest state, so only SMI that arrives with CR0.PG=0 is problematic.  In
that case, TLB flushes may not be triggered by kvm_set_cr0() or kvm_set_cr4(),
but kvm_set_cr3() will always trigger a flush because the "no flush" PCID bit
will always be clear.  Well, unless the SMM handler writes the read-only SMRAM
field, at which point it deserves to die :-)

Anyways, before we transitions SMM away from kvm_mmu_reset_context(), we should
add an explicit KVM_REQ_TLB_FLUSH_CURRENT in svm_{enter,leave}_smm(), with a TODO
similar to nested_svm_transition_tlb_flush() to document that the explicit flush
can go away when KVM ensures unique ASIDs for non-SMM vs. SMM.

[*] https://lore.kernel.org/all/20220209170020.1775368-13-pbonzini@redhat.com

  reply	other threads:[~2022-03-03 23:00 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-25 18:22 [PATCH v2 0/7] KVM: x86/mmu: Zap only obsolete roots on "reload" Sean Christopherson
2022-02-25 18:22 ` [PATCH v2 1/7] KVM: x86: Remove spurious whitespaces from kvm_post_set_cr4() Sean Christopherson
2022-02-25 18:22 ` [PATCH v2 2/7] KVM: x86: Invoke kvm_mmu_unload() directly on CR4.PCIDE change Sean Christopherson
2022-02-25 18:22 ` [PATCH v2 3/7] KVM: Drop kvm_reload_remote_mmus(), open code request in x86 users Sean Christopherson
2022-02-28 22:05   ` Ben Gardon
2022-02-25 18:22 ` [PATCH v2 4/7] KVM: x86/mmu: Zap only obsolete roots if a root shadow page is zapped Sean Christopherson
2022-02-28 22:38   ` Ben Gardon
2022-03-01 17:55   ` Paolo Bonzini
2022-03-02 18:04     ` Paolo Bonzini
2022-03-02 19:45       ` Sean Christopherson
2022-03-02 20:39         ` Paolo Bonzini
2022-03-02 22:53           ` Sean Christopherson
2022-03-03  7:14             ` Paolo Bonzini
2022-03-03 23:00               ` Sean Christopherson [this message]
2022-02-25 18:22 ` [PATCH v2 5/7] KVM: s390: Replace KVM_REQ_MMU_RELOAD usage with arch specific request Sean Christopherson
2022-02-25 18:22 ` [PATCH v2 6/7] KVM: Drop KVM_REQ_MMU_RELOAD and update vcpu-requests.rst documentation Sean Christopherson
2022-02-28 22:22   ` Ben Gardon
2022-02-25 18:22 ` [PATCH v2 7/7] KVM: WARN if is_unsync_root() is called on a root without a shadow page Sean Christopherson
2022-02-28 22:33   ` Ben Gardon
2022-03-01 15:35     ` Sean Christopherson
2022-03-01 17:08 ` [PATCH v2 0/7] KVM: x86/mmu: Zap only obsolete roots on "reload" Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YiFIjNVPLVVnRatm@google.com \
    --to=seanjc@google.com \
    --cc=bgardon@google.com \
    --cc=borntraeger@linux.ibm.com \
    --cc=david@redhat.com \
    --cc=frankja@linux.ibm.com \
    --cc=imbrenda@linux.ibm.com \
    --cc=jiangshanlai@gmail.com \
    --cc=jmattson@google.com \
    --cc=joro@8bytes.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=vkuznets@redhat.com \
    --cc=wanpengli@tencent.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.