From patchwork Thu Dec 8 17:05:48 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jones X-Patchwork-Id: 9466719 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 88E1960459 for ; Thu, 8 Dec 2016 17:06:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 742D0285E2 for ; Thu, 8 Dec 2016 17:06:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 671E5285E3; Thu, 8 Dec 2016 17:06:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0295E285B7 for ; Thu, 8 Dec 2016 17:05:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753702AbcLHRFz (ORCPT ); Thu, 8 Dec 2016 12:05:55 -0500 Received: from mx1.redhat.com ([209.132.183.28]:54316 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753059AbcLHRFy (ORCPT ); Thu, 8 Dec 2016 12:05:54 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 945BB80F8D; Thu, 8 Dec 2016 17:05:54 +0000 (UTC) Received: from kamzik.brq.redhat.com (kamzik.brq.redhat.com [10.34.1.143]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id uB8H5p0K027860; Thu, 8 Dec 2016 12:05:53 -0500 From: Andrew Jones To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: wei@redhat.com, cov@codeaurora.org, andre.przywara@arm.com Subject: [PATCH kvm-unit-tests v2 1/2] arm/pmu: fix probe on AArch64 Date: Thu, 8 Dec 2016 18:05:48 +0100 Message-Id: <20161208170549.8793-2-drjones@redhat.com> In-Reply-To: <20161208170549.8793-1-drjones@redhat.com> References: <20161208170549.8793-1-drjones@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Thu, 08 Dec 2016 17:05:54 +0000 (UTC) Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The spec for ID_DFR0_EL1 says "In an AArch64-only implementation, this register is UNKNOWN." Indeed ThunderX just returns zero when that register is read. This means we can't rely on a non-zero value to determine if we can test the PMU. For AArch64 we need to read ID_AA64DFR0_EL1. This patch has the side effect of no longer running PMU tests on TCG for AArch64. That's actually another fix, though, as TCG chooses not to implement a PMU for AArch64 at this time. The only way it worked before was probing the wrong register and proceeding even though the version was 2, which is not a valid version for AArch64. When TCG eventually implements a PMU things should "just work". Signed-off-by: Andrew Jones Reviewed-by: Wei Huang . I also tested on real machine --- arm/pmu.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/arm/pmu.c b/arm/pmu.c index a39dae43c99e..c4d5c97dbf87 100644 --- a/arm/pmu.c +++ b/arm/pmu.c @@ -28,15 +28,15 @@ #define PMU_PMCR_IMP_SHIFT 24 #define PMU_PMCR_IMP_MASK 0xff -#define ID_DFR0_PERFMON_SHIFT 24 -#define ID_DFR0_PERFMON_MASK 0xf - -#define PMU_CYCLE_IDX 31 +#define PMU_CYCLE_IDX 31 #define NR_SAMPLES 10 static unsigned int pmu_version; #if defined(__arm__) +#define ID_DFR0_PERFMON_SHIFT 24 +#define ID_DFR0_PERFMON_MASK 0xf + #define PMCR __ACCESS_CP15(c9, 0, c12, 0) #define ID_DFR0 __ACCESS_CP15(c0, 0, c1, 2) #define PMSELR __ACCESS_CP15(c9, 0, c12, 5) @@ -50,6 +50,11 @@ static inline uint32_t get_pmcr(void) { return read_sysreg(PMCR); } static inline void set_pmcr(uint32_t v) { write_sysreg(v, PMCR); } static inline void set_pmcntenset(uint32_t v) { write_sysreg(v, PMCNTENSET); } +static inline uint8_t get_pmu_version(void) +{ + return (get_id_dfr0() >> ID_DFR0_PERFMON_SHIFT) & ID_DFR0_PERFMON_MASK; +} + static inline uint64_t get_pmccntr(void) { if (pmu_version == 0x3) @@ -95,7 +100,10 @@ static inline void precise_instrs_loop(int loop, uint32_t pmcr) : "cc"); } #elif defined(__aarch64__) -static inline uint32_t get_id_dfr0(void) { return read_sysreg(id_dfr0_el1); } +#define ID_AA64DFR0_PERFMON_SHIFT 8 +#define ID_AA64DFR0_PERFMON_MASK 0xf + +static inline uint32_t get_id_aa64dfr0(void) { return read_sysreg(id_aa64dfr0_el1); } static inline uint32_t get_pmcr(void) { return read_sysreg(pmcr_el0); } static inline void set_pmcr(uint32_t v) { write_sysreg(v, pmcr_el0); } static inline uint64_t get_pmccntr(void) { return read_sysreg(pmccntr_el0); } @@ -103,6 +111,12 @@ static inline void set_pmccntr(uint64_t v) { write_sysreg(v, pmccntr_el0); } static inline void set_pmcntenset(uint32_t v) { write_sysreg(v, pmcntenset_el0); } static inline void set_pmccfiltr(uint32_t v) { write_sysreg(v, pmccfiltr_el0); } +static inline uint8_t get_pmu_version(void) +{ + uint8_t ver = (get_id_aa64dfr0() >> ID_AA64DFR0_PERFMON_SHIFT) & ID_AA64DFR0_PERFMON_MASK; + return ver == 1 ? 3 : ver; +} + /* * Extra instructions inserted by the compiler would be difficult to compensate * for, so hand assemble everything between, and including, the PMCR accesses @@ -256,16 +270,9 @@ static bool check_cpi(int cpi) /* Return FALSE if no PMU found, otherwise return TRUE */ bool pmu_probe(void) { - uint32_t dfr0; - - /* probe pmu version */ - dfr0 = get_id_dfr0(); - pmu_version = (dfr0 >> ID_DFR0_PERFMON_SHIFT) & ID_DFR0_PERFMON_MASK; - - if (pmu_version) - report_info("PMU version: %d", pmu_version); - - return pmu_version; + pmu_version = get_pmu_version(); + report_info("PMU version: %d", pmu_version); + return pmu_version != 0 && pmu_version != 0xf; } int main(int argc, char *argv[])