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 v2 16/20] KVM: selftests: Ensure guest writes min number of pages in dirty_log_test
Date: Fri, 10 Jan 2025 16:30:00 -0800 [thread overview]
Message-ID: <20250111003004.1235645-17-seanjc@google.com> (raw)
In-Reply-To: <20250111003004.1235645-1-seanjc@google.com>
Ensure the vCPU fully completes at least one write in each dirty_log_test
iteration, as failure to dirty any pages complicates verification and
forces the test to be overly conservative about possible values. E.g.
verification needs to allow the last dirty page from a previous iteration
to have *any* value, because the vCPU could get stuck for multiple
iterations, which is unlikely but can happen in heavily overloaded and/or
nested virtualization setups.
Somewhat arbitrarily set the minimum to 0x100/256; high enough to be
interesting, but not so high as to lead to pointlessly long runtimes.
Opportunistically report the number of writes per iteration for debug
purposes, and so that a human can sanity check the test. Due to each
write targeting a random page, the number of dirty pages will likely be
lower than the number of total writes, but it shouldn't be absurdly lower
(which would suggest the pRNG is broken)
Reported-by: Maxim Levitsky <mlevitsk@redhat.com>
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
tools/testing/selftests/kvm/dirty_log_test.c | 40 ++++++++++++++++++--
1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/kvm/dirty_log_test.c b/tools/testing/selftests/kvm/dirty_log_test.c
index 500257b712e3..c6b843ec8e0c 100644
--- a/tools/testing/selftests/kvm/dirty_log_test.c
+++ b/tools/testing/selftests/kvm/dirty_log_test.c
@@ -37,6 +37,12 @@
/* Interval for each host loop (ms) */
#define TEST_HOST_LOOP_INTERVAL 10UL
+/*
+ * Ensure the vCPU is able to perform a reasonable number of writes in each
+ * iteration to provide a lower bound on coverage.
+ */
+#define TEST_MIN_WRITES_PER_ITERATION 0x100
+
/* Dirty bitmaps are always little endian, so we need to swap on big endian */
#if defined(__s390x__)
# define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7)
@@ -72,6 +78,7 @@ static uint64_t host_page_size;
static uint64_t guest_page_size;
static uint64_t guest_num_pages;
static uint64_t iteration;
+static uint64_t nr_writes;
static bool vcpu_stop;
/*
@@ -107,6 +114,7 @@ static void guest_code(void)
for (i = 0; i < guest_num_pages; i++) {
addr = guest_test_virt_mem + i * guest_page_size;
vcpu_arch_put_guest(*(uint64_t *)addr, READ_ONCE(iteration));
+ nr_writes++;
}
#endif
@@ -118,6 +126,7 @@ static void guest_code(void)
addr = align_down(addr, host_page_size);
vcpu_arch_put_guest(*(uint64_t *)addr, READ_ONCE(iteration));
+ nr_writes++;
}
GUEST_SYNC(1);
@@ -548,8 +557,8 @@ static void vm_dirty_log_verify(enum vm_guest_mode mode, unsigned long **bmap)
}
}
- pr_info("Iteration %2ld: dirty: %-6lu clean: %-6lu\n",
- iteration, nr_dirty_pages, nr_clean_pages);
+ pr_info("Iteration %2ld: dirty: %-6lu clean: %-6lu writes: %-6lu\n",
+ iteration, nr_dirty_pages, nr_clean_pages, nr_writes);
host_dirty_count += nr_dirty_pages;
host_clear_count += nr_clean_pages;
@@ -665,6 +674,8 @@ static void run_test(enum vm_guest_mode mode, void *arg)
host_dirty_count = 0;
host_clear_count = 0;
WRITE_ONCE(dirty_ring_vcpu_ring_full, false);
+ WRITE_ONCE(nr_writes, 0);
+ sync_global_to_guest(vm, nr_writes);
/*
* Ensure the previous iteration didn't leave a dangling semaphore, i.e.
@@ -683,10 +694,22 @@ static void run_test(enum vm_guest_mode mode, void *arg)
dirty_ring_prev_iteration_last_page = dirty_ring_last_page;
- /* Give the vcpu thread some time to dirty some pages */
- for (i = 0; i < p->interval; i++) {
+ /*
+ * Let the vCPU run beyond the configured interval until it has
+ * performed the minimum number of writes. This verifies the
+ * guest is making forward progress, e.g. isn't stuck because
+ * of a KVM bug, and puts a firm floor on test coverage.
+ */
+ for (i = 0; i < p->interval || nr_writes < TEST_MIN_WRITES_PER_ITERATION; i++) {
+ /*
+ * Sleep in 1ms chunks to keep the interval math simple
+ * and so that the test doesn't run too far beyond the
+ * specified interval.
+ */
usleep(1000);
+ sync_global_from_guest(vm, nr_writes);
+
/*
* Reap dirty pages while the guest is running so that
* dirty ring full events are resolved, i.e. so that a
@@ -737,6 +760,12 @@ static void run_test(enum vm_guest_mode mode, void *arg)
WRITE_ONCE(vcpu_stop, false);
sync_global_to_guest(vm, vcpu_stop);
+ /*
+ * Sync the number of writes performed before verification, the
+ * info will be printed along with the dirty/clean page counts.
+ */
+ sync_global_from_guest(vm, nr_writes);
+
/*
* NOTE: for dirty ring, it's possible that we didn't stop at
* GUEST_SYNC but instead we stopped because ring is full;
@@ -760,6 +789,9 @@ static void run_test(enum vm_guest_mode mode, void *arg)
WRITE_ONCE(host_quit, true);
sync_global_to_guest(vm, iteration);
+ WRITE_ONCE(nr_writes, 0);
+ sync_global_to_guest(vm, nr_writes);
+
WRITE_ONCE(dirty_ring_vcpu_ring_full, false);
sem_post(&sem_vcpu_cont);
--
2.47.1.613.gc27f4b7a9f-goog
next prev parent reply other threads:[~2025-01-11 0:30 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-11 0:29 [PATCH v2 00/20] KVM: selftests: Fixes and cleanups for dirty_log_test Sean Christopherson
2025-01-11 0:29 ` [PATCH v2 01/20] KVM: selftests: Support multiple write retires in dirty_log_test Sean Christopherson
2025-01-11 0:29 ` [PATCH v2 02/20] KVM: selftests: Sync dirty_log_test iteration to guest *before* resuming Sean Christopherson
2025-01-11 0:29 ` [PATCH v2 03/20] KVM: selftests: Drop signal/kick from dirty ring testcase Sean Christopherson
2025-01-11 0:29 ` [PATCH v2 04/20] KVM: selftests: Drop stale srandom() initialization from dirty_log_test Sean Christopherson
2025-01-11 0:29 ` [PATCH v2 05/20] KVM: selftests: Precisely track number of dirty/clear pages for each iteration Sean Christopherson
2025-01-11 0:29 ` [PATCH v2 06/20] KVM: selftests: Read per-page value into local var when verifying dirty_log_test Sean Christopherson
2025-01-11 0:29 ` [PATCH v2 07/20] KVM: selftests: Continuously reap dirty ring while vCPU is running Sean Christopherson
2025-01-11 0:29 ` [PATCH v2 08/20] KVM: selftests: Limit dirty_log_test's s390x workaround to s390x Sean Christopherson
2025-01-11 0:29 ` [PATCH v2 09/20] KVM: selftests: Honor "stop" request in dirty ring test Sean Christopherson
2025-01-11 0:29 ` [PATCH v2 10/20] KVM: selftests: Keep dirty_log_test vCPU in guest until it needs to stop Sean Christopherson
2025-01-11 0:29 ` [PATCH v2 11/20] KVM: selftests: Post to sem_vcpu_stop if and only if vcpu_stop is true Sean Christopherson
2025-01-11 0:29 ` [PATCH v2 12/20] KVM: selftests: Use continue to handle all "pass" scenarios in dirty_log_test Sean Christopherson
2025-01-11 0:29 ` [PATCH v2 13/20] KVM: selftests: Print (previous) last_page on dirty page value mismatch Sean Christopherson
2025-01-11 0:29 ` [PATCH v2 14/20] KVM: selftests: Collect *all* dirty entries in each dirty_log_test iteration Sean Christopherson
2025-01-11 0:29 ` [PATCH v2 15/20] KVM: sefltests: Verify value of dirty_log_test last page isn't bogus Sean Christopherson
2025-01-11 0:30 ` Sean Christopherson [this message]
2025-01-11 0:30 ` [PATCH v2 17/20] KVM: selftests: Tighten checks around prev iter's last dirty page in ring Sean Christopherson
2025-01-11 0:30 ` [PATCH v2 18/20] KVM: selftests: Set per-iteration variables at the start of each iteration Sean Christopherson
2025-01-11 0:30 ` [PATCH v2 19/20] KVM: selftests: Fix an off-by-one in the number of dirty_log_test iterations Sean Christopherson
2025-01-11 0:30 ` [PATCH v2 20/20] KVM: selftests: Allow running a single iteration of dirty_log_test Sean Christopherson
2025-01-20 20:34 ` [PATCH v2 00/20] KVM: selftests: Fixes and cleanups for dirty_log_test Maxim Levitsky
2025-02-15 0:50 ` Sean Christopherson
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=20250111003004.1235645-17-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®