From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D6694E94617 for ; Mon, 9 Feb 2026 22:41:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type:Cc:To:From: Subject:Message-ID:References:Mime-Version:In-Reply-To:Date:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=2S8QK1DUpnxCvBG6dnxfgC3sjGb7yD/nYkqrFgFEa7w=; b=QubbIoMnNaqGmaUXPS0GPXmj2d S8sR6i0DWBV4lska2UvOVeg2pjjgXmYy0EkAgjT1Xe48IZW1SRT2uL6eKC7tuHhNAVFaU98RvoNGQ 9RRpCBV6XT53ul6tvm7+PVgyRN+gtRPt6yVCfiRdEoW3d48XCkOELGGcdpTHKAeQpHCJivo9XzGKG 45o5xCh54VrbGOAqMKWwbpuzODnVye+iKbVeLvOs7CvI2EJ3bQkqm6iPQWzPi/a3TpYcb/RRdkjtP bB0SRjvIbKxpedxC+sTyA2RNqVnNK94dr2F9ZaOUdVxsgf7h7Ug6z49+YkCiATGNOR1wfeo/AI0E7 VkqjVrPw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux)) id 1vpZwi-0000000G81u-2gbg; Mon, 09 Feb 2026 22:41:32 +0000 Received: from mail-oa1-x4a.google.com ([2001:4860:4864:20::4a]) by bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux)) id 1vpZwH-0000000G7SM-1nJC for linux-arm-kernel@lists.infradead.org; Mon, 09 Feb 2026 22:41:07 +0000 Received: by mail-oa1-x4a.google.com with SMTP id 586e51a60fabf-40418f60513so16027361fac.2 for ; Mon, 09 Feb 2026 14:41:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770676864; x=1771281664; darn=lists.infradead.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=2S8QK1DUpnxCvBG6dnxfgC3sjGb7yD/nYkqrFgFEa7w=; b=cIlRX+qtIPFLCQpTp74M09OcjicKzofiO2ynWnkNXrfYCkwNwMxzpzVrtvPrC76xFZ YSRmRnnnVuReSGRdNTzRpAFY2mLlthSFUU+JzLqRdSd7FHtVunoSrd3RSS2a5/uJMc5k HMD86dyg4T6QT5agn37ohdTY1B47Ew1ABNwHtZr5mn+f2K4Pib2bsFCOsk08Vxx2bQ80 cPz+icJEd8dAnJmFQvx9W//2OPLU+47gnxqBxrl8FECbmvBXI322YPBPB78aJsPxChzJ jK3tPVFKJBx/wNUa+fKBJ7/frhasLaqJ4WQGQH98h9ftYJ+plwpXVjNx0VGgQrcrvhaB l2KA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770676864; x=1771281664; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=2S8QK1DUpnxCvBG6dnxfgC3sjGb7yD/nYkqrFgFEa7w=; b=JXH0xkGlZOQAdBw1W5EGqpcDSEopkDSju8Tq1pa4cqUE+pPF9k09UdqbTT3j9YGyV0 MK8juLCmFiM0PGyxJhY4B45GYG3joG2Bo0l7jFQt4PEex4iwohej8uFVZzqPlT3QJc5o D6kRhUDDTMUmKK9+YpNPWo9qydWOZAFkmY9rdGy6ScivrQEcLKqmzj6cX32molqNbxpg j9BmlAqxAdAzc7tgVX+3KAkc4grTF1zd7u+9sDYLIIGJMngv/5qlEQzhrHZJFl4tKZ4F jAiXUiEWI5POWCdl/0OO5TXAmKBfXiMdwo0i3EXpJL5aRFI8imBtOPI/e9wunTw41KfY AZtA== X-Forwarded-Encrypted: i=1; AJvYcCUN+j1amcPJvxEFIakJVVDOW10PkuO/9J3O+27h0RWg/wPbpoUFFsAKQ0zv081AEHPheL5moi385rLx9qwF2cYP@lists.infradead.org X-Gm-Message-State: AOJu0YzrIuLdmnwXWEKt7YZcF02jikwz8chn1VlQcr0eM8uZzSBkRRvX s1tySmOneZENJU1RhLEHmmp+qRjMeFxph/bYTZ9JmccXdBjjjIaZkhoptw2eUK7z8ZnNtz++wCh Fa33+hRjCNlvXq9bX/gh/p1/jmQ== X-Received: from oapz39.prod.google.com ([2002:a05:6870:d6a7:b0:409:b837:9227]) (user=coltonlewis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6871:d083:b0:404:3635:c885 with SMTP id 586e51a60fabf-40a96fccba3mr6975342fac.32.1770676864078; Mon, 09 Feb 2026 14:41:04 -0800 (PST) Date: Mon, 9 Feb 2026 22:14:13 +0000 In-Reply-To: <20260209221414.2169465-1-coltonlewis@google.com> Mime-Version: 1.0 References: <20260209221414.2169465-1-coltonlewis@google.com> X-Mailer: git-send-email 2.53.0.rc2.204.g2597b5adb4-goog Message-ID: <20260209221414.2169465-19-coltonlewis@google.com> Subject: [PATCH v6 18/19] KVM: arm64: selftests: Add test case for partitioned PMU From: Colton Lewis To: kvm@vger.kernel.org Cc: Alexandru Elisei , Paolo Bonzini , Jonathan Corbet , Russell King , Catalin Marinas , Will Deacon , Marc Zyngier , Oliver Upton , Mingwei Zhang , Joey Gouly , Suzuki K Poulose , Zenghui Yu , Mark Rutland , Shuah Khan , Ganapatrao Kulkarni , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-perf-users@vger.kernel.org, linux-kselftest@vger.kernel.org, Colton Lewis Content-Type: text/plain; charset="UTF-8" X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260209_144105_540644_C77911C5 X-CRM114-Status: GOOD ( 22.13 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Rerun all tests for a partitioned PMU in vpmu_counter_access. Create an enum specifying whether we are testing the emulated or partitioned PMU and all the test functions are modified to take the implementation as an argument and make the difference in setup appropriately. Signed-off-by: Colton Lewis --- .../selftests/kvm/arm64/vpmu_counter_access.c | 94 ++++++++++++++----- 1 file changed, 73 insertions(+), 21 deletions(-) diff --git a/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c b/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c index ae36325c022fb..9702f1d43b832 100644 --- a/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c +++ b/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c @@ -25,9 +25,20 @@ /* The cycle counter bit position that's common among the PMU registers */ #define ARMV8_PMU_CYCLE_IDX 31 +enum pmu_impl { + EMULATED, + PARTITIONED +}; + +const char *pmu_impl_str[] = { + "Emulated", + "Partitioned" +}; + struct vpmu_vm { struct kvm_vm *vm; struct kvm_vcpu *vcpu; + bool pmu_partitioned; }; static struct vpmu_vm vpmu_vm; @@ -399,7 +410,7 @@ static void guest_code(uint64_t expected_pmcr_n) } /* Create a VM that has one vCPU with PMUv3 configured. */ -static void create_vpmu_vm(void *guest_code) +static void create_vpmu_vm(void *guest_code, enum pmu_impl impl) { struct kvm_vcpu_init init; uint8_t pmuver, ec; @@ -409,6 +420,13 @@ static void create_vpmu_vm(void *guest_code) .attr = KVM_ARM_VCPU_PMU_V3_IRQ, .addr = (uint64_t)&irq, }; + bool partition = (impl == PARTITIONED); + struct kvm_device_attr part_attr = { + .group = KVM_ARM_VCPU_PMU_V3_CTRL, + .attr = KVM_ARM_VCPU_PMU_V3_ENABLE_PARTITION, + .addr = (uint64_t)&partition + }; + int ret; /* The test creates the vpmu_vm multiple times. Ensure a clean state */ memset(&vpmu_vm, 0, sizeof(vpmu_vm)); @@ -436,6 +454,15 @@ static void create_vpmu_vm(void *guest_code) "Unexpected PMUVER (0x%x) on the vCPU with PMUv3", pmuver); vcpu_ioctl(vpmu_vm.vcpu, KVM_SET_DEVICE_ATTR, &irq_attr); + + ret = __vcpu_has_device_attr( + vpmu_vm.vcpu, KVM_ARM_VCPU_PMU_V3_CTRL, KVM_ARM_VCPU_PMU_V3_ENABLE_PARTITION); + if (!ret) { + vcpu_ioctl(vpmu_vm.vcpu, KVM_SET_DEVICE_ATTR, &part_attr); + vpmu_vm.pmu_partitioned = partition; + pr_debug("Set PMU partitioning: %d\n", partition); + } + } static void destroy_vpmu_vm(void) @@ -461,13 +488,14 @@ static void run_vcpu(struct kvm_vcpu *vcpu, uint64_t pmcr_n) } } -static void test_create_vpmu_vm_with_nr_counters(unsigned int nr_counters, bool expect_fail) +static void test_create_vpmu_vm_with_nr_counters( + unsigned int nr_counters, enum pmu_impl impl, bool expect_fail) { struct kvm_vcpu *vcpu; unsigned int prev; int ret; - create_vpmu_vm(guest_code); + create_vpmu_vm(guest_code, impl); vcpu = vpmu_vm.vcpu; prev = get_pmcr_n(vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_PMCR_EL0))); @@ -489,7 +517,7 @@ static void test_create_vpmu_vm_with_nr_counters(unsigned int nr_counters, bool * Create a guest with one vCPU, set the PMCR_EL0.N for the vCPU to @pmcr_n, * and run the test. */ -static void run_access_test(uint64_t pmcr_n) +static void run_access_test(uint64_t pmcr_n, enum pmu_impl impl) { uint64_t sp; struct kvm_vcpu *vcpu; @@ -497,7 +525,7 @@ static void run_access_test(uint64_t pmcr_n) pr_debug("Test with pmcr_n %lu\n", pmcr_n); - test_create_vpmu_vm_with_nr_counters(pmcr_n, false); + test_create_vpmu_vm_with_nr_counters(pmcr_n, impl, false); vcpu = vpmu_vm.vcpu; /* Save the initial sp to restore them later to run the guest again */ @@ -531,14 +559,14 @@ static struct pmreg_sets validity_check_reg_sets[] = { * Create a VM, and check if KVM handles the userspace accesses of * the PMU register sets in @validity_check_reg_sets[] correctly. */ -static void run_pmregs_validity_test(uint64_t pmcr_n) +static void run_pmregs_validity_test(uint64_t pmcr_n, enum pmu_impl impl) { int i; struct kvm_vcpu *vcpu; uint64_t set_reg_id, clr_reg_id, reg_val; uint64_t valid_counters_mask, max_counters_mask; - test_create_vpmu_vm_with_nr_counters(pmcr_n, false); + test_create_vpmu_vm_with_nr_counters(pmcr_n, impl, false); vcpu = vpmu_vm.vcpu; valid_counters_mask = get_counters_mask(pmcr_n); @@ -588,11 +616,11 @@ static void run_pmregs_validity_test(uint64_t pmcr_n) * the vCPU to @pmcr_n, which is larger than the host value. * The attempt should fail as @pmcr_n is too big to set for the vCPU. */ -static void run_error_test(uint64_t pmcr_n) +static void run_error_test(uint64_t pmcr_n, enum pmu_impl impl) { - pr_debug("Error test with pmcr_n %lu (larger than the host)\n", pmcr_n); + pr_debug("Error test with pmcr_n %lu (larger than the host allows)\n", pmcr_n); - test_create_vpmu_vm_with_nr_counters(pmcr_n, true); + test_create_vpmu_vm_with_nr_counters(pmcr_n, impl, true); destroy_vpmu_vm(); } @@ -600,11 +628,11 @@ static void run_error_test(uint64_t pmcr_n) * Return the default number of implemented PMU event counters excluding * the cycle counter (i.e. PMCR_EL0.N value) for the guest. */ -static uint64_t get_pmcr_n_limit(void) +static uint64_t get_pmcr_n_limit(enum pmu_impl impl) { uint64_t pmcr; - create_vpmu_vm(guest_code); + create_vpmu_vm(guest_code, impl); pmcr = vcpu_get_reg(vpmu_vm.vcpu, KVM_ARM64_SYS_REG(SYS_PMCR_EL0)); destroy_vpmu_vm(); return get_pmcr_n(pmcr); @@ -614,7 +642,7 @@ static bool kvm_supports_nr_counters_attr(void) { bool supported; - create_vpmu_vm(NULL); + create_vpmu_vm(NULL, EMULATED); supported = !__vcpu_has_device_attr(vpmu_vm.vcpu, KVM_ARM_VCPU_PMU_V3_CTRL, KVM_ARM_VCPU_PMU_V3_SET_NR_COUNTERS); destroy_vpmu_vm(); @@ -622,22 +650,46 @@ static bool kvm_supports_nr_counters_attr(void) return supported; } -int main(void) +static bool kvm_supports_partition_attr(void) +{ + bool supported; + + create_vpmu_vm(NULL, EMULATED); + supported = !__vcpu_has_device_attr(vpmu_vm.vcpu, KVM_ARM_VCPU_PMU_V3_CTRL, + KVM_ARM_VCPU_PMU_V3_ENABLE_PARTITION); + destroy_vpmu_vm(); + + return supported; +} + +void test_pmu(enum pmu_impl impl) { uint64_t i, pmcr_n; - TEST_REQUIRE(kvm_has_cap(KVM_CAP_ARM_PMU_V3)); - TEST_REQUIRE(kvm_supports_vgic_v3()); - TEST_REQUIRE(kvm_supports_nr_counters_attr()); + pr_info("Testing PMU: Implementation = %s\n", pmu_impl_str[impl]); + + pmcr_n = get_pmcr_n_limit(impl); + pr_debug("PMCR_EL0.N: Limit = %lu\n", pmcr_n); - pmcr_n = get_pmcr_n_limit(); for (i = 0; i <= pmcr_n; i++) { - run_access_test(i); - run_pmregs_validity_test(i); + run_access_test(i, impl); + run_pmregs_validity_test(i, impl); } for (i = pmcr_n + 1; i < ARMV8_PMU_MAX_COUNTERS; i++) - run_error_test(i); + run_error_test(i, impl); +} + +int main(void) +{ + TEST_REQUIRE(kvm_has_cap(KVM_CAP_ARM_PMU_V3)); + TEST_REQUIRE(kvm_supports_vgic_v3()); + TEST_REQUIRE(kvm_supports_nr_counters_attr()); + + test_pmu(EMULATED); + + if (kvm_supports_partition_attr()) + test_pmu(PARTITIONED); return 0; } -- 2.53.0.rc2.204.g2597b5adb4-goog