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 C6D9EC4332F for ; Fri, 30 Dec 2022 04:06:58 +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=eT/qRpyLPMWgEbhyK+E5hLW4Od8aa/9IyEP29ikt5MQ=; b=0zxCEsw0omGznm8Kd+Xzcq7Utd bRmk38+01BSaLGcQNyvb1rH41Z5/fjP/oAM1oOmHAnEubO7/QcZO/TETaQ5lpbFRDtEOaGsbOhxGk tLxQGpOCNLgP9fEAR8Mp0EDeIhf+oUGGyrozXS97PsExZulYkl3uTG+5oZTqT69u7vx43wWpLuQ66 ZLboXfve+DrYkctHiMamgm9XARypYK3R3ukB+qA8tSCoXU8e3BgGHdip1Q4epDaob5lZilPb1XoKX E5DS0AMJZ/HkZEb+I+1xWAOrSUz5eb0DL7mGQ8VIJaLs8fiseso/57doyIF0fB/kGVBmYoK4E3fGP raU+/3sA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1pB6eK-005GK1-M6; Fri, 30 Dec 2022 04:05:41 +0000 Received: from mail-pg1-x54a.google.com ([2607:f8b0:4864:20::54a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1pB6aN-005ESW-JQ for linux-arm-kernel@lists.infradead.org; Fri, 30 Dec 2022 04:01:38 +0000 Received: by mail-pg1-x54a.google.com with SMTP id 23-20020a630017000000b0048d84f2cbbeso9744026pga.9 for ; Thu, 29 Dec 2022 20:01:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=TF6mtXCSZiwAgtARbQ5xLSrPWgFz4SHEJ+nKUXLPeJ8=; b=sU5Q2FZB1j3zoL2IyByPHp4XXlV347Lgzl2S/dL8FIDS6Q2Gk5gLVaYY0mql2Dp6Ou KisxGHgGXlWLqy0KrCm2jzMx6MW2DUdsSKYrvTMRQzTkIP9n++TZxJNW5O7MKxr4/+u1 y5AtwhDj5bQkpOMw4Rt3TEsg9R3+Nx3N5SwHtOOOHaLq+xbJBQ7qymHu5n5oPGJsFhZD JZltvpqhshV0s0u4yV8AiKaVmx6dZd0jT75t4Jl9ACLOcRVNz/c6KlNj8gwquqeyYcTq 5YaMYUnKjoDopeUfn2jtR5j+bKqWjhgC2qrimfQn1WGUUn8dqPl3crbncgC3P1Un3vGK fC2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=TF6mtXCSZiwAgtARbQ5xLSrPWgFz4SHEJ+nKUXLPeJ8=; b=LmERx7B6FAoxighCjST4PsLGeaEF0lzQpavz6V3BvTs3jsQjWKyMAxtj8ZDMzs8ouI nQqKWL94v/6yBVsq0YdLavkyRs7iLs4ij/G85HGpIpM7mRN4eU9mQxtrK9d0I1PuwRs5 HWwAF+znnNL0iLUcQxaEqt3fEXuqtQw9/kKVIXoyC4UrTDF6iAE9FVWD/OJ+j6GPgg3K WOtBxCDwfAUKdGG2gjEErQz+qC7OgYxRkoRoNJs4TNYmSUg7qjhIREr9DzW9ahEoHJiX RNxBSCRE15eonk9SxhXHuQu5AJ6Z/HKn2SU4laTEIQAqkfMfYs9LNHg18JCdKRTi53dD Wfhw== X-Gm-Message-State: AFqh2kqpCBy52g3YSAbAoUY9ZYmMd0q8wXCPnV3jwiBFetlNwKpawMlr +6F5Co5SQRhTufZwQIuazE9XrgL3xgs= X-Google-Smtp-Source: AMrXdXu5U/lKBFXfJCQ+vyRfT4vdWYzYWTLMDKD8zziBxUMakTgcKuR9JnE7SThBpiyZZGBEQxkoI0dzeRs= X-Received: from reijiw-west4.c.googlers.com ([fda3:e722:ac3:cc00:20:ed76:c0a8:aa1]) (user=reijiw job=sendgmr) by 2002:a17:90b:4d83:b0:220:1f03:129b with SMTP id oj3-20020a17090b4d8300b002201f03129bmr181538pjb.0.1672372888381; Thu, 29 Dec 2022 20:01:28 -0800 (PST) Date: Thu, 29 Dec 2022 19:59:28 -0800 In-Reply-To: <20221230035928.3423990-1-reijiw@google.com> Mime-Version: 1.0 References: <20221230035928.3423990-1-reijiw@google.com> X-Mailer: git-send-email 2.39.0.314.g84b9a713c41-goog Message-ID: <20221230035928.3423990-8-reijiw@google.com> Subject: [PATCH 7/7] KVM: selftests: aarch64: vPMU register test for unimplemented counters From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu, kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20221229_200136_667401_629E9C25 X-CRM114-Status: GOOD ( 23.11 ) 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: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add a new test case to the vpmu_counter_access test to check if PMU registers or their bits for unimplemented counters are not accessible or are RAZ, as expected. Signed-off-by: Reiji Watanabe --- .../kvm/aarch64/vpmu_counter_access.c | 103 +++++++++++++++++- .../selftests/kvm/include/aarch64/processor.h | 1 + 2 files changed, 98 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/kvm/aarch64/vpmu_counter_access.c b/tools/testing/selftests/kvm/aarch64/vpmu_counter_access.c index 5b9d837f903a..af1abdfa2be2 100644 --- a/tools/testing/selftests/kvm/aarch64/vpmu_counter_access.c +++ b/tools/testing/selftests/kvm/aarch64/vpmu_counter_access.c @@ -5,8 +5,8 @@ * Copyright (c) 2022 Google LLC. * * This test checks if the guest can see the same number of the PMU event - * counters (PMCR_EL1.N) that userspace sets, and if the guest can access - * those counters. + * counters (PMCR_EL1.N) that userspace sets, if the guest can access + * those counters, and if the guest cannot access any other counters. * This test runs only when KVM_CAP_ARM_PMU_V3 is supported on the host. */ #include @@ -179,6 +179,51 @@ struct pmc_accessor pmc_accessors[] = { { read_sel_evcntr, write_pmevcntrn, read_sel_evtyper, write_pmevtypern }, }; +#define INVALID_EC (-1ul) +uint64_t expected_ec = INVALID_EC; +uint64_t op_end_addr; + +static void guest_sync_handler(struct ex_regs *regs) +{ + uint64_t esr, ec; + + esr = read_sysreg(esr_el1); + ec = (esr >> ESR_EC_SHIFT) & ESR_EC_MASK; + GUEST_ASSERT_4(op_end_addr && (expected_ec == ec), + regs->pc, esr, ec, expected_ec); + + /* Will go back to op_end_addr after the handler exits */ + regs->pc = op_end_addr; + + /* + * Clear op_end_addr, and setting expected_ec to INVALID_EC + * as a sign that an exception has occurred. + */ + op_end_addr = 0; + expected_ec = INVALID_EC; +} + +/* + * Run the given operation that should trigger an exception with the + * given exception class. The exception handler (guest_sync_handler) + * will reset op_end_addr to 0, and expected_ec to INVALID_EC, and + * will come back to the instruction at the @done_label. + * The @done_label must be a unique label in this test program. + */ +#define TEST_EXCEPTION(ec, ops, done_label) \ +{ \ + extern int done_label; \ + \ + WRITE_ONCE(op_end_addr, (uint64_t)&done_label); \ + GUEST_ASSERT(ec != INVALID_EC); \ + WRITE_ONCE(expected_ec, ec); \ + dsb(ish); \ + ops; \ + asm volatile(#done_label":"); \ + GUEST_ASSERT(!op_end_addr); \ + GUEST_ASSERT(expected_ec == INVALID_EC); \ +} + static void pmu_disable_reset(void) { uint64_t pmcr = read_sysreg(pmcr_el0); @@ -352,16 +397,38 @@ static void test_access_pmc_regs(struct pmc_accessor *acc, int pmc_idx) pmc_idx, acc, read_data, read_data_prev); } +/* + * Tests for reading/writing registers for the unimplemented event counter + * specified by @pmc_idx (>= PMCR_EL1.N). + */ +static void test_access_invalid_pmc_regs(struct pmc_accessor *acc, int pmc_idx) +{ + /* + * Reading/writing the event count/type registers should cause + * an UNDEFINED exception. + */ + TEST_EXCEPTION(ESR_EC_UNKNOWN, acc->read_cntr(pmc_idx), inv_rd_cntr); + TEST_EXCEPTION(ESR_EC_UNKNOWN, acc->write_cntr(pmc_idx, 0), inv_wr_cntr); + TEST_EXCEPTION(ESR_EC_UNKNOWN, acc->read_typer(pmc_idx), inv_rd_typer); + TEST_EXCEPTION(ESR_EC_UNKNOWN, acc->write_typer(pmc_idx, 0), inv_wr_typer); + /* + * The bit corresponding to the (unimplemented) counter in + * {PMCNTEN,PMOVS}{SET,CLR}_EL1 registers should be RAZ. + */ + test_bitmap_pmu_regs(pmc_idx, 1); + test_bitmap_pmu_regs(pmc_idx, 0); +} + /* * The guest is configured with PMUv3 with @expected_pmcr_n number of * event counters. * Check if @expected_pmcr_n is consistent with PMCR_EL0.N, and - * if reading/writing PMU registers for implemented counters can work - * as expected. + * if reading/writing PMU registers for implemented or unimplemented + * counters can work as expected. */ static void guest_code(uint64_t expected_pmcr_n) { - uint64_t pmcr, pmcr_n; + uint64_t pmcr, pmcr_n, unimp_mask; int i, pmc; GUEST_ASSERT(expected_pmcr_n <= ARMV8_PMU_MAX_GENERAL_COUNTERS); @@ -372,6 +439,14 @@ static void guest_code(uint64_t expected_pmcr_n) /* Make sure that PMCR_EL0.N indicates the value userspace set */ GUEST_ASSERT_2(pmcr_n == expected_pmcr_n, pmcr_n, expected_pmcr_n); + /* + * Make sure that (RAZ) bits corresponding to unimplemented event + * counters in {PMCNTEN,PMOVS}{SET,CLR}_EL1 registers are reset to zero. + * (NOTE: bits for implemented event counters are reset to UNKNOWN) + */ + unimp_mask = GENMASK_ULL(ARMV8_PMU_MAX_GENERAL_COUNTERS - 1, pmcr_n); + check_bitmap_pmu_regs(unimp_mask, false); + /* * Tests for reading/writing PMU registers for implemented counters. * Use each combination of PMEVT{CNTR,TYPER}_EL0 accessor functions. @@ -381,6 +456,14 @@ static void guest_code(uint64_t expected_pmcr_n) test_access_pmc_regs(&pmc_accessors[i], pmc); } + /* + * Tests for reading/writing PMU registers for unimplemented counters. + * Use each combination of PMEVT{CNTR,TYPER}_EL0 accessor functions. + */ + for (i = 0; i < ARRAY_SIZE(pmc_accessors); i++) { + for (pmc = pmcr_n; pmc < ARMV8_PMU_MAX_GENERAL_COUNTERS; pmc++) + test_access_invalid_pmc_regs(&pmc_accessors[i], pmc); + } GUEST_DONE(); } @@ -394,7 +477,7 @@ static struct kvm_vm *create_vpmu_vm(void *guest_code, struct kvm_vcpu **vcpup, struct kvm_vm *vm; struct kvm_vcpu *vcpu; struct kvm_vcpu_init init; - uint8_t pmuver; + uint8_t pmuver, ec; uint64_t dfr0, irq = 23; struct kvm_device_attr irq_attr = { .group = KVM_ARM_VCPU_PMU_V3_CTRL, @@ -408,11 +491,18 @@ static struct kvm_vm *create_vpmu_vm(void *guest_code, struct kvm_vcpu **vcpup, vm = vm_create(1); ucall_init(vm, NULL); + vm_init_descriptor_tables(vm); + /* Catch exceptions for easier debugging */ + for (ec = 0; ec < ESR_EC_NUM; ec++) { + vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT, ec, + guest_sync_handler); + } /* Create vCPU with PMUv3 */ vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &init); init.features[0] |= (1 << KVM_ARM_VCPU_PMU_V3); vcpu = aarch64_vcpu_add(vm, 0, &init, guest_code); + vcpu_init_descriptor_tables(vcpu); *gic_fd = vgic_v3_setup(vm, 1, 64, GICD_BASE_GPA, GICR_BASE_GPA); /* Make sure that PMUv3 support is indicated in the ID register */ @@ -481,6 +571,7 @@ static void run_test(uint64_t pmcr_n) vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &init); init.features[0] |= (1 << KVM_ARM_VCPU_PMU_V3); aarch64_vcpu_setup(vcpu, &init); + vcpu_init_descriptor_tables(vcpu); vcpu_set_reg(vcpu, ARM64_CORE_REG(sp_el1), sp); vcpu_set_reg(vcpu, ARM64_CORE_REG(regs.pc), (uint64_t)guest_code); diff --git a/tools/testing/selftests/kvm/include/aarch64/processor.h b/tools/testing/selftests/kvm/include/aarch64/processor.h index 5f977528e09c..52d87809356c 100644 --- a/tools/testing/selftests/kvm/include/aarch64/processor.h +++ b/tools/testing/selftests/kvm/include/aarch64/processor.h @@ -104,6 +104,7 @@ enum { #define ESR_EC_SHIFT 26 #define ESR_EC_MASK (ESR_EC_NUM - 1) +#define ESR_EC_UNKNOWN 0x0 #define ESR_EC_SVC64 0x15 #define ESR_EC_IABT 0x21 #define ESR_EC_DABT 0x25 -- 2.39.0.314.g84b9a713c41-goog _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel