Kernel KVM virtualization development
 help / color / mirror / Atom feed
* [PATCH v3 0/2] KVM: selftests: Reduce PMC test runtime by ~17x
@ 2026-08-04 21:00 Sean Christopherson
  2026-08-04 21:00 ` [PATCH v3 1/2] KVM: selftests: Test one random GP counter in PMU arch events testcase Sean Christopherson
  2026-08-04 21:00 ` [PATCH v3 2/2] KVM: selftests: Create one VM with many vCPUs for each major PMU counters test Sean Christopherson
  0 siblings, 2 replies; 5+ messages in thread
From: Sean Christopherson @ 2026-08-04 21:00 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel

Reduce the runtime of the PMU counters test on an Emerald Rapids system from
~85 seconds to ~5 seconds by (a) testing one random GP counter in the arch
events test instead of every GP counter and (b) creating one large VM per
"major" test and then running each subtest with a different vCPUs, versus
creating a new single-vCPU VM for every subtest.

AFAICT, there aren't any bugs anywhere in the VM creation flow, there's just
a lot of work to be done.  And VM creation isn't even that slow, but creating
something like 1000+ VMs for the test adds up.

v3:
 - Allocate an array of vCPU pointers, not an array of vCPUs. [Sashiko]
 - Fix a copy+paste goof that caused the GP counters test to always run with
   the maximum number of GP counters. [Sashiko]
 - Fix a (benign) off-by-one error in the arch events tests. [Sashiko]

v2:
 - Fail hard.  Pretend this version doesn't exist.
 - https://lore.kernel.org/all/20260804204048.3401810-1-seanjc@google.com

v1: https://lore.kernel.org/all/20260804173437.3339269-1-seanjc@google.com


Sean Christopherson (2):
  KVM: selftests: Test one random GP counter in PMU arch events testcase
  KVM: selftests: Create one VM with many vCPUs for each major PMU
    counters test

 .../testing/selftests/kvm/include/test_util.h |   4 +-
 tools/testing/selftests/kvm/lib/test_util.c   |  22 +-
 .../selftests/kvm/x86/pmu_counters_test.c     | 229 ++++++++++--------
 3 files changed, 149 insertions(+), 106 deletions(-)


base-commit: 2dfab80a305700a45bd947350dae253ba4e30c41
-- 
2.55.0.571.g244d577d93-goog


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v3 1/2] KVM: selftests: Test one random GP counter in PMU arch events testcase
  2026-08-04 21:00 [PATCH v3 0/2] KVM: selftests: Reduce PMC test runtime by ~17x Sean Christopherson
@ 2026-08-04 21:00 ` Sean Christopherson
  2026-08-04 21:00 ` [PATCH v3 2/2] KVM: selftests: Create one VM with many vCPUs for each major PMU counters test Sean Christopherson
  1 sibling, 0 replies; 5+ messages in thread
From: Sean Christopherson @ 2026-08-04 21:00 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel

To significantly reduce the PMU counter test's runtime, without sacrificing
test coverage in the aggregate, test a random GP counter in the arch events
testcase instead of testing every possible GP counter.  Testing every PMC
in every run of the test significantly increases the runtime of the test,
without providing an equivalent increase in validation coverage, as the
odds of a KVM having a bug that only affected a subset of counters and only
when testing all other counters are extremely low.

Opportunistically clean up kvm_random_u64_in_range() to eliminate
unnecessary newlines.

Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 .../testing/selftests/kvm/include/test_util.h |  4 ++--
 tools/testing/selftests/kvm/lib/test_util.c   | 22 +++++++++++++++----
 .../selftests/kvm/x86/pmu_counters_test.c     | 18 +++++++--------
 3 files changed, 28 insertions(+), 16 deletions(-)

