lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250930172850.598938-2-jthoughton@google.com>
Date: Tue, 30 Sep 2025 17:28:50 +0000
From: James Houghton <jthoughton@...gle.com>
To: Paolo Bonzini <pbonzini@...hat.com>, Sean Christopherson <seanjc@...gle.com>
Cc: James Houghton <jthoughton@...gle.com>, kvm@...r.kernel.org, 
	linux-kernel@...r.kernel.org
Subject: [PATCH 2/2] KVM: selftests: Add parallel KVM_GET_DIRTY_LOG to dirty_log_perf_test

The parallelism is by memslot. This is useful because KVM no longer
serializes KVM_GET_DIRTY_LOG if KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 is
enabled.

Signed-off-by: James Houghton <jthoughton@...gle.com>
---
 .../selftests/kvm/dirty_log_perf_test.c       | 20 ++++++++--
 .../testing/selftests/kvm/include/memstress.h |  2 +
 tools/testing/selftests/kvm/lib/kvm_util.c    |  2 +
 tools/testing/selftests/kvm/lib/memstress.c   | 40 +++++++++++++++++++
 4 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/kvm/dirty_log_perf_test.c b/tools/testing/selftests/kvm/dirty_log_perf_test.c
index e79817bd0e29..8a5f289c4966 100644
--- a/tools/testing/selftests/kvm/dirty_log_perf_test.c
+++ b/tools/testing/selftests/kvm/dirty_log_perf_test.c
@@ -131,8 +131,18 @@ struct test_params {
 	int slots;
 	uint32_t write_percent;
 	bool random_access;
+	bool parallel_get_dirty_log;
 };
 
+static void get_dirty_log(struct kvm_vm *vm, unsigned long *bitmaps[],
+			  struct test_params *p)
+{
+	if (p->parallel_get_dirty_log)
+		memstress_get_dirty_log_parallel(vm, bitmaps, p->slots);
+	else
+		memstress_get_dirty_log(vm, bitmaps, p->slots);
+}
+
 static void run_test(enum vm_guest_mode mode, void *arg)
 {
 	struct test_params *p = arg;
@@ -230,7 +240,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
 			iteration, ts_diff.tv_sec, ts_diff.tv_nsec);
 
 		clock_gettime(CLOCK_MONOTONIC, &start);
-		memstress_get_dirty_log(vm, bitmaps, p->slots);
+		get_dirty_log(vm, bitmaps, p);
 		ts_diff = timespec_elapsed(start);
 		get_dirty_log_total = timespec_add(get_dirty_log_total,
 						   ts_diff);
