linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] avoid unnecessary memslot rmap walks
@ 2020-06-02 20:07 Anthony Yznaga
  2020-06-02 20:07 ` [PATCH 1/3] KVM: x86: remove unnecessary rmap walk of read-only memslots Anthony Yznaga
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Anthony Yznaga @ 2020-06-02 20:07 UTC (permalink / raw)
  To: kvm, linux-kernel
  Cc: pbonzini, sean.j.christopherson, vkuznets, wanpengli, jmattson,
	joro, tglx, mingo, bp, x86, hpa, steven.sistare, anthony.yznaga

While investigating optimizing qemu start time for large memory guests
I found that kvm_mmu_slot_apply_flags() is walking rmaps to update
existing sptes when creating or moving a slot but that there won't be
any existing sptes to update and any sptes inserted once the new memslot
is visible won't need updating.  I can't find any reason for this not to
be the case, but I've taken a more cautious approach to fixing this by
dividing things into three patches.

Anthony Yznaga (3):
  KVM: x86: remove unnecessary rmap walk of read-only memslots
  KVM: x86: avoid unnecessary rmap walks when creating/moving slots
  KVM: x86: minor code refactor and comments fixup around dirty logging

 arch/x86/kvm/x86.c | 106 +++++++++++++++++++++++++----------------------------
 1 file changed, 49 insertions(+), 57 deletions(-)

-- 
2.13.3


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] KVM: x86: remove unnecessary rmap walk of read-only memslots
  2020-06-02 20:07 [PATCH 0/3] avoid unnecessary memslot rmap walks Anthony Yznaga
@ 2020-06-02 20:07 ` Anthony Yznaga
  2020-06-02 20:07 ` [PATCH 2/3] KVM: x86: avoid unnecessary rmap walks when creating/moving slots Anthony Yznaga
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Anthony Yznaga @ 2020-06-02 20:07 UTC (permalink / raw)
  To: kvm, linux-kernel
  Cc: pbonzini, sean.j.christopherson, vkuznets, wanpengli, jmattson,
	joro, tglx, mingo, bp, x86, hpa, steven.sistare, anthony.yznaga

There's no write access to remove.  An existing memslot cannot be updated
to set or clear KVM_MEM_READONLY, and any mappings established in a newly
created or moved read-only memslot will already be read-only.

Signed-off-by: Anthony Yznaga <anthony.yznaga@oracle.com>
---
 arch/x86/kvm/x86.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index c17e6eb9ad43..23fd888e52ee 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10038,11 +10038,9 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
 static void kvm_mmu_slot_apply_flags(struct kvm *kvm,
 				     struct kvm_memory_slot *new)
 {
-	/* Still write protect RO slot */
-	if (new->flags & KVM_MEM_READONLY) {
-		kvm_mmu_slot_remove_write_access(kvm, new, PT_PAGE_TABLE_LEVEL);
+	/* Nothing to do for RO slots */
+	if (new->flags & KVM_MEM_READONLY)
 		return;
-	}
 
 	/*
 	 * Call kvm_x86_ops dirty logging hooks when they are valid.
-- 
2.13.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] KVM: x86: avoid unnecessary rmap walks when creating/moving slots
  2020-06-02 20:07 [PATCH 0/3] avoid unnecessary memslot rmap walks Anthony Yznaga
  2020-06-02 20:07 ` [PATCH 1/3] KVM: x86: remove unnecessary rmap walk of read-only memslots Anthony Yznaga
@ 2020-06-02 20:07 ` Anthony Yznaga
  2020-06-02 20:07 ` [PATCH 3/3] KVM: x86: minor code refactor and comments fixup around dirty logging Anthony Yznaga
  2020-06-04 18:42 ` [PATCH 0/3] avoid unnecessary memslot rmap walks Paolo Bonzini
  3 siblings, 0 replies; 5+ messages in thread
From: Anthony Yznaga @ 2020-06-02 20:07 UTC (permalink / raw)
  To: kvm, linux-kernel
  Cc: pbonzini, sean.j.christopherson, vkuznets, wanpengli, jmattson,
	joro, tglx, mingo, bp, x86, hpa, steven.sistare, anthony.yznaga

On large memory guests it has been observed that creating a memslot
for a very large range can take noticeable amount of time.
Investigation showed that the time is spent walking the rmaps to update
existing sptes to remove write access or set/clear dirty bits to support
dirty logging.  These rmap walks are unnecessary when creating or moving
a memslot.  A newly created memslot will not have any existing mappings,
and the existing mappings of a moved memslot will have been invalidated
and flushed.  Any mappings established once the new/moved memslot becomes
visible will be set using the properties of the new slot.

Signed-off-by: Anthony Yznaga <anthony.yznaga@oracle.com>
---
 arch/x86/kvm/x86.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 23fd888e52ee..d211c8ced6bb 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10138,7 +10138,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 	 *
 	 * FIXME: const-ify all uses of struct kvm_memory_slot.
 	 */
-	if (change != KVM_MR_DELETE)
+	if (change == KVM_MR_FLAGS_ONLY)
 		kvm_mmu_slot_apply_flags(kvm, (struct kvm_memory_slot *) new);
 
 	/* Free the arrays associated with the old memslot. */
-- 
2.13.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] KVM: x86: minor code refactor and comments fixup around dirty logging
  2020-06-02 20:07 [PATCH 0/3] avoid unnecessary memslot rmap walks Anthony Yznaga
  2020-06-02 20:07 ` [PATCH 1/3] KVM: x86: remove unnecessary rmap walk of read-only memslots Anthony Yznaga
  2020-06-02 20:07 ` [PATCH 2/3] KVM: x86: avoid unnecessary rmap walks when creating/moving slots Anthony Yznaga
@ 2020-06-02 20:07 ` Anthony Yznaga
  2020-06-04 18:42 ` [PATCH 0/3] avoid unnecessary memslot rmap walks Paolo Bonzini
  3 siblings, 0 replies; 5+ messages in thread
From: Anthony Yznaga @ 2020-06-02 20:07 UTC (permalink / raw)
  To: kvm, linux-kernel
  Cc: pbonzini, sean.j.christopherson, vkuznets, wanpengli, jmattson,
	joro, tglx, mingo, bp, x86, hpa, steven.sistare, anthony.yznaga

Consolidate the code and correct the comments to show that the actions
taken to update existing mappings to disable or enable dirty logging
are not necessary when creating, moving, or deleting a memslot.

Signed-off-by: Anthony Yznaga <anthony.yznaga@oracle.com>
---
 arch/x86/kvm/x86.c | 104 +++++++++++++++++++++++++----------------------------
 1 file changed, 49 insertions(+), 55 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index d211c8ced6bb..1e70d188d83a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10036,41 +10036,65 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
 }
 
 static void kvm_mmu_slot_apply_flags(struct kvm *kvm,
-				     struct kvm_memory_slot *new)
+				     struct kvm_memory_slot *old,
+				     struct kvm_memory_slot *new,
+				     enum kvm_mr_change change)
 {
-	/* Nothing to do for RO slots */
-	if (new->flags & KVM_MEM_READONLY)
+	/*
+	 * Nothing to do for RO slots or CREATE/MOVE/DELETE of a slot.
+	 * See comments below.
+	 */
+	if ((change != KVM_MR_FLAGS_ONLY) || (new->flags & KVM_MEM_READONLY))
 		return;
 
 	/*
-	 * Call kvm_x86_ops dirty logging hooks when they are valid.
-	 *
-	 * kvm_x86_ops.slot_disable_log_dirty is called when:
-	 *
-	 *  - KVM_MR_CREATE with dirty logging is disabled
-	 *  - KVM_MR_FLAGS_ONLY with dirty logging is disabled in new flag
-	 *
-	 * The reason is, in case of PML, we need to set D-bit for any slots
-	 * with dirty logging disabled in order to eliminate unnecessary GPA
-	 * logging in PML buffer (and potential PML buffer full VMEXIT). This
-	 * guarantees leaving PML enabled during guest's lifetime won't have
-	 * any additional overhead from PML when guest is running with dirty
-	 * logging disabled for memory slots.
+	 * Dirty logging tracks sptes in 4k granularity, meaning that large
+	 * sptes have to be split.  If live migration is successful, the guest
+	 * in the source machine will be destroyed and large sptes will be
+	 * created in the destination. However, if the guest continues to run
+	 * in the source machine (for example if live migration fails), small
+	 * sptes will remain around and cause bad performance.
 	 *
-	 * kvm_x86_ops.slot_enable_log_dirty is called when switching new slot
-	 * to dirty logging mode.
+	 * Scan sptes if dirty logging has been stopped, dropping those
+	 * which can be collapsed into a single large-page spte.  Later
+	 * page faults will create the large-page sptes.
 	 *
-	 * If kvm_x86_ops dirty logging hooks are invalid, use write protect.
+	 * There is no need to do this in any of the following cases:
+	 * CREATE:      No dirty mappings will already exist.
+	 * MOVE/DELETE: The old mappings will already have been cleaned up by
+	 *		kvm_arch_flush_shadow_memslot()
+	 */
+	if ((old->flags & KVM_MEM_LOG_DIRTY_PAGES) &&
+	    !(new->flags & KVM_MEM_LOG_DIRTY_PAGES))
+		kvm_mmu_zap_collapsible_sptes(kvm, new);
+
+	/*
+	 * Enable or disable dirty logging for the slot.
 	 *
-	 * In case of write protect:
+	 * For KVM_MR_DELETE and KVM_MR_MOVE, the shadow pages of the old
+	 * slot have been zapped so no dirty logging updates are needed for
+	 * the old slot.
+	 * For KVM_MR_CREATE and KVM_MR_MOVE, once the new slot is visible
+	 * any mappings that might be created in it will consume the
+	 * properties of the new slot and do not need to be updated here.
 	 *
-	 * Write protect all pages for dirty logging.
+	 * When PML is enabled, the kvm_x86_ops dirty logging hooks are
+	 * called to enable/disable dirty logging.
 	 *
-	 * All the sptes including the large sptes which point to this
-	 * slot are set to readonly. We can not create any new large
-	 * spte on this slot until the end of the logging.
+	 * When disabling dirty logging with PML enabled, the D-bit is set
+	 * for sptes in the slot in order to prevent unnecessary GPA
+	 * logging in the PML buffer (and potential PML buffer full VMEXIT).
+	 * This guarantees leaving PML enabled for the guest's lifetime
+	 * won't have any additional overhead from PML when the guest is
+	 * running with dirty logging disabled.
 	 *
+	 * When enabling dirty logging, large sptes are write-protected
+	 * so they can be split on first write.  New large sptes cannot
+	 * be created for this slot until the end of the logging.
 	 * See the comments in fast_page_fault().
+	 * For small sptes, nothing is done if the dirty log is in the
+	 * initial-all-set state.  Otherwise, depending on whether pml
+	 * is enabled the D-bit or the W-bit will be cleared.
 	 */
 	if (new->flags & KVM_MEM_LOG_DIRTY_PAGES) {
 		if (kvm_x86_ops.slot_enable_log_dirty) {
@@ -10107,39 +10131,9 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 				kvm_mmu_calculate_default_mmu_pages(kvm));
 
 	/*
-	 * Dirty logging tracks sptes in 4k granularity, meaning that large
-	 * sptes have to be split.  If live migration is successful, the guest
-	 * in the source machine will be destroyed and large sptes will be
-	 * created in the destination. However, if the guest continues to run
-	 * in the source machine (for example if live migration fails), small
-	 * sptes will remain around and cause bad performance.
-	 *
-	 * Scan sptes if dirty logging has been stopped, dropping those
-	 * which can be collapsed into a single large-page spte.  Later
-	 * page faults will create the large-page sptes.
-	 *
-	 * There is no need to do this in any of the following cases:
-	 * CREATE:	No dirty mappings will already exist.
-	 * MOVE/DELETE:	The old mappings will already have been cleaned up by
-	 *		kvm_arch_flush_shadow_memslot()
-	 */
-	if (change == KVM_MR_FLAGS_ONLY &&
-		(old->flags & KVM_MEM_LOG_DIRTY_PAGES) &&
-		!(new->flags & KVM_MEM_LOG_DIRTY_PAGES))
-		kvm_mmu_zap_collapsible_sptes(kvm, new);
-
-	/*
-	 * Set up write protection and/or dirty logging for the new slot.
-	 *
-	 * For KVM_MR_DELETE and KVM_MR_MOVE, the shadow pages of old slot have
-	 * been zapped so no dirty logging staff is needed for old slot. For
-	 * KVM_MR_FLAGS_ONLY, the old slot is essentially the same one as the
-	 * new and it's also covered when dealing with the new slot.
-	 *
 	 * FIXME: const-ify all uses of struct kvm_memory_slot.
 	 */
-	if (change == KVM_MR_FLAGS_ONLY)
-		kvm_mmu_slot_apply_flags(kvm, (struct kvm_memory_slot *) new);
+	kvm_mmu_slot_apply_flags(kvm, old, (struct kvm_memory_slot *) new, change);
 
 	/* Free the arrays associated with the old memslot. */
 	if (change == KVM_MR_MOVE)
-- 
2.13.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/3] avoid unnecessary memslot rmap walks
  2020-06-02 20:07 [PATCH 0/3] avoid unnecessary memslot rmap walks Anthony Yznaga
                   ` (2 preceding siblings ...)
  2020-06-02 20:07 ` [PATCH 3/3] KVM: x86: minor code refactor and comments fixup around dirty logging Anthony Yznaga
@ 2020-06-04 18:42 ` Paolo Bonzini
  3 siblings, 0 replies; 5+ messages in thread
From: Paolo Bonzini @ 2020-06-04 18:42 UTC (permalink / raw)
  To: Anthony Yznaga, kvm, linux-kernel
  Cc: sean.j.christopherson, vkuznets, wanpengli, jmattson, joro, tglx,
	mingo, bp, x86, hpa, steven.sistare

On 02/06/20 22:07, Anthony Yznaga wrote:
> While investigating optimizing qemu start time for large memory guests
> I found that kvm_mmu_slot_apply_flags() is walking rmaps to update
> existing sptes when creating or moving a slot but that there won't be
> any existing sptes to update and any sptes inserted once the new memslot
> is visible won't need updating.  I can't find any reason for this not to
> be the case, but I've taken a more cautious approach to fixing this by
> dividing things into three patches.
> 
> Anthony Yznaga (3):
>   KVM: x86: remove unnecessary rmap walk of read-only memslots
>   KVM: x86: avoid unnecessary rmap walks when creating/moving slots
>   KVM: x86: minor code refactor and comments fixup around dirty logging
> 
>  arch/x86/kvm/x86.c | 106 +++++++++++++++++++++++++----------------------------
>  1 file changed, 49 insertions(+), 57 deletions(-)
> 

Queued, thanks.

Paolo


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-06-04 18:42 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-02 20:07 [PATCH 0/3] avoid unnecessary memslot rmap walks Anthony Yznaga
2020-06-02 20:07 ` [PATCH 1/3] KVM: x86: remove unnecessary rmap walk of read-only memslots Anthony Yznaga
2020-06-02 20:07 ` [PATCH 2/3] KVM: x86: avoid unnecessary rmap walks when creating/moving slots Anthony Yznaga
2020-06-02 20:07 ` [PATCH 3/3] KVM: x86: minor code refactor and comments fixup around dirty logging Anthony Yznaga
2020-06-04 18:42 ` [PATCH 0/3] avoid unnecessary memslot rmap walks Paolo Bonzini

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).