diff --git a/tools/testing/selftests/kvm/include/test_util.h b/tools/testing/selftests/kvm/include/test_util.h
index e8356ee54d7b..a6a3e1657895 100644
--- a/tools/testing/selftests/kvm/include/test_util.h
+++ b/tools/testing/selftests/kvm/include/test_util.h
@@ -135,8 +135,8 @@ static inline u64 kvm_random_u64(struct kvm_random_state *state)
 	return ((u64)kvm_random_u32(state) << 32) | kvm_random_u32(state);
 }
 
-u64 kvm_random_u64_in_range(struct kvm_random_state *state, u64 min,
-			    u64 max);
+u32 kvm_random_u32_in_range(struct kvm_random_state *state, u32 min, u32 max);
+u64 kvm_random_u64_in_range(struct kvm_random_state *state, u64 min, u64 max);
 
 enum vm_mem_backing_src_type {
 	VM_MEM_SRC_ANONYMOUS,
diff --git a/tools/testing/selftests/kvm/lib/test_util.c b/tools/testing/selftests/kvm/lib/test_util.c
index 6b00ab11f3c0..4dff72f6bd34 100644
--- a/tools/testing/selftests/kvm/lib/test_util.c
+++ b/tools/testing/selftests/kvm/lib/test_util.c
@@ -43,12 +43,26 @@ u32 kvm_random_u32(struct kvm_random_state *state)
 	return state->seed;
 }
 
+/* Returns a random u32 in the inclusive range [min, max] */
+u32 kvm_random_u32_in_range(struct kvm_random_state *state, u32 min, u32 max)
+{
+	u32 value, range;
+
+	TEST_ASSERT(min <= max, "PEBKAC, min = 0x%x, max = 0x%x", min, max);
+
+	value = kvm_random_u32(state);
+
+	range = max - min;
+	if (range == UINT_MAX)
+		return value;
+
+	return min + (value % (range + 1));
+}
+
 /* Returns a random u64 in the inclusive range [min, max] */
-u64 kvm_random_u64_in_range(struct kvm_random_state *state, u64 min,
-			    u64 max)
+u64 kvm_random_u64_in_range(struct kvm_random_state *state, u64 min, u64 max)
 {
-	u64 value;
-	u64 range;
+	u64 value, range;
 
 	TEST_ASSERT(min <= max, "PEBKAC, min = 0x%lx, max = 0x%lx", min, max);
 
diff --git a/tools/testing/selftests/kvm/x86/pmu_counters_test.c b/tools/testing/selftests/kvm/x86/pmu_counters_test.c
index dc6afac3aa91..8abf17cc9469 100644
--- a/tools/testing/selftests/kvm/x86/pmu_counters_test.c
+++ b/tools/testing/selftests/kvm/x86/pmu_counters_test.c
@@ -273,6 +273,7 @@ static void guest_test_arch_event(u8 idx)
 	struct kvm_x86_pmu_feature gp_event, fixed_event;
 	u32 base_pmc_msr;
 	unsigned int i;
+	u64 eventsel;
 
 	/* The host side shouldn't invoke this without a guest PMU. */
 	GUEST_ASSERT(pmu_version);
@@ -287,19 +288,16 @@ static void guest_test_arch_event(u8 idx)
 	GUEST_ASSERT_EQ(idx, gp_event.f.bit);
 
 	GUEST_ASSERT(nr_gp_counters);
+	i = kvm_random_u32_in_range(&kvm_rng, 0, nr_gp_counters - 1);
 
-	for (i = 0; i < nr_gp_counters; i++) {
-		u64 eventsel = ARCH_PERFMON_EVENTSEL_OS |
-				    ARCH_PERFMON_EVENTSEL_ENABLE |
-				    intel_pmu_arch_events[idx];
+	eventsel = ARCH_PERFMON_EVENTSEL_OS | ARCH_PERFMON_EVENTSEL_ENABLE |
+		   intel_pmu_arch_events[idx];
 
-		wrmsr(MSR_P6_EVNTSEL0 + i, 0);
-		if (guest_has_perf_global_ctrl)
-			wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, BIT_ULL(i));
+	wrmsr(MSR_P6_EVNTSEL0 + i, 0);
+	if (guest_has_perf_global_ctrl)
+		wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, BIT_ULL(i));
 
-		__guest_test_arch_event(idx, i, base_pmc_msr + i,
-					MSR_P6_EVNTSEL0 + i, eventsel);
-	}
+	__guest_test_arch_event(idx, i, base_pmc_msr + i, MSR_P6_EVNTSEL0 + i, eventsel);
 
 	if (!guest_has_perf_global_ctrl)
 		return;
-- 
2.55.0.571.g244d577d93-goog


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v3 2/2] KVM: selftests: Create one VM with many vCPUs for each major PMU counters test
  2026-08-04 21:00 [PATCH v3 0/2] KVM: selftests: Reduce PMC test runtime by ~17x Sean Christopherson
  2026-08-04 21:00 ` [PATCH v3 1/2] KVM: selftests: Test one random GP counter in PMU arch events testcase Sean Christopherson
@ 2026-08-04 21:00 ` Sean Christopherson
  2026-08-04 21:12   ` sashiko-bot
  1 sibling, 1 reply; 5+ messages in thread
From: Sean Christopherson @ 2026-08-04 21:00 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel

To reduce the runtime of the PMU counters test by an order of magnitude,
create one VM per category of test (arch events, GP PMCs, fixed PMCs),
with N vCPUs per VM, where 'N' is the number of testscases to run per
category.  The vast majority of the test's runtime is spent creating VMs,
because while creating a VM only takes a few milliseconds, the total time
adds up when creating hundreds of VMs.  The only reason the test creates
so many VMs is because KVM disallows changing the virtual PMU model after
a vCPU runs, so rather than create an entirely new VM just to get a "fresh"
vCPUs, simply use a different vCPU.

On an Emerald Rapids host, this reduces the runtime from 75+ seconds to
less than 6 seconds.

Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 .../selftests/kvm/x86/pmu_counters_test.c     | 211 ++++++++++--------
 1 file changed, 121 insertions(+), 90 deletions(-)

diff --git a/tools/testing/selftests/kvm/x86/pmu_counters_test.c b/tools/testing/selftests/kvm/x86/pmu_counters_test.c
index 8abf17cc9469..08bfa82d7ab8 100644
--- a/tools/testing/selftests/kvm/x86/pmu_counters_test.c
+++ b/tools/testing/selftests/kvm/x86/pmu_counters_test.c
@@ -87,14 +87,18 @@ static struct kvm_intel_pmu_event intel_event_to_feature(u8 idx)
 	return __intel_event_to_feature[idx];
 }
 
-static struct kvm_vm *pmu_vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,
-						  void *guest_code,
-						  u8 pmu_version,
-						  u64 perf_capabilities)
+static struct kvm_vm *pmu_vm_create_with_vcpus(u32 nr_vcpus, void *guest_code,
+					       u8 pmu_version,
+					       u64 perf_capabilities,
+					       struct kvm_vcpu **__vcpus[])
 {
+	struct kvm_vcpu **vcpus = calloc(nr_vcpus, sizeof(*vcpus));
 	struct kvm_vm *vm;
+	int i;
 
-	vm = vm_create_with_one_vcpu(vcpu, guest_code);
+	*__vcpus = vcpus;
+
+	vm = vm_create_with_vcpus(nr_vcpus, guest_code, vcpus);
 	sync_global_to_guest(vm, kvm_pmu_version);
 	sync_global_to_guest(vm, hardware_pmu_arch_events);
 
@@ -102,13 +106,22 @@ static struct kvm_vm *pmu_vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,
 	 * Set PERF_CAPABILITIES before PMU version as KVM disallows enabling
 	 * features via PERF_CAPABILITIES if the guest doesn't have a vPMU.
 	 */
-	if (kvm_has_perf_caps)
-		vcpu_set_msr(*vcpu, MSR_IA32_PERF_CAPABILITIES, perf_capabilities);
+	for (i = 0; i < nr_vcpus; i++) {
+		if (kvm_has_perf_caps)
+			vcpu_set_msr(vcpus[i], MSR_IA32_PERF_CAPABILITIES, perf_capabilities);
+
+		vcpu_set_cpuid_property(vcpus[i], X86_PROPERTY_PMU_VERSION, pmu_version);
+	}
 
-	vcpu_set_cpuid_property(*vcpu, X86_PROPERTY_PMU_VERSION, pmu_version);
 	return vm;
 }
 
+static void pmu_vm_free(struct kvm_vm *vm, struct kvm_vcpu **vcpus)
+{
+	kvm_vm_free(vm);
+	free(vcpus);
+}
+
 static void run_vcpu(struct kvm_vcpu *vcpu)
 {
 	struct ucall uc;
@@ -326,30 +339,72 @@ static void guest_test_arch_events(void)
 	GUEST_DONE();
 }
 
-static void test_arch_events(u8 pmu_version, u64 perf_capabilities,
-			     u8 length, u32 unavailable_mask)
+static void __test_arch_events(struct kvm_vcpu *vcpu, u64 perf_capabilities,
+			       u8 length, u32 unavailable_mask)
 {
-	struct kvm_vcpu *vcpu;
-	struct kvm_vm *vm;
-
-	/* Testing arch events requires a vPMU (there are no negative tests). */
-	if (!pmu_version)
-		return;
-
 	unavailable_mask &= GENMASK(X86_PROPERTY_PMU_EVENTS_MASK.hi_bit,
 				    X86_PROPERTY_PMU_EVENTS_MASK.lo_bit);
 
-	vm = pmu_vm_create_with_one_vcpu(&vcpu, guest_test_arch_events,
-					 pmu_version, perf_capabilities);
-
 	vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_EBX_BIT_VECTOR_LENGTH,
 				length);
 	vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_EVENTS_MASK,
 				unavailable_mask);
 
 	run_vcpu(vcpu);
+}
 
-	kvm_vm_free(vm);
+static void test_arch_events(u8 pmu_version, u64 perf_capabilities)
+{
+	struct kvm_vcpu **vcpus;
+	struct kvm_vm *vm;
+	int i = 0;
+	u32 k;
+	u8 j;
+
+	/*
+	 * To keep the total runtime reasonable, test only a handful of select,
+	 * semi-arbitrary values for the mask of unavailable PMU events.  Test
+	 * 0 (all events available) and all ones (no events available) as well
+	 * as alternating bit sequencues, e.g. to detect if KVM is checking the
+	 * wrong bit(s).
+	 */
+	const u32 unavailable_masks[] = {
+		0x0,
+		0xffffffffu,
+		0xaaaaaaaau,
+		0x55555555u,
+		0xf0f0f0f0u,
+		0x0f0f0f0fu,
+		0xa0a0a0a0u,
+		0x0a0a0a0au,
+		0x50505050u,
+		0x05050505u,
+	};
+
+	pr_info("Testing arch events, PMU version %u, perf_caps = %lx\n",
+		pmu_version, perf_capabilities);
+
+	/* Testing arch events requires a vPMU (there are no negative tests). */
+	if (!pmu_version)
+		return;
+
+	vm = pmu_vm_create_with_vcpus((NR_INTEL_ARCH_EVENTS + 2) * (ARRAY_SIZE(unavailable_masks) - 1),
+				      guest_test_arch_events, pmu_version,
+				      perf_capabilities, &vcpus);
+
+	/*
+	 * Test single bits for all PMU version and lengths up the number of
+	 * events +1 (to verify KVM doesn't do weird things if the guest length
+	 * is greater than the host length).  Explicitly test a mask of '0' and
+	 * all ones i.e. all events being available and unavailable.
+	 */
+	for (j = 0; j <= NR_INTEL_ARCH_EVENTS + 1; j++) {
+		for (k = 1; k < ARRAY_SIZE(unavailable_masks); k++)
+			__test_arch_events(vcpus[i++], perf_capabilities, j,
+					   unavailable_masks[k]);
+	}
+
+	pmu_vm_free(vm, vcpus);
 }
 
 /*
@@ -493,21 +548,26 @@ static void guest_test_gp_counters(void)
 	GUEST_DONE();
 }
 
-static void test_gp_counters(u8 pmu_version, u64 perf_capabilities,
-			     u8 nr_gp_counters)
+static void test_gp_counters(u8 pmu_version, u64 perf_capabilities)
 {
-	struct kvm_vcpu *vcpu;
+	u8 nr_gp_counters = kvm_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);
+	struct kvm_vcpu **vcpus;
 	struct kvm_vm *vm;
+	u8 j;
 
-	vm = pmu_vm_create_with_one_vcpu(&vcpu, guest_test_gp_counters,
-					 pmu_version, perf_capabilities);
+	pr_info("Testing %u GP counters, PMU version %u, perf_caps = %lx\n",
+		nr_gp_counters, pmu_version, perf_capabilities);
 
-	vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_NR_GP_COUNTERS,
-				nr_gp_counters);
+	vm = pmu_vm_create_with_vcpus(nr_gp_counters + 1, guest_test_gp_counters,
+				      pmu_version, perf_capabilities, &vcpus);
 
-	run_vcpu(vcpu);
+	for (j = 0; j <= nr_gp_counters; j++) {
+		vcpu_set_cpuid_property(vcpus[j], X86_PROPERTY_PMU_NR_GP_COUNTERS, j);
 
-	kvm_vm_free(vm);
+		run_vcpu(vcpus[j]);
+	}
+
+	pmu_vm_free(vm, vcpus);
 }
 
 static void guest_test_fixed_counters(void)
@@ -559,59 +619,53 @@ static void guest_test_fixed_counters(void)
 	GUEST_DONE();
 }
 
-static void test_fixed_counters(u8 pmu_version, u64 perf_capabilities,
-				u8 nr_fixed_counters, u32 supported_bitmask)
+static void __test_fixed_counters(struct kvm_vcpu *vcpu, u8 nr_fixed_counters,
+				  u32 supported_bitmask)
 {
-	struct kvm_vcpu *vcpu;
-	struct kvm_vm *vm;
-
-	vm = pmu_vm_create_with_one_vcpu(&vcpu, guest_test_fixed_counters,
-					 pmu_version, perf_capabilities);
-
 	vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_FIXED_COUNTERS_BITMASK,
 				supported_bitmask);
 	vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_NR_FIXED_COUNTERS,
 				nr_fixed_counters);
 
 	run_vcpu(vcpu);
-
-	kvm_vm_free(vm);
 }
 
-static void test_intel_counters(void)
+static void test_fixed_counters(u8 pmu_version, u64 perf_capabilities)
 {
 	u8 nr_fixed_counters = kvm_cpu_property(X86_PROPERTY_PMU_NR_FIXED_COUNTERS);
-	u8 nr_gp_counters = kvm_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);
+	struct kvm_vcpu **vcpus;
+	struct kvm_vm *vm;
+	int i = 0;
+	u32 k;
+	u8 j;
+
+	pr_info("Testing %u fixed counters, PMU version %u, perf_caps = %lx\n",
+		nr_fixed_counters, pmu_version, perf_capabilities);
+
+
+	vm = pmu_vm_create_with_vcpus((nr_fixed_counters + 1) * BIT(nr_fixed_counters),
+				      guest_test_fixed_counters,
+				      pmu_version, perf_capabilities, &vcpus);
+
+	for (j = 0; j <= nr_fixed_counters; j++) {
+		for (k = 0; k <= (BIT(nr_fixed_counters) - 1); k++)
+			__test_fixed_counters(vcpus[i++], j, k);
+	}
+
+	pmu_vm_free(vm, vcpus);
+}
+
+static void test_intel_counters(void)
+{
 	u8 pmu_version = kvm_cpu_property(X86_PROPERTY_PMU_VERSION);
 	unsigned int i;
-	u8 v, j;
-	u32 k;
+	u8 v;
 
 	const u64 perf_caps[] = {
 		0,
 		PMU_CAP_FW_WRITES,
 	};
 
-	/*
-	 * To keep the total runtime reasonable, test only a handful of select,
-	 * semi-arbitrary values for the mask of unavailable PMU events.  Test
-	 * 0 (all events available) and all ones (no events available) as well
-	 * as alternating bit sequencues, e.g. to detect if KVM is checking the
-	 * wrong bit(s).
-	 */
-	const u32 unavailable_masks[] = {
-		0x0,
-		0xffffffffu,
-		0xaaaaaaaau,
-		0x55555555u,
-		0xf0f0f0f0u,
-		0x0f0f0f0fu,
-		0xa0a0a0a0u,
-		0x0a0a0a0au,
-		0x50505050u,
-		0x05050505u,
-	};
-
 	/*
 	 * Test up to PMU v5, which is the current maximum version defined by
 	 * Intel, i.e. is the last version that is guaranteed to be backwards
@@ -647,32 +701,9 @@ static void test_intel_counters(void)
 			if (!kvm_has_perf_caps && perf_caps[i])
 				continue;
 
-			pr_info("Testing arch events, PMU version %u, perf_caps = %lx\n",
-				v, perf_caps[i]);
-
-			/*
-			 * Test single bits for all PMU version and lengths up
-			 * the number of events +1 (to verify KVM doesn't do
-			 * weird things if the guest length is greater than the
-			 * host length).  Explicitly test a mask of '0' and all
-			 * ones i.e. all events being available and unavailable.
-			 */
-			for (j = 0; j <= NR_INTEL_ARCH_EVENTS + 1; j++) {
-				for (k = 1; k < ARRAY_SIZE(unavailable_masks); k++)
-					test_arch_events(v, perf_caps[i], j, unavailable_masks[k]);
-			}
-
-			pr_info("Testing GP counters, PMU version %u, perf_caps = %lx\n",
-				v, perf_caps[i]);
-			for (j = 0; j <= nr_gp_counters; j++)
-				test_gp_counters(v, perf_caps[i], j);
-
-			pr_info("Testing fixed counters, PMU version %u, perf_caps = %lx\n",
-				v, perf_caps[i]);
-			for (j = 0; j <= nr_fixed_counters; j++) {
-				for (k = 0; k <= (BIT(nr_fixed_counters) - 1); k++)
-					test_fixed_counters(v, perf_caps[i], j, k);
-			}
+			test_arch_events(v, perf_caps[i]);
+			test_gp_counters(v, perf_caps[i]);
+			test_fixed_counters(v, perf_caps[i]);
 		}
 	}
 }
-- 
2.55.0.571.g244d577d93-goog


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 2/2] KVM: selftests: Create one VM with many vCPUs for each major PMU counters test
  2026-08-04 21:00 ` [PATCH v3 2/2] KVM: selftests: Create one VM with many vCPUs for each major PMU counters test Sean Christopherson
@ 2026-08-04 21:12   ` sashiko-bot
  2026-08-04 21:21     ` Sean Christopherson
  0 siblings, 1 reply; 5+ messages in thread
From: sashiko-bot @ 2026-08-04 21:12 UTC (permalink / raw)
  To: Sean Christopherson; +Cc: kvm

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Medium] The test now demands up to 144 vCPUs per VM and will assert/crash on hosts with lower KVM max vCPU limits.
- [Low] The `perf_capabilities` parameter is unused in `__test_arch_events`.
- [Low] Confusing and unusual pointer syntax `struct kvm_vcpu **__vcpus[]` is used for an out parameter.
--

--- Patch [2]: [PATCH v3 2/2] KVM: selftests: Create one VM with many vCPUs for each major PMU counters test ---
commit 135d3508be788c9140c4a2eec25c4bc440f48012
Author: Sean Christopherson <seanjc@google.com>

KVM: selftests: Create one VM with many vCPUs for each major PMU counters test

This commit updates the KVM PMU counters test to batch test cases into fewer
VMs by using multiple vCPUs per VM. This significantly reduces the total
runtime spent creating and destroying VMs.

> diff --git a/tools/testing/selftests/kvm/x86/pmu_counters_test.c b/tools/testing/selftests/kvm/x86/pmu_counters_test.c
> index 8abf17cc9469d..08bfa82d7ab84 100644
> --- a/tools/testing/selftests/kvm/x86/pmu_counters_test.c
> +++ b/tools/testing/selftests/kvm/x86/pmu_counters_test.c
> @@ -87,14 +87,18 @@ static struct kvm_intel_pmu_event intel_event_to_feature(u8 idx)
>  	return __intel_event_to_feature[idx];
>  }
>  
> -static struct kvm_vm *pmu_vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,
> -						  void *guest_code,
> -						  u8 pmu_version,
> -						  u64 perf_capabilities)
> +static struct kvm_vm *pmu_vm_create_with_vcpus(u32 nr_vcpus, void *guest_code,
> +					       u8 pmu_version,
> +					       u64 perf_capabilities,
> +					       struct kvm_vcpu **__vcpus[])

[Severity: Low]
This isn't a bug, but is the struct kvm_vcpu **__vcpus[] signature
intentional? Mixing double pointers with array brackets in a function
signature can be a bit confusing to read compared to ***__vcpus.

[ ... ]

> @@ -326,30 +339,72 @@ static void guest_test_arch_events(void)
>  	GUEST_DONE();
>  }
>  
> -static void test_arch_events(u8 pmu_version, u64 perf_capabilities,
> -			     u8 length, u32 unavailable_mask)
> +static void __test_arch_events(struct kvm_vcpu *vcpu, u64 perf_capabilities,
> +			       u8 length, u32 unavailable_mask)
>  {

[Severity: Low]
Is the perf_capabilities parameter still needed here? It looks like it is
no longer referenced in the function body since the MSR setup was moved into
pmu_vm_create_with_vcpus().

> -	struct kvm_vcpu *vcpu;
> -	struct kvm_vm *vm;
> -
> -	/* Testing arch events requires a vPMU (there are no negative tests). */
> -	if (!pmu_version)
> -		return;
> -
>  	unavailable_mask &= GENMASK(X86_PROPERTY_PMU_EVENTS_MASK.hi_bit,
>  				    X86_PROPERTY_PMU_EVENTS_MASK.lo_bit);
>  

[ ... ]

> +static void test_arch_events(u8 pmu_version, u64 perf_capabilities)
> +{
> +	struct kvm_vcpu **vcpus;
> +	struct kvm_vm *vm;
> +	int i = 0;
> +	u32 k;
> +	u8 j;
> +

[ ... ]

> +	pr_info("Testing arch events, PMU version %u, perf_caps = %lx\n",
> +		pmu_version, perf_capabilities);
> +
> +	/* Testing arch events requires a vPMU (there are no negative tests). */
> +	if (!pmu_version)
> +		return;
> +
> +	vm = pmu_vm_create_with_vcpus((NR_INTEL_ARCH_EVENTS + 2) * (ARRAY_SIZE(unavailable_masks) - 1),
> +				      guest_test_arch_events, pmu_version,
> +				      perf_capabilities, &vcpus);

[Severity: Medium]
Could this cause the test to assert on hosts with lower vCPU limits?

This calculation requests up to 144 vCPUs per VM ((14 + 2) * (10 - 1)). If the 
host has a KVM_CAP_MAX_VCPUS limit lower than 144 (which is common in nested
virtualization or lightweight VMs), vm_create_with_vcpus() might fail with a
hard assertion.

Should this check against the host limit and either skip via TEST_REQUIRE()
or batch the creations into smaller groups of vCPUs?

> +
> +	/*
> +	 * Test single bits for all PMU version and lengths up the number of
> +	 * events +1 (to verify KVM doesn't do weird things if the guest length
> +	 * is greater than the host length).  Explicitly test a mask of '0' and
> +	 * all ones i.e. all events being available and unavailable.
> +	 */

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260804210046.3413149-1-seanjc@google.com?part=2

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 2/2] KVM: selftests: Create one VM with many vCPUs for each major PMU counters test
  2026-08-04 21:12   ` sashiko-bot
@ 2026-08-04 21:21     ` Sean Christopherson
  0 siblings, 0 replies; 5+ messages in thread
From: Sean Christopherson @ 2026-08-04 21:21 UTC (permalink / raw)
  To: sashiko-reviews; +Cc: kvm

On Tue, Aug 04, 2026, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
> > +	pr_info("Testing arch events, PMU version %u, perf_caps = %lx\n",
> > +		pmu_version, perf_capabilities);
> > +
> > +	/* Testing arch events requires a vPMU (there are no negative tests). */
> > +	if (!pmu_version)
> > +		return;
> > +
> > +	vm = pmu_vm_create_with_vcpus((NR_INTEL_ARCH_EVENTS + 2) * (ARRAY_SIZE(unavailable_masks) - 1),
> > +				      guest_test_arch_events, pmu_version,
> > +				      perf_capabilities, &vcpus);
> 
> [Severity: Medium]
> Could this cause the test to assert on hosts with lower vCPU limits?
> 
> This calculation requests up to 144 vCPUs per VM ((14 + 2) * (10 - 1)). If the 
> host has a KVM_CAP_MAX_VCPUS limit lower than 144 (which is common in nested
> virtualization or lightweight VMs), 

No, it's not.  Unless userspace overwrites the VM's max vCPUs, KVM x86's *minimum*
value for KVM_CAP_MAX_VCPUS is 1024.

	case KVM_CAP_MAX_VCPUS:
		r = KVM_MAX_VCPUS;
		if (kvm)
			r = kvm->max_vcpus;
		break;

  #ifdef CONFIG_KVM_MAX_NR_VCPUS
  #define KVM_MAX_VCPUS CONFIG_KVM_MAX_NR_VCPUS
  #else
  #define KVM_MAX_VCPUS 1024
  #endif


  config KVM_MAX_NR_VCPUS
	int "Maximum number of vCPUs per KVM guest"
	depends on KVM_X86
	range 1024 4096
	default 4096 if MAXSMP
	default 1024


KVM_CAP_NR_VCPUS incorporates the number of CPUs in the system, but that's purely
a "suggestion" for userspace.

	case KVM_CAP_NR_VCPUS:
		r = min_t(unsigned int, num_online_cpus(), KVM_MAX_VCPUS);
		break;

> vm_create_with_vcpus() might fail with a hard assertion.
> 
> Should this check against the host limit and either skip via TEST_REQUIRE()
> or batch the creations into smaller groups of vCPUs?

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-08-04 21:21 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-04 21:00 [PATCH v3 0/2] KVM: selftests: Reduce PMC test runtime by ~17x Sean Christopherson
2026-08-04 21:00 ` [PATCH v3 1/2] KVM: selftests: Test one random GP counter in PMU arch events testcase Sean Christopherson
2026-08-04 21:00 ` [PATCH v3 2/2] KVM: selftests: Create one VM with many vCPUs for each major PMU counters test Sean Christopherson
2026-08-04 21:12   ` sashiko-bot
2026-08-04 21:21     ` Sean Christopherson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox