Skip to content

Commit dc6df7d

Browse files
Gavin ShanMarc Zyngier
authored andcommitted
KVM: selftests: Automate choosing dirty ring size in dirty_log_test
In the dirty ring case, we rely on vcpu exit due to full dirty ring state. On ARM64 system, there are 4096 host pages when the host page size is 64KB. In this case, the vcpu never exits due to the full dirty ring state. The similar case is 4KB page size on host and 64KB page size on guest. The vcpu corrupts same set of host pages, but the dirty page information isn't collected in the main thread. This leads to infinite loop as the following log shows. # ./dirty_log_test -M dirty-ring -c 65536 -m 5 Setting log mode to: 'dirty-ring' Test iterations: 32, interval: 10 (ms) Testing guest mode: PA-bits:40, VA-bits:48, 4K pages guest physical test memory offset: 0xffbffe0000 vcpu stops because vcpu is kicked out... Notifying vcpu to continue vcpu continues now. Iteration 1 collected 576 pages <No more output afterwards> Fix the issue by automatically choosing the best dirty ring size, to ensure vcpu exit due to full dirty ring state. The option '-c' becomes a hint to the dirty ring count, instead of the value of it. Signed-off-by: Gavin Shan <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 7167190 commit dc6df7d

File tree

1 file changed

+22
-4
lines changed

1 file changed

+22
-4
lines changed

tools/testing/selftests/kvm/dirty_log_test.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
#include "guest_modes.h"
2525
#include "processor.h"
2626

27+
#define DIRTY_MEM_BITS 30 /* 1G */
28+
#define PAGE_SHIFT_4K 12
29+
2730
/* The memory slot index to track dirty pages */
2831
#define TEST_MEM_SLOT_INDEX 1
2932

@@ -273,6 +276,24 @@ static bool dirty_ring_supported(void)
273276

274277
static void dirty_ring_create_vm_done(struct kvm_vm *vm)
275278
{
279+
uint64_t pages;
280+
uint32_t limit;
281+
282+
/*
283+
* We rely on vcpu exit due to full dirty ring state. Adjust
284+
* the ring buffer size to ensure we're able to reach the
285+
* full dirty ring state.
286+
*/
287+
pages = (1ul << (DIRTY_MEM_BITS - vm->page_shift)) + 3;
288+
pages = vm_adjust_num_guest_pages(vm->mode, pages);
289+
if (vm->page_size < getpagesize())
290+
pages = vm_num_host_pages(vm->mode, pages);
291+
292+
limit = 1 << (31 - __builtin_clz(pages));
293+
test_dirty_ring_count = 1 << (31 - __builtin_clz(test_dirty_ring_count));
294+
test_dirty_ring_count = min(limit, test_dirty_ring_count);
295+
pr_info("dirty ring count: 0x%x\n", test_dirty_ring_count);
296+
276297
/*
277298
* Switch to dirty ring mode after VM creation but before any
278299
* of the vcpu creation.
@@ -685,9 +706,6 @@ static struct kvm_vm *create_vm(enum vm_guest_mode mode, struct kvm_vcpu **vcpu,
685706
return vm;
686707
}
687708

688-
#define DIRTY_MEM_BITS 30 /* 1G */
689-
#define PAGE_SHIFT_4K 12
690-
691709
struct test_params {
692710
unsigned long iterations;
693711
unsigned long interval;
@@ -830,7 +848,7 @@ static void help(char *name)
830848
printf("usage: %s [-h] [-i iterations] [-I interval] "
831849
"[-p offset] [-m mode]\n", name);
832850
puts("");
833-
printf(" -c: specify dirty ring size, in number of entries\n");
851+
printf(" -c: hint to dirty ring size, in number of entries\n");
834852
printf(" (only useful for dirty-ring test; default: %"PRIu32")\n",
835853
TEST_DIRTY_RING_COUNT);
836854
printf(" -i: specify iteration counts (default: %"PRIu64")\n",

0 commit comments

Comments
 (0)