Skip to content

Commit cfe12e6

Browse files
sean-jcbonzini
authored andcommitted
KVM: selftests: Add an option to run vCPUs while disabling dirty logging
Add a command line option to dirty_log_perf_test to run vCPUs for the entire duration of disabling dirty logging. By default, the test stops running runs vCPUs before disabling dirty logging, which is faster but less interesting as it doesn't stress KVM's handling of contention between page faults and the zapping of collapsible SPTEs. Enabling the flag also lets the user verify that KVM is indeed rebuilding zapped SPTEs as huge pages by checking KVM's pages_{1g,2m,4k} stats. Without vCPUs to fault in the zapped SPTEs, the stats will show that KVM is zapping pages, but they never show whether or not KVM actually allows huge pages to be recreated. Note! Enabling the flag can _significantly_ increase runtime, especially if the thread that's disabling dirty logging doesn't have a dedicated pCPU, e.g. if all pCPUs are used to run vCPUs. Signed-off-by: Sean Christopherson <seanjc@google.com> Message-Id: <20220715232107.3775620-5-seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 85f44f8 commit cfe12e6

File tree

1 file changed

+27
-3
lines changed

1 file changed

+27
-3
lines changed

tools/testing/selftests/kvm/dirty_log_perf_test.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ static void arch_cleanup_vm(struct kvm_vm *vm)
5959

6060
static int nr_vcpus = 1;
6161
static uint64_t guest_percpu_mem_size = DEFAULT_PER_VCPU_MEM_SIZE;
62+
static bool run_vcpus_while_disabling_dirty_logging;
6263

6364
/* Host variables */
6465
static u64 dirty_log_manual_caps;
@@ -109,8 +110,13 @@ static void vcpu_worker(struct perf_test_vcpu_args *vcpu_args)
109110
ts_diff.tv_nsec);
110111
}
111112

113+
/*
114+
* Keep running the guest while dirty logging is being disabled
115+
* (iteration is negative) so that vCPUs are accessing memory
116+
* for the entire duration of zapping collapsible SPTEs.
117+
*/
112118
while (current_iteration == READ_ONCE(iteration) &&
113-
!READ_ONCE(host_quit)) {}
119+
READ_ONCE(iteration) >= 0 && !READ_ONCE(host_quit)) {}
114120
}
115121

116122
avg = timespec_div(total, vcpu_last_completed_iteration[vcpu_idx]);
@@ -302,14 +308,26 @@ static void run_test(enum vm_guest_mode mode, void *arg)
302308
}
303309
}
304310

311+
/*
312+
* Run vCPUs while dirty logging is being disabled to stress disabling
313+
* in terms of both performance and correctness. Opt-in via command
314+
* line as this significantly increases time to disable dirty logging.
315+
*/
316+
if (run_vcpus_while_disabling_dirty_logging)
317+
WRITE_ONCE(iteration, -1);
318+
305319
/* Disable dirty logging */
306320
clock_gettime(CLOCK_MONOTONIC, &start);
307321
disable_dirty_logging(vm, p->slots);
308322
ts_diff = timespec_elapsed(start);
309323
pr_info("Disabling dirty logging time: %ld.%.9lds\n",
310324
ts_diff.tv_sec, ts_diff.tv_nsec);
311325

312-
/* Tell the vcpu thread to quit */
326+
/*
327+
* Tell the vCPU threads to quit. No need to manually check that vCPUs
328+
* have stopped running after disabling dirty logging, the join will
329+
* wait for them to exit.
330+
*/
313331
host_quit = true;
314332
perf_test_join_vcpu_threads(nr_vcpus);
315333

@@ -349,6 +367,9 @@ static void help(char *name)
349367
" Warning: a low offset can conflict with the loaded test code.\n");
350368
guest_modes_help();
351369
printf(" -n: Run the vCPUs in nested mode (L2)\n");
370+
printf(" -e: Run vCPUs while dirty logging is being disabled. This\n"
371+
" can significantly increase runtime, especially if there\n"
372+
" isn't a dedicated pCPU for the main thread.\n");
352373
printf(" -b: specify the size of the memory region which should be\n"
353374
" dirtied by each vCPU. e.g. 10M or 3G.\n"
354375
" (default: 1G)\n");
@@ -385,8 +406,11 @@ int main(int argc, char *argv[])
385406

386407
guest_modes_append_default();
387408

388-
while ((opt = getopt(argc, argv, "ghi:p:m:nb:f:v:os:x:")) != -1) {
409+
while ((opt = getopt(argc, argv, "eghi:p:m:nb:f:v:os:x:")) != -1) {
389410
switch (opt) {
411+
case 'e':
412+
/* 'e' is for evil. */
413+
run_vcpus_while_disabling_dirty_logging = true;
390414
case 'g':
391415
dirty_log_manual_caps = 0;
392416
break;

0 commit comments

Comments
 (0)