linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: Sean Christopherson <seanjc@google.com>,
	Christian Borntraeger <borntraeger@linux.ibm.com>,
	Janosch Frank <frankja@linux.ibm.com>
Cc: 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: Wed, 2 Mar 2022 19:04:44 +0100	[thread overview]
Message-ID: <ee757515-4a0f-c5cb-cd57-04983f62f499@redhat.com> (raw)
In-Reply-To: <40a22c39-9da4-6c37-8ad0-b33970e35a2b@redhat.com>

On 3/1/22 18:55, Paolo Bonzini wrote:
> On 2/25/22 19:22, Sean Christopherson wrote:
>> @@ -5656,7 +5707,7 @@ static void kvm_mmu_zap_all_fast(struct kvm *kvm)
>>        * Note: we need to do this under the protection of mmu_lock,
>>        * otherwise, vcpu would purge shadow page but miss tlb flush.
>>        */
>> -    kvm_make_all_cpus_request(kvm, KVM_REQ_MMU_RELOAD);
>> +    kvm_make_all_cpus_request(kvm, KVM_REQ_MMU_FREE_OBSOLETE_ROOTS);
> 
> I was going to squash in this:
> 
>        * invalidating TDP MMU roots must be done while holding mmu_lock for
> -     * write and in the same critical section as making the reload 
> request,
> +     * write and in the same critical section as making the free request,
>        * e.g. before kvm_zap_obsolete_pages() could drop mmu_lock and 
> yield.
> 
> But then I realized that this needs better comments and that my 
> knowledge of
> this has serious holes.  Regarding this comment, this is my proposal:
> 
>          /*
>           * Invalidated TDP MMU roots are zapped within MMU read_lock to be
>           * able to walk the list of roots, but with the expectation of no
>           * concurrent change to the pages themselves.  There cannot be
>           * any yield between kvm_tdp_mmu_invalidate_all_roots and the free
>           * request, otherwise somebody could grab a reference to the root
>       * and break that assumption.
>           */
>          if (is_tdp_mmu_enabled(kvm))
>                  kvm_tdp_mmu_invalidate_all_roots(kvm);
> 
> However, for the second comment (the one in the context above), there's 
> much
> more.  From easier to harder:
> 
> 1) I'm basically clueless about the TLB flush "note" above.
> 
> 2) It's not clear to me what needs to use for_each_tdp_mmu_root; for
> example, why would anything but the MMU notifiers use 
> for_each_tdp_mmu_root?
> It is used in kvm_tdp_mmu_write_protect_gfn, 
> kvm_tdp_mmu_try_split_huge_pages
> and kvm_tdp_mmu_clear_dirty_pt_masked.
> 
> 3) Does it make sense that yielding users of for_each_tdp_mmu_root must
> either look at valid roots only, or take MMU lock for write?  If so, can
> this be enforced in tdp_mmu_next_root?

Ok, I could understand this a little better now, but please correct me
if this is incorrect:

2) if I'm not wrong, kvm_tdp_mmu_try_split_huge_pages indeed does not
need to walk invalid  roots.  The others do because the TDP MMU does
not necessarily kick vCPUs after marking roots as invalid.  But
because TDP MMU roots are gone for good once their refcount hits 0,
I wonder if we could do something like

diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c
index 7e3d1f985811..a4a6dfee27f9 100644
--- a/arch/x86/kvm/mmu/tdp_mmu.c
+++ b/arch/x86/kvm/mmu/tdp_mmu.c
@@ -164,6 +164,7 @@ void kvm_tdp_mmu_put_root(struct kvm *kvm, struct kvm_mmu_page *root,
  	 */
  	if (!kvm_tdp_root_mark_invalid(root)) {
  		refcount_set(&root->tdp_mmu_root_count, 1);
+		kvm_make_all_cpus_request(kvm, KVM_REQ_MMU_FREE_OBSOLETE_ROOTS);
  
  		/*
  		 * If the struct kvm is alive, we might as well zap the root
@@ -1099,12 +1100,16 @@ void kvm_tdp_mmu_zap_invalidated_roots(struct kvm *kvm)
  void kvm_tdp_mmu_invalidate_all_roots(struct kvm *kvm)
  {
  	struct kvm_mmu_page *root;
+	bool invalidated_root = false
  
  	lockdep_assert_held_write(&kvm->mmu_lock);
  	list_for_each_entry(root, &kvm->arch.tdp_mmu_roots, link) {
  		if (!WARN_ON_ONCE(!kvm_tdp_mmu_get_root(root)))
-			root->role.invalid = true;
+			invalidated_root |= !kvm_tdp_root_mark_invalid(root);
  	}
+
+	if (invalidated_root)
+		kvm_make_all_cpus_request(kvm, KVM_REQ_MMU_FREE_OBSOLETE_ROOTS);
  }
  
  /*

(based on my own version of Sean's patches) and stop walking invalid roots
in kvm_tdp_mmu_write_protect_gfn and kvm_tdp_mmu_clear_dirty_pt_masked.


3) Yes, it makes sense that yielding users of for_each_tdp_mmu_root must
either look at valid roots only, or take MMU lock for write.  The only
exception is kvm_tdp_mmu_try_split_huge_pages, which does not need to
walk invalid roots.  And kvm_tdp_mmu_zap_invalidated_pages(), but that
one is basically an asynchronous worker [and this is where I had the
inspiration to get rid of the function altogether]

Paolo


  reply	other threads:[~2022-03-02 18:04 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 [this message]
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
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=ee757515-4a0f-c5cb-cd57-04983f62f499@redhat.com \
    --to=pbonzini@redhat.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=seanjc@google.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).