From patchwork Fri Oct 20 21:40:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Raghavendra Rao Ananta X-Patchwork-Id: 13431228 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 81145C001DF for ; Fri, 20 Oct 2023 21:42:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:Message-ID: References:Mime-Version:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=/CA9pLF4nKgY/vbJ7HuzahfCFevHwn5xZhMvVFvaV6c=; b=0sTgpKlkx1tShdWH2zJsuphT+e ZtwY7TrO8ICHj8EzeFxmx479GTGWPsK3DamLKNBQfikGsnPDx9SeUAcby6+90AEpDmUqDBVfUFBvv lyQ1cktjxa/ZWeld09lq/+2SkrA9z22SIDTyKOA7d6HmUZhwVP/WX40T9mLv6o3oQEgboaI6fIVvW 5D7hQN1J1+b+EUmL22GsbGLWd0OS+oZpwhT33xjPm13esYNcLieJqAkzzdtk/93OHkKixunOgmJY3 CJuoq7aZoMA8blaYXh9/CGkr90lMI2WJwugBP0V41Z4hevPIqYI73wmvMRptvXjUFlVYQJc6/Ee0c ZKXJs7YQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qtxFk-0034id-1g; Fri, 20 Oct 2023 21:41:56 +0000 Received: from mail-yw1-x1149.google.com ([2607:f8b0:4864:20::1149]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qtxF0-0034In-0O for linux-arm-kernel@lists.infradead.org; Fri, 20 Oct 2023 21:41:21 +0000 Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-5a7b9e83b70so10820207b3.0 for ; Fri, 20 Oct 2023 14:41:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1697838068; x=1698442868; 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=6wxdPIo7k8IJbvmMmlNhkE3/rZQV8LNj5jffuDILKrU=; b=OsD5oSNdVZWhN2fN7s8TdAPmb/qvche8XJlsJdNUXDoMmgQzPHk+54lrXz4BgRS3/z VuYPT8LoXlhfWG1wdDMchrg6zK9Ebhzrm980iAOPfSkbBFHl3zZS3NsQESn8EKxDOi+k PzG8M/o27jd6Oy07ojq4/TWzdnPkA72oAnmBPO2Bm9+dg4yqfFq74e6w24Fojys9ub7f zlDc40TTa6iX/j8Jfde608dFmEt1TNg6SqtLVeM2O7/lUsOBkbZPmq22hpJXLq1xoGVB Q+lVRGPcejiuq9bJF5mBTStekEcBZ33wEWmgCVyvM3IH4ArFMMOCgiw11x4WMmYsSy3D VF8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697838068; x=1698442868; 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=6wxdPIo7k8IJbvmMmlNhkE3/rZQV8LNj5jffuDILKrU=; b=qc7c9hDASidDgXB0uVYNLDKauMI6lYGOe1K1y0bjXMtEpvMRsIFec3/J6LbfpNCee3 1GzOPZJxdIEdKGJSXCarvarjn3B6M3E5vVV5PzGJ1SUFxo4oPdzpFXdOxdtWz2RHGeEp iZABa3G3eRgQwYIe0I1GUebkbZ+nuPOBI0eJHQ0vegvEorRXje+fHEIEDr1tL94dn/+m v/Wom0mbHPfxefpERvr1FnCNrAZPdMV2VyuxSlMr1Lv7Ku/Vqkg5pEjcRJhaRRyk8F/2 zctZViXL30hBSp7MQCVCOFi4f+pDcm0AlP8dJrmsO4Nkh8jZthH+LpS47UcLaEctKqNJ TcOQ== X-Gm-Message-State: AOJu0YxBFqHOg2JZZfTGsqK/VsOU8C2XBwnxT1Qt3lsT3f4QCH66ku7C GoIK6sjFoyzG38lZObcbXMx9bwnJJOv5 X-Google-Smtp-Source: AGHT+IEULiFO21+dHH0b0ROgjE4Z7TEImGseE8FLXI46Z1/spsev4ZP3rz8+bMFoLN226OvPc4WV10YeF0cN X-Received: from rananta-linux.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:20a1]) (user=rananta job=sendgmr) by 2002:a81:4852:0:b0:5a4:fd03:2516 with SMTP id v79-20020a814852000000b005a4fd032516mr87740ywa.1.1697838068747; Fri, 20 Oct 2023 14:41:08 -0700 (PDT) Date: Fri, 20 Oct 2023 21:40:52 +0000 In-Reply-To: <20231020214053.2144305-1-rananta@google.com> Mime-Version: 1.0 References: <20231020214053.2144305-1-rananta@google.com> X-Mailer: git-send-email 2.42.0.655.g421f12c284-goog Message-ID: <20231020214053.2144305-13-rananta@google.com> Subject: [PATCH v8 12/13] KVM: selftests: aarch64: vPMU test for validating user accesses From: Raghavendra Rao Ananta To: Oliver Upton , Marc Zyngier Cc: Alexandru Elisei , James Morse , Suzuki K Poulose , Paolo Bonzini , Zenghui Yu , Shaoqin Huang , Jing Zhang , Reiji Watanabe , Colton Lewis , Raghavendra Rao Anata , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231020_144110_158428_494E27D0 X-CRM114-Status: GOOD ( 20.66 ) 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 Add a vPMU test scenario to validate the userspace accesses for the registers PM{C,I}NTEN{SET,CLR} and PMOVS{SET,CLR} to ensure that KVM honors the architectural definitions of these registers for a given PMCR.N. Signed-off-by: Raghavendra Rao Ananta --- .../kvm/aarch64/vpmu_counter_access.c | 87 ++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/aarch64/vpmu_counter_access.c b/tools/testing/selftests/kvm/aarch64/vpmu_counter_access.c index d5143925690db..2b697b144e677 100644 --- a/tools/testing/selftests/kvm/aarch64/vpmu_counter_access.c +++ b/tools/testing/selftests/kvm/aarch64/vpmu_counter_access.c @@ -8,6 +8,8 @@ * counters (PMCR_EL0.N) that userspace sets, if the guest can access * those counters, and if the guest is prevented from accessing any * other counters. + * It also checks if the userspace accesses to the PMU regsisters honor the + * PMCR.N value that's set for the guest. * This test runs only when KVM_CAP_ARM_PMU_V3 is supported on the host. */ #include @@ -20,6 +22,9 @@ /* The max number of the PMU event counters (excluding the cycle counter) */ #define ARMV8_PMU_MAX_GENERAL_COUNTERS (ARMV8_PMU_MAX_COUNTERS - 1) +/* The cycle counter bit position that's common among the PMU registers */ +#define ARMV8_PMU_CYCLE_IDX 31 + struct vpmu_vm { struct kvm_vm *vm; struct kvm_vcpu *vcpu; @@ -28,6 +33,13 @@ struct vpmu_vm { static struct vpmu_vm vpmu_vm; +struct pmreg_sets { + uint64_t set_reg_id; + uint64_t clr_reg_id; +}; + +#define PMREG_SET(set, clr) {.set_reg_id = set, .clr_reg_id = clr} + static uint64_t get_pmcr_n(uint64_t pmcr) { return (pmcr >> ARMV8_PMU_PMCR_N_SHIFT) & ARMV8_PMU_PMCR_N_MASK; @@ -39,6 +51,15 @@ static void set_pmcr_n(uint64_t *pmcr, uint64_t pmcr_n) *pmcr |= (pmcr_n << ARMV8_PMU_PMCR_N_SHIFT); } +static uint64_t get_counters_mask(uint64_t n) +{ + uint64_t mask = BIT(ARMV8_PMU_CYCLE_IDX); + + if (n) + mask |= GENMASK(n - 1, 0); + return mask; +} + /* Read PMEVTCNTR_EL0 through PMXEVCNTR_EL0 */ static inline unsigned long read_sel_evcntr(int sel) { @@ -552,6 +573,68 @@ static void run_access_test(uint64_t pmcr_n) destroy_vpmu_vm(); } +static struct pmreg_sets validity_check_reg_sets[] = { + PMREG_SET(SYS_PMCNTENSET_EL0, SYS_PMCNTENCLR_EL0), + PMREG_SET(SYS_PMINTENSET_EL1, SYS_PMINTENCLR_EL1), + PMREG_SET(SYS_PMOVSSET_EL0, SYS_PMOVSCLR_EL0), +}; + +/* + * 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) +{ + 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_pmcr_n(pmcr_n, false); + vcpu = vpmu_vm.vcpu; + + valid_counters_mask = get_counters_mask(pmcr_n); + max_counters_mask = get_counters_mask(ARMV8_PMU_MAX_COUNTERS); + + for (i = 0; i < ARRAY_SIZE(validity_check_reg_sets); i++) { + set_reg_id = validity_check_reg_sets[i].set_reg_id; + clr_reg_id = validity_check_reg_sets[i].clr_reg_id; + + /* + * Test if the 'set' and 'clr' variants of the registers + * are initialized based on the number of valid counters. + */ + vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(set_reg_id), ®_val); + TEST_ASSERT((reg_val & (~valid_counters_mask)) == 0, + "Initial read of set_reg: 0x%llx has unimplemented counters enabled: 0x%lx\n", + KVM_ARM64_SYS_REG(set_reg_id), reg_val); + + vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(clr_reg_id), ®_val); + TEST_ASSERT((reg_val & (~valid_counters_mask)) == 0, + "Initial read of clr_reg: 0x%llx has unimplemented counters enabled: 0x%lx\n", + KVM_ARM64_SYS_REG(clr_reg_id), reg_val); + + /* + * Using the 'set' variant, force-set the register to the + * max number of possible counters and test if KVM discards + * the bits for unimplemented counters as it should. + */ + vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(set_reg_id), max_counters_mask); + + vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(set_reg_id), ®_val); + TEST_ASSERT((reg_val & (~valid_counters_mask)) == 0, + "Read of set_reg: 0x%llx has unimplemented counters enabled: 0x%lx\n", + KVM_ARM64_SYS_REG(set_reg_id), reg_val); + + vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(clr_reg_id), ®_val); + TEST_ASSERT((reg_val & (~valid_counters_mask)) == 0, + "Read of clr_reg: 0x%llx has unimplemented counters enabled: 0x%lx\n", + KVM_ARM64_SYS_REG(clr_reg_id), reg_val); + } + + destroy_vpmu_vm(); +} + /* * Create a guest with one vCPU, and attempt to set the PMCR_EL0.N for * the vCPU to @pmcr_n, which is larger than the host value. @@ -586,8 +669,10 @@ int main(void) TEST_REQUIRE(kvm_has_cap(KVM_CAP_ARM_PMU_V3)); pmcr_n = get_pmcr_n_limit(); - for (i = 0; i <= pmcr_n; i++) + for (i = 0; i <= pmcr_n; i++) { run_access_test(i); + run_pmregs_validity_test(i); + } for (i = pmcr_n + 1; i < ARMV8_PMU_MAX_COUNTERS; i++) run_error_test(i);