@@ -292,7 +302,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
 static void help(char *name)
 {
 	puts("");
-	printf("usage: %s [-h] [-a] [-i iterations] [-p offset] [-g] "
+	printf("usage: %s [-h] [-a] [-i iterations] [-p offset] [-g] [-l] "
 	       "[-m mode] [-n] [-b vcpu bytes] [-v vcpus] [-o] [-r random seed ] [-s mem type]"
 	       "[-x memslots] [-w percentage] [-c physical cpus to run test on]\n", name);
 	puts("");
@@ -305,6 +315,7 @@ static void help(char *name)
 	       "     and writes will be tracked as soon as dirty logging is\n"
 	       "     enabled on the memslot (i.e. KVM_DIRTY_LOG_INITIALLY_SET\n"
 	       "     is not enabled).\n");
+	printf(" -l: Do KVM_GET_DIRTY_LOG calls for each memslot in parallel.\n");
 	printf(" -p: specify guest physical test memory offset\n"
 	       "     Warning: a low offset can conflict with the loaded test code.\n");
 	guest_modes_help();
@@ -355,7 +366,7 @@ int main(int argc, char *argv[])
 
 	guest_modes_append_default();
 
-	while ((opt = getopt(argc, argv, "ab:c:eghi:m:nop:r:s:v:x:w:")) != -1) {
+	while ((opt = getopt(argc, argv, "ab:c:eghi:lm:nop:r:s:v:x:w:")) != -1) {
 		switch (opt) {
 		case 'a':
 			p.random_access = true;
@@ -379,6 +390,9 @@ int main(int argc, char *argv[])
 		case 'i':
 			p.iterations = atoi_positive("Number of iterations", optarg);
 			break;
+		case 'l':
+			p.parallel_get_dirty_log = true;
+			break;
 		case 'm':
 			guest_modes_cmdline(optarg);
 			break;
diff --git a/tools/testing/selftests/kvm/include/memstress.h b/tools/testing/selftests/kvm/include/memstress.h
index 9071eb6dea60..3e6ad2cdec80 100644
--- a/tools/testing/selftests/kvm/include/memstress.h
+++ b/tools/testing/selftests/kvm/include/memstress.h
@@ -74,6 +74,8 @@ void memstress_setup_nested(struct kvm_vm *vm, int nr_vcpus, struct kvm_vcpu *vc
 void memstress_enable_dirty_logging(struct kvm_vm *vm, int slots);
 void memstress_disable_dirty_logging(struct kvm_vm *vm, int slots);
 void memstress_get_dirty_log(struct kvm_vm *vm, unsigned long *bitmaps[], int slots);
+void memstress_get_dirty_log_parallel(struct kvm_vm *vm, unsigned long *bitmaps[],
+				      int slots);
 void memstress_clear_dirty_log(struct kvm_vm *vm, unsigned long *bitmaps[],
 			       int slots, uint64_t pages_per_slot);
 unsigned long **memstress_alloc_bitmaps(int slots, uint64_t pages_per_slot);
diff --git a/tools/testing/selftests/kvm/lib/memstress.c b/tools/testing/selftests/kvm/lib/memstress.c
index 557c0a0a5658..abbd96a1c3ba 100644
--- a/tools/testing/selftests/kvm/lib/memstress.c
+++ b/tools/testing/selftests/kvm/lib/memstress.c
@@ -40,6 +40,12 @@ static bool all_vcpu_threads_running;
 
 static struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
 
+struct get_dirty_log_args {
+	struct kvm_vm *vm;
+	unsigned long *bitmap;
+	int slot;
+};
+
 /*
  * Continuously write to the first 8 bytes of each page in the
  * specified region.
@@ -341,6 +347,15 @@ void memstress_disable_dirty_logging(struct kvm_vm *vm, int slots)
 	toggle_dirty_logging(vm, slots, false);
 }
 
+static void *get_dirty_log_worker(void *arg)
+{
+	struct get_dirty_log_args *args = arg;
+
+	kvm_vm_get_dirty_log(args->vm, args->slot, args->bitmap);
+
+	return NULL;
+}
+
 void memstress_get_dirty_log(struct kvm_vm *vm, unsigned long *bitmaps[], int slots)
 {
 	int i;
@@ -352,6 +367,31 @@ void memstress_get_dirty_log(struct kvm_vm *vm, unsigned long *bitmaps[], int sl
 	}
 }
 
+void memstress_get_dirty_log_parallel(struct kvm_vm *vm, unsigned long *bitmaps[],
+				      int slots)
+{
+	struct {
+		pthread_t thd;
+		struct get_dirty_log_args args;
+	} *threads;
+	int i;
+
+	threads = malloc(slots * sizeof(*threads));
+
+	for (i = 0; i < slots; i++) {
+		threads[i].args.vm = vm;
+		threads[i].args.slot = MEMSTRESS_MEM_SLOT_INDEX + i;
+		threads[i].args.bitmap = bitmaps[i];
+		pthread_create(&threads[i].thd, NULL, get_dirty_log_worker,
+			       &threads[i].args);
+	}
+
+	for (i = 0; i < slots; i++)
+		pthread_join(threads[i].thd, NULL);
+
+	free(threads);
+}
+
 void memstress_clear_dirty_log(struct kvm_vm *vm, unsigned long *bitmaps[],
 			       int slots, uint64_t pages_per_slot)
 {
-- 
2.51.0.618.g983fd99d29-goog


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