From nobody Fri Oct 2 06:17:21 2026 Received: from mail-pg1-f197.google.com (mail-pg1-f197.google.com [209.85.215.197]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6BB783009CB for ; Tue, 4 Aug 2026 17:34:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.197 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785864881; cv=none; b=U2E1qXD2ivTjR9gEFhTZ6qzHkrCJnP4yF6dv4+SM4kEwSzrohzlAErKpKoPmnYrHGILYSxoxzuvTJG7aoM4nAWe0ZNnazTsBpAD4W/9xGzO0t9EAocZDjNmurMo4ytARhGnSMjf9KqdhLn7hLFhNB4N0KSCDCvknDpHscDry/x8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785864881; c=relaxed/simple; bh=cxsYu/SAZXKKH+qzPWN68EM5LaGATeu0vffi9KXr19s=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=tp9N2zBzNfVyylrN+Prx5AmCcdzXQaQgK9wlxmaeSc8s3NRZ2jGEC+E6/2xcjidiMxtBxIkWHIa0l3qZGrpdSYsAWYtvMITqE+xucqfpYS9Pw8Fkg5EEvAaH1h6QbIPydKQa1YwJdaB8VTExTft7rMOGWkP4iRfyz6e3D2z+3Tg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=EW8OktRW; arc=none smtp.client-ip=209.85.215.197 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="EW8OktRW" Received: by mail-pg1-f197.google.com with SMTP id 41be03b00d2f7-ca860baea9fso40265a12.2 for ; Tue, 04 Aug 2026 10:34:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1785864880; x=1786469680; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:reply-to:from:to:cc:subject:date:message-id :reply-to:content-type; bh=UeyWwtdawyJZ7yaU5xxuUItmJbT+/6l6O65XfniG79w=; b=EW8OktRWc50uMj7y46lz26AsbdMSgNTjZ3c0FG+jNy3Fbn/S4ZBRVuNH+RxXYe2oJk Y+4jdE/XJEwu+SOr7WscN9pPIBJ1BWmerJy9w2lWIGxfjnfzqGc6n9FyaLmrwaaV4P00 tlA5hYhTIcJnSGe8MPgBmjp1dZ2Gqaz3Nh6IxSRO5W7YEUpnjjDBK4r7Af6o1PkQSp30 nGmibbbVx3V5qnf33Jy9r1O65UpibN5GRl5Q2pc3pvl2aUdYjzRn8gugwI8mbj1n9JmF 2jgOQmkuLc+egHEiMT2m6rXkBDSrYDPR3g7iMdJgeaQFxBLg/G8jQWar4bILfdG3n1og 4Q6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785864880; x=1786469680; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:reply-to:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to:content-type; bh=UeyWwtdawyJZ7yaU5xxuUItmJbT+/6l6O65XfniG79w=; b=imMh2absDx3C5iT2cnJ4FJFaE01PXsM1crp0e57peCCh/bMur7Fz3WZai0Vm20JT1b Gj/gg7Wb2w9iuuliKXxEA5qWJrnX3J/mDTFylclIH5BaF5sp+VZoCjhIgMFXa10zuyTJ v8lVnCfXtQGXuo+MCwuyy1aWXPqPeEvyOdUgU4BNWt8+m4gz5QebQo2chqs/jgw5u9v9 tFX4RDcAp7/FMJBhaWVlMUCHGNIRCdULru8xgb9994LUEymvy81tAvFvabA5IOlWFNFu //JpfG4FR2qzMApasgXr1R6xEefnyRnLtWy1NkUT1Il2RjnnDgbO2xREoDTxD98gzqEV aZDw== X-Forwarded-Encrypted: i=1; AHgh+Rrfj+OxyypAChk/pzBH3icKjD4A3XWSMnBOdYcTSiW2hzaZ4Iu/vk4tGw/rIZzhfD5ph4G7xMO9+enYp3Q=@vger.kernel.org X-Gm-Message-State: AOJu0YyoFtVuXIxmZo1G/O7HY1TTYVpC1/pKPQ2HB9HWWoH6oJ/KTupq CayEQNDWDXeQlLa6Ati4gPsEoMKVWCWcD/TRQHD3kIOoP+N26Sb+SP+ZAWVTEUqCx3qwJvvrzm/ NUXw4EA== X-Received: from pgbbw28.prod.google.com ([2002:a05:6a02:49c:b0:c8b:2b50:846b]) (user=seanjc job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:734b:b0:3b2:8685:1473 with SMTP id adf61e73a8af0-3cb85dcb2efmr452352637.7.1785864879494; Tue, 04 Aug 2026 10:34:39 -0700 (PDT) Reply-To: Sean Christopherson Date: Tue, 4 Aug 2026 10:34:36 -0700 In-Reply-To: <20260804173437.3339269-1-seanjc@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260804173437.3339269-1-seanjc@google.com> X-Mailer: git-send-email 2.55.0.571.g244d577d93-goog Message-ID: <20260804173437.3339269-2-seanjc@google.com> Subject: [PATCH 1/2] KVM: selftests: Test one random GP counter in PMU arch events testcase From: Sean Christopherson To: Sean Christopherson , Paolo Bonzini Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 --- .../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/testin= g/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_stat= e *state) return ((u64)kvm_random_u32(state) << 32) | kvm_random_u32(state); } =20 -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 m= ax); +u64 kvm_random_u64_in_range(struct kvm_random_state *state, u64 min, u64 m= ax); =20 enum vm_mem_backing_src_type { VM_MEM_SRC_ANONYMOUS, diff --git a/tools/testing/selftests/kvm/lib/test_util.c b/tools/testing/se= lftests/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; } =20 +/* Returns a random u32 in the inclusive range [min, max] */ +u32 kvm_random_u32_in_range(struct kvm_random_state *state, u32 min, u32 m= ax) +{ + u32 value, range; + + TEST_ASSERT(min <=3D max, "PEBKAC, min =3D 0x%x, max =3D 0x%x", min, max); + + value =3D kvm_random_u32(state); + + range =3D max - min; + if (range =3D=3D 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 m= ax) { - u64 value; - u64 range; + u64 value, range; =20 TEST_ASSERT(min <=3D max, "PEBKAC, min =3D 0x%lx, max =3D 0x%lx", min, ma= x); =20 diff --git a/tools/testing/selftests/kvm/x86/pmu_counters_test.c b/tools/te= sting/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; =20 /* 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); =20 GUEST_ASSERT(nr_gp_counters); + i =3D kvm_random_u32_in_range(&kvm_rng, 0, nr_gp_counters - 1); =20 - for (i =3D 0; i < nr_gp_counters; i++) { - u64 eventsel =3D ARCH_PERFMON_EVENTSEL_OS | - ARCH_PERFMON_EVENTSEL_ENABLE | - intel_pmu_arch_events[idx]; + eventsel =3D ARCH_PERFMON_EVENTSEL_OS | ARCH_PERFMON_EVENTSEL_ENABLE | + intel_pmu_arch_events[idx]; =20 - 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)); =20 - __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, ev= entsel); =20 if (!guest_has_perf_global_ctrl) return; --=20 2.55.0.571.g244d577d93-goog From nobody Fri Oct 2 06:17:21 2026 Received: from mail-pf1-f198.google.com (mail-pf1-f198.google.com [209.85.210.198]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9A2D248D860 for ; Tue, 4 Aug 2026 17:34:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.198 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785864883; cv=none; b=YEQBzRkN6aZ+RKREqpurWIdIxaxNtV7hnXblHG3CXpewNwU/JG1Icfg1eSwrQP+C0Zwbbwej55QC4kXg0E+Vv9IkhgAYDR2MDf07olkwbvCxzgeK+0R/7Py7+Rk1Wxqcbzpi4yCfifvPZW6EqFmEa+IoMLwwyGx02xyeWfDLY5E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785864883; c=relaxed/simple; bh=i6Y3AJDIc/+NHhYUrlPbZumjNKFm05ZnO0fppq94cvY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Dx3X8hLQ9JFxRjV+JchB+Jl+m04Lc8MYcTUdDyCnVl6RW0Cx7+nafSq5U2FWVBcREmfUY+l3DhXCibgMscWF043tHdUtNQRrX93wHNkAEFVy5rEZ1AsK2ZIaPNt8RWbBMf7UngXRSaACMSLGs9yv6ucfM0/2iL5i74f00pVxlWw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=nMXkCFRH; arc=none smtp.client-ip=209.85.210.198 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="nMXkCFRH" Received: by mail-pf1-f198.google.com with SMTP id d2e1a72fcca58-84e375d9736so69853b3a.2 for ; Tue, 04 Aug 2026 10:34:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1785864881; x=1786469681; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:reply-to:from:to:cc:subject:date:message-id :reply-to:content-type; bh=RVQO+0wsSIcqGCC1Ku5ayckl1cs0tZZdjNaS1/TooNk=; b=nMXkCFRHLZteD6wSmX/MGkacM+fjrt9n2QN3iXmlgNbdeTMN0JGX/MEMRGNIniDafM sfindOMCA1qFQf7XlETs/Fi2Wx/C06rHgdrMgFkwmPggxwlDMOQIJZ60Uvu+rq3gW5rk vRZmKn9jDhS65bW8EPJLv94qSKW3GvGZeg2/GEXjeK2C5J5E5Pp/Mb0V+I6DVCcwF7rq OGPr5ScgrByhJkkD6Co1zhCb9R57TjDIuVk+JKVQw2RHzQzdqW0RRuXltPQpUg977fdI fi4Jma7Yrb79dPKIw1lHPCGfLpgj6wDZ5j9u7b4dm2SyJHzNIYqIpImcgF40MuHLEkoA b/kw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785864881; x=1786469681; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:reply-to:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to:content-type; bh=RVQO+0wsSIcqGCC1Ku5ayckl1cs0tZZdjNaS1/TooNk=; b=festnO9Vj5qXSYlunni8+j8LLywO8HGofyv7i2rlN15QBUiOO6K/pHP1vVmU9q+4vI ktkEhYOtgtyUQlzXhbqhdhW/wcjzoiWkn2AkJy96fKQop4yCrFrhGFKavJDf8RJlGDdS 8x+oHXISfLV6zu5OrNHYU9XbfjQs89L6J7hCidQC7WvehPvle7/c/VfsH68867YaDG5S b+qYMQymhTm4fFLSKMKivLEeGm4QQHzSf7GoM11kOOof8mYtaku7ccerhpOBi34MmFqA GmOtJ4Xhr6vg8ixD7C5i2BjvFPVL7rjCFLJ/hNThXgrDubVkIX5T1w7KdnW4KX+MzHz1 Le4A== X-Forwarded-Encrypted: i=1; AHgh+Rqwnm+E9QUmtX8r9kvHbv+aeLERYoiInLQaVBUAp1Dq7QN/gsd8A6+VO78eJfIFTzAHFNcPWebF+DgiWlY=@vger.kernel.org X-Gm-Message-State: AOJu0YznYowYbDtyyYlE1sep/DEjuc9OniMYQYLX/HgzRjX+/XruLUDQ qhW7WTABnL+eYG6tEqpXn/W8u2KGDr6rd1u3kPEDOOJrJ8pAQnm7OvRQR5u1kUBIqZoK/nqxo4w KWMfsKw== X-Received: from pfbfj32.prod.google.com ([2002:a05:6a00:3a20:b0:847:82b3:aca]) (user=seanjc job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:1388:b0:847:82dc:452d with SMTP id d2e1a72fcca58-84f2e017ab9mr444843b3a.29.1785864880600; Tue, 04 Aug 2026 10:34:40 -0700 (PDT) Reply-To: Sean Christopherson Date: Tue, 4 Aug 2026 10:34:37 -0700 In-Reply-To: <20260804173437.3339269-1-seanjc@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260804173437.3339269-1-seanjc@google.com> X-Mailer: git-send-email 2.55.0.571.g244d577d93-goog Message-ID: <20260804173437.3339269-3-seanjc@google.com> Subject: [PATCH 2/2] KVM: selftests: Create one VM with many vCPUs for each major PMU counters test From: Sean Christopherson To: Sean Christopherson , Paolo Bonzini Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 --- .../selftests/kvm/x86/pmu_counters_test.c | 212 ++++++++++-------- 1 file changed, 122 insertions(+), 90 deletions(-) diff --git a/tools/testing/selftests/kvm/x86/pmu_counters_test.c b/tools/te= sting/selftests/kvm/x86/pmu_counters_test.c index 8abf17cc9469..c7c566220381 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_featur= e(u8 idx) return __intel_event_to_feature[idx]; } =20 -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_c= ode, + u8 pmu_version, + u64 perf_capabilities, + struct kvm_vcpu **__vcpus[]) { + struct kvm_vcpu **vcpus =3D calloc(nr_vcpus, sizeof(struct kvm_vcpu)); struct kvm_vm *vm; + int i; =20 - vm =3D vm_create_with_one_vcpu(vcpu, guest_code); + *__vcpus =3D vcpus; + + vm =3D 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); =20 @@ -102,13 +106,22 @@ static struct kvm_vm *pmu_vm_create_with_one_vcpu(str= uct 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 =3D 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); + } =20 - vcpu_set_cpuid_property(*vcpu, X86_PROPERTY_PMU_VERSION, pmu_version); return vm; } =20 +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(); } =20 -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_capabilitie= s, + 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 &=3D GENMASK(X86_PROPERTY_PMU_EVENTS_MASK.hi_bit, X86_PROPERTY_PMU_EVENTS_MASK.lo_bit); =20 - vm =3D 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); =20 run_vcpu(vcpu); +} =20 - 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 =3D 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[] =3D { + 0x0, + 0xffffffffu, + 0xaaaaaaaau, + 0x55555555u, + 0xf0f0f0f0u, + 0x0f0f0f0fu, + 0xa0a0a0a0u, + 0x0a0a0a0au, + 0x50505050u, + 0x05050505u, + }; + + pr_info("Testing arch events, PMU version %u, perf_caps =3D %lx\n", + pmu_version, perf_capabilities); + + /* Testing arch events requires a vPMU (there are no negative tests). */ + if (!pmu_version) + return; + + vm =3D pmu_vm_create_with_vcpus((NR_INTEL_ARCH_EVENTS + 2) * ARRAY_SIZE(u= navailable_masks), + 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 =3D 0; j <=3D NR_INTEL_ARCH_EVENTS + 1; j++) { + for (k =3D 1; k < ARRAY_SIZE(unavailable_masks); k++) + __test_arch_events(vcpus[i++], perf_capabilities, j, + unavailable_masks[k]); + } + + pmu_vm_free(vm, vcpus); } =20 /* @@ -493,21 +548,27 @@ static void guest_test_gp_counters(void) GUEST_DONE(); } =20 -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 =3D kvm_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS); + struct kvm_vcpu **vcpus; struct kvm_vm *vm; + u8 j; =20 - vm =3D 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 =3D %lx\n", + nr_gp_counters, pmu_version, perf_capabilities); =20 - vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_NR_GP_COUNTERS, - nr_gp_counters); + vm =3D pmu_vm_create_with_vcpus(nr_gp_counters + 1, guest_test_gp_counter= s, + pmu_version, perf_capabilities, &vcpus); =20 - run_vcpu(vcpu); + for (j =3D 0; j <=3D nr_gp_counters; j++) { + vcpu_set_cpuid_property(vcpus[j], X86_PROPERTY_PMU_NR_GP_COUNTERS, + nr_gp_counters); =20 - kvm_vm_free(vm); + run_vcpu(vcpus[j]); + } + + pmu_vm_free(vm, vcpus); } =20 static void guest_test_fixed_counters(void) @@ -559,59 +620,53 @@ static void guest_test_fixed_counters(void) GUEST_DONE(); } =20 -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_count= ers, + u32 supported_bitmask) { - struct kvm_vcpu *vcpu; - struct kvm_vm *vm; - - vm =3D 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); =20 run_vcpu(vcpu); - - kvm_vm_free(vm); } =20 -static void test_intel_counters(void) +static void test_fixed_counters(u8 pmu_version, u64 perf_capabilities) { u8 nr_fixed_counters =3D kvm_cpu_property(X86_PROPERTY_PMU_NR_FIXED_COUNT= ERS); - u8 nr_gp_counters =3D kvm_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS); + struct kvm_vcpu **vcpus; + struct kvm_vm *vm; + int i =3D 0; + u32 k; + u8 j; + + pr_info("Testing %u fixed counters, PMU version %u, perf_caps =3D %lx\n", + nr_fixed_counters, pmu_version, perf_capabilities); + + + vm =3D pmu_vm_create_with_vcpus((nr_fixed_counters + 1) * BIT(nr_fixed_co= unters), + guest_test_fixed_counters, + pmu_version, perf_capabilities, &vcpus); + + for (j =3D 0; j <=3D nr_fixed_counters; j++) { + for (k =3D 0; k <=3D (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 =3D kvm_cpu_property(X86_PROPERTY_PMU_VERSION); unsigned int i; - u8 v, j; - u32 k; + u8 v; =20 const u64 perf_caps[] =3D { 0, PMU_CAP_FW_WRITES, }; =20 - /* - * 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[] =3D { - 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 +702,9 @@ static void test_intel_counters(void) if (!kvm_has_perf_caps && perf_caps[i]) continue; =20 - pr_info("Testing arch events, PMU version %u, perf_caps =3D %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 =3D 0; j <=3D NR_INTEL_ARCH_EVENTS + 1; j++) { - for (k =3D 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 =3D %lx\n", - v, perf_caps[i]); - for (j =3D 0; j <=3D nr_gp_counters; j++) - test_gp_counters(v, perf_caps[i], j); - - pr_info("Testing fixed counters, PMU version %u, perf_caps =3D %lx\n", - v, perf_caps[i]); - for (j =3D 0; j <=3D nr_fixed_counters; j++) { - for (k =3D 0; k <=3D (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]); } } } --=20 2.55.0.571.g244d577d93-goog