mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Sean Christopherson <seanjc@google.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
	 Peter Xu <peterx@redhat.com>,
	Maxim Levitsky <mlevitsk@redhat.com>,
	 Sean Christopherson <seanjc@google.com>
Subject: [PATCH 07/20] KVM: selftests: Continuously reap dirty ring while vCPU is running
Date: Fri, 13 Dec 2024 17:07:08 -0800	[thread overview]
Message-ID: <20241214010721.2356923-8-seanjc@google.com> (raw)
In-Reply-To: <20241214010721.2356923-1-seanjc@google.com>

Continue collecting entries from the dirty ring for the entire time the
vCPU is running.  Collecting exactly once all but guarantees the vCPU will
encounter a "ring full" event and stop.  While testing ring full is
interesting, stopping and doing nothing is not, especially for larger
intervals as the test effectively does nothing for a much longer time.

To balance continuous collection with letting the guest make forward
progress, chunk the interval waiting into 1ms loops (which also makes
the math dead simple).

To maintain coverage for "ring full", collect entries on subsequent
iterations if and only if the ring has been filled at least once.  I.e.
let the ring fill up (if the interval allows), but after that contiuously
empty it so that the vCPU can keep running.

Opportunistically drop unnecessary zero-initialization of "count".

Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 tools/testing/selftests/kvm/dirty_log_test.c | 63 ++++++++++++++------
 1 file changed, 46 insertions(+), 17 deletions(-)

diff --git a/tools/testing/selftests/kvm/dirty_log_test.c b/tools/testing/selftests/kvm/dirty_log_test.c
index 5a04a7bd73e0..2aee047b8b1c 100644
--- a/tools/testing/selftests/kvm/dirty_log_test.c
+++ b/tools/testing/selftests/kvm/dirty_log_test.c
@@ -340,8 +340,6 @@ static uint32_t dirty_ring_collect_one(struct kvm_dirty_gfn *dirty_gfns,
 	struct kvm_dirty_gfn *cur;
 	uint32_t count = 0;
 
-	dirty_ring_prev_iteration_last_page = dirty_ring_last_page;
-
 	while (true) {
 		cur = &dirty_gfns[*fetch_index % test_dirty_ring_count];
 		if (!dirty_gfn_is_dirtied(cur))
@@ -360,17 +358,11 @@ static uint32_t dirty_ring_collect_one(struct kvm_dirty_gfn *dirty_gfns,
 	return count;
 }
 
-static void dirty_ring_continue_vcpu(void)
-{
-	pr_info("Notifying vcpu to continue\n");
-	sem_post(&sem_vcpu_cont);
-}
-
 static void dirty_ring_collect_dirty_pages(struct kvm_vcpu *vcpu, int slot,
 					   void *bitmap, uint32_t num_pages,
 					   uint32_t *ring_buf_idx)
 {
-	uint32_t count = 0, cleared;
+	uint32_t count, cleared;
 
 	/* Only have one vcpu */
 	count = dirty_ring_collect_one(vcpu_map_dirty_ring(vcpu),
@@ -385,9 +377,6 @@ static void dirty_ring_collect_dirty_pages(struct kvm_vcpu *vcpu, int slot,
 	 */
 	TEST_ASSERT(cleared == count, "Reset dirty pages (%u) mismatch "
 		    "with collected (%u)", cleared, count);
-
-	if (READ_ONCE(dirty_ring_vcpu_ring_full))
-		dirty_ring_continue_vcpu();
 }
 
 static void dirty_ring_after_vcpu_run(struct kvm_vcpu *vcpu)
@@ -404,7 +393,6 @@ static void dirty_ring_after_vcpu_run(struct kvm_vcpu *vcpu)
 		sem_post(&sem_vcpu_stop);
 		pr_info("Dirty ring full, waiting for it to be collected\n");
 		sem_wait(&sem_vcpu_cont);
-		pr_info("vcpu continues now.\n");
 		WRITE_ONCE(dirty_ring_vcpu_ring_full, false);
 	} else {
 		TEST_ASSERT(false, "Invalid guest sync status: "
@@ -755,11 +743,52 @@ static void run_test(enum vm_guest_mode mode, void *arg)
 	pthread_create(&vcpu_thread, NULL, vcpu_worker, vcpu);
 
 	while (iteration < p->iterations) {
+		bool saw_dirty_ring_full = false;
+		unsigned long i;
+
+		dirty_ring_prev_iteration_last_page = dirty_ring_last_page;
+
 		/* Give the vcpu thread some time to dirty some pages */
-		usleep(p->interval * 1000);
-		log_mode_collect_dirty_pages(vcpu, TEST_MEM_SLOT_INDEX,
-					     bmap, host_num_pages,
-					     &ring_buf_idx);
+		for (i = 0; i < p->interval; i++) {
+			usleep(1000);
+
+			/*
+			 * Reap dirty pages while the guest is running so that
+			 * dirty ring full events are resolved, i.e. so that a
+			 * larger interval doesn't always end up with a vCPU
+			 * that's effectively blocked.  Collecting while the
+			 * guest is running also verifies KVM doesn't lose any
+			 * state.
+			 *
+			 * For bitmap modes, KVM overwrites the entire bitmap,
+			 * i.e. collecting the bitmaps is destructive.  Collect
+			 * the bitmap only on the first pass, otherwise this
+			 * test would lose track of dirty pages.
+			 */
+			if (i && host_log_mode != LOG_MODE_DIRTY_RING)
+				continue;
+
+			/*
+			 * For the dirty ring, empty the ring on subsequent
+			 * passes only if the ring was filled at least once,
+			 * to verify KVM's handling of a full ring (emptying
+			 * the ring on every pass would make it unlikely the
+			 * vCPU would ever fill the fing).
+			 */
+			if (READ_ONCE(dirty_ring_vcpu_ring_full))
+				saw_dirty_ring_full = true;
+			if (i && !saw_dirty_ring_full)
+				continue;
+
+			log_mode_collect_dirty_pages(vcpu, TEST_MEM_SLOT_INDEX,
+						     bmap, host_num_pages,
+						     &ring_buf_idx);
+
+			if (READ_ONCE(dirty_ring_vcpu_ring_full)) {
+				pr_info("Dirty ring emptied, restarting vCPU\n");
+				sem_post(&sem_vcpu_cont);
+			}
+		}
 
 		/*
 		 * See vcpu_sync_stop_requested definition for details on why
-- 
2.47.1.613.gc27f4b7a9f-goog


  parent reply	other threads:[~2024-12-14  1:07 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-12-14  1:07 [PATCH 00/20] KVM: selftests: Fixes and cleanups for dirty_log_test Sean Christopherson
2024-12-14  1:07 ` [PATCH 01/20] KVM: selftests: Support multiple write retires in dirty_log_test Sean Christopherson
2024-12-14  1:07 ` [PATCH 02/20] KVM: selftests: Sync dirty_log_test iteration to guest *before* resuming Sean Christopherson
2024-12-17 23:58   ` Maxim Levitsky
2024-12-18 21:36     ` Sean Christopherson
2024-12-19 15:11       ` Maxim Levitsky
2024-12-14  1:07 ` [PATCH 03/20] KVM: selftests: Drop signal/kick from dirty ring testcase Sean Christopherson
2024-12-14  1:07 ` [PATCH 04/20] KVM: selftests: Drop stale srandom() initialization from dirty_log_test Sean Christopherson
2024-12-17 23:59   ` Maxim Levitsky
2024-12-14  1:07 ` [PATCH 05/20] KVM: selftests: Precisely track number of dirty/clear pages for each iteration Sean Christopherson
2024-12-17 23:59   ` Maxim Levitsky
2024-12-18 21:37     ` Sean Christopherson
2024-12-14  1:07 ` [PATCH 06/20] KVM: selftests: Read per-page value into local var when verifying dirty_log_test Sean Christopherson
2024-12-17 23:59   ` Maxim Levitsky
2024-12-14  1:07 ` Sean Christopherson [this message]
2024-12-18  0:00   ` [PATCH 07/20] KVM: selftests: Continuously reap dirty ring while vCPU is running Maxim Levitsky
2024-12-19  1:50     ` Sean Christopherson
2024-12-14  1:07 ` [PATCH 08/20] KVM: selftests: Limit dirty_log_test's s390x workaround to s390x Sean Christopherson
2024-12-14  1:07 ` [PATCH 09/20] KVM: selftests: Honor "stop" request in dirty ring test Sean Christopherson
2024-12-18  0:00   ` Maxim Levitsky
2024-12-19  2:00     ` Sean Christopherson
2024-12-19 15:07       ` Maxim Levitsky
2024-12-19 15:23         ` Sean Christopherson
2024-12-19 15:57           ` Maxim Levitsky
2024-12-14  1:07 ` [PATCH 10/20] KVM: selftests: Keep dirty_log_test vCPU in guest until it needs to stop Sean Christopherson
2024-12-18  0:01   ` Maxim Levitsky
2024-12-19 15:59     ` Maxim Levitsky
2024-12-14  1:07 ` [PATCH 11/20] KVM: selftests: Post to sem_vcpu_stop if and only if vcpu_stop is true Sean Christopherson
2024-12-18  0:01   ` Maxim Levitsky
2024-12-14  1:07 ` [PATCH 12/20] KVM: selftests: Use continue to handle all "pass" scenarios in dirty_log_test Sean Christopherson
2024-12-18  0:01   ` Maxim Levitsky
2024-12-14  1:07 ` [PATCH 13/20] KVM: selftests: Print (previous) last_page on dirty page value mismatch Sean Christopherson
2024-12-18  0:01   ` Maxim Levitsky
2024-12-14  1:07 ` [PATCH 14/20] KVM: selftests: Collect *all* dirty entries in each dirty_log_test iteration Sean Christopherson
2024-12-18  0:02   ` Maxim Levitsky
2024-12-19  2:13     ` Sean Christopherson
2024-12-19 12:55       ` Paolo Bonzini
2024-12-19 15:01         ` Maxim Levitsky
2024-12-14  1:07 ` [PATCH 15/20] KVM: sefltests: Verify value of dirty_log_test last page isn't bogus Sean Christopherson
2024-12-18  0:02   ` Maxim Levitsky
2024-12-14  1:07 ` [PATCH 16/20] KVM: selftests: Ensure guest writes min number of pages in dirty_log_test Sean Christopherson
2024-12-18  0:02   ` Maxim Levitsky
2024-12-14  1:07 ` [PATCH 17/20] KVM: selftests: Tighten checks around prev iter's last dirty page in ring Sean Christopherson
2024-12-18  0:03   ` Maxim Levitsky
2024-12-14  1:07 ` [PATCH 18/20] KVM: selftests: Set per-iteration variables at the start of each iteration Sean Christopherson
2024-12-14  1:07 ` [PATCH 19/20] KVM: selftests: Fix an off-by-one in the number of dirty_log_test iterations Sean Christopherson
2024-12-18  0:03   ` Maxim Levitsky
2024-12-14  1:07 ` [PATCH 20/20] KVM: selftests: Allow running a single iteration of dirty_log_test Sean Christopherson
2024-12-18  0:03   ` Maxim Levitsky

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=20241214010721.2356923-8-seanjc@google.com \
    --to=seanjc@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mlevitsk@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peterx@redhat.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

all inboxes | Powered by JetHome®