From nobody Sat Oct 25 13:17:02 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1521233582629391.18692840171775; Fri, 16 Mar 2018 13:53:02 -0700 (PDT) Received: from localhost ([::1]:59577 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ewwLR-0006EZ-RE for importer@patchew.org; Fri, 16 Mar 2018 16:52:57 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44345) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eww1Z-00060c-MP for qemu-devel@nongnu.org; Fri, 16 Mar 2018 16:32:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eww1X-0003Um-QY for qemu-devel@nongnu.org; Fri, 16 Mar 2018 16:32:25 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:56158) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eww1R-0003Mj-QZ; Fri, 16 Mar 2018 16:32:18 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 96A066055D; Fri, 16 Mar 2018 20:32:14 +0000 (UTC) Received: from mossypile.qualcomm.com (global_nat1_iad_fw.qualcomm.com [129.46.232.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: alindsay@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 1A91160FB1; Fri, 16 Mar 2018 20:32:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1521232336; bh=0ZHlk6YlDd/LOItzoFxI6o1v1+n4NV0kN0IjqDQ1YF0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JB1a21fanLbT/fFUHntyyd3gmCDv8R5KDzcRi71OKMDHEtNEkTKkfMzgkLQJQo3p7 XDNwtpDNy1mzENb+wXy8iIW1iT0avYiZLF+soQh5O4g/dJCe1E3M/o+rW+2x3oSFkJ y4tSzU9RTTrjfyKUKUw62XvcpODOdEexw8nqhZeM= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1521232332; bh=0ZHlk6YlDd/LOItzoFxI6o1v1+n4NV0kN0IjqDQ1YF0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=e9WjWsJTxFa+u/lI45Hvxv6Z9A0sRxtO1oVHPfBaGq5wMI1bQnhPGZhJgArk1vPc+ CiyEoUxr3yzGbCD14o5knJ92TuXMcnBFb6URVeWzvxkqkip8I0L99plJS8s/c8CNuO XRUC+8on8yuajFYocd+xg6rkimQQYxnAvg1AFO3k= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 1A91160FB1 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=alindsay@codeaurora.org From: Aaron Lindsay To: qemu-arm@nongnu.org, Peter Maydell , Alistair Francis , Wei Huang , Peter Crosthwaite Date: Fri, 16 Mar 2018 16:31:10 -0400 Message-Id: <1521232280-13089-13-git-send-email-alindsay@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1521232280-13089-1-git-send-email-alindsay@codeaurora.org> References: <1521232280-13089-1-git-send-email-alindsay@codeaurora.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 198.145.29.96 Subject: [Qemu-devel] [PATCH v3 12/22] target/arm: Filter cycle counter based on PMCCFILTR_EL0 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Spradling , qemu-devel@nongnu.org, Digant Desai Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The pmu_counter_filtered and pmu_op_start/finish functions are generic (as opposed to PMCCNTR-specific) to allow for the implementation of other events. Signed-off-by: Aaron Lindsay --- target/arm/cpu.c | 3 ++ target/arm/cpu.h | 37 +++++++++++++++++++---- target/arm/helper.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++= +--- 3 files changed, 116 insertions(+), 11 deletions(-) diff --git a/target/arm/cpu.c b/target/arm/cpu.c index a2cb21e..b0d032c 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -887,6 +887,9 @@ static void arm_cpu_realizefn(DeviceState *dev, Error *= *errp) if (!cpu->has_pmu) { unset_feature(env, ARM_FEATURE_PMU); cpu->id_aa64dfr0 &=3D ~0xf00; + } else { + arm_register_pre_el_change_hook(cpu, &pmu_pre_el_change, 0); + arm_register_el_change_hook(cpu, &pmu_post_el_change, 0); } =20 if (!arm_feature(env, ARM_FEATURE_EL2)) { diff --git a/target/arm/cpu.h b/target/arm/cpu.h index b0ef727..9c3b5ef 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -458,6 +458,11 @@ typedef struct CPUARMState { * was reset. Otherwise it stores the counter value */ uint64_t c15_ccnt; + /* ccnt_cached_cycles is used to hold the last cycle count when + * c15_ccnt holds the guest-visible count instead of the delta dur= ing + * PMU operations which require this. + */ + uint64_t ccnt_cached_cycles; uint64_t pmccfiltr_el0; /* Performance Monitor Filter Register */ uint64_t vpidr_el2; /* Virtualization Processor ID Register */ uint64_t vmpidr_el2; /* Virtualization Multiprocessor ID Register = */ @@ -896,15 +901,35 @@ int cpu_arm_signal_handler(int host_signum, void *pin= fo, void *puc); =20 /** - * pmccntr_sync + * pmccntr_op_start/finish * @env: CPUARMState * - * Synchronises the counter in the PMCCNTR. This must always be called twi= ce, - * once before any action that might affect the timer and again afterwards. - * The function is used to swap the state of the register if required. - * This only happens when not in user mode (!CONFIG_USER_ONLY) + * Convert the counter in the PMCCNTR between its delta form (the typical = mode + * when it's enabled) and the guest-visible value. These two calls must al= ways + * surround any action which might affect the counter, and the return value + * from pmccntr_op_start must be supplied as the second argument to + * pmccntr_op_finish. + */ +uint64_t pmccntr_op_start(CPUARMState *env); +void pmccntr_op_finish(CPUARMState *env, uint64_t prev_cycles); + +/** + * pmu_op_start/finish + * @env: CPUARMState + * + * Convert all PMU counters between their delta form (the typical mode when + * they are enabled) and the guest-visible values. These two calls must + * surround any action which might affect the counters, and the return val= ue + * from pmu_op_start must be supplied as the second argument to pmu_op_fin= ish. + */ +uint64_t pmu_op_start(CPUARMState *env); +void pmu_op_finish(CPUARMState *env, uint64_t prev_cycles); + +/** + * Functions to register as EL change hooks for PMU mode filtering */ -void pmccntr_sync(CPUARMState *env); +void pmu_pre_el_change(ARMCPU *cpu, void *ignored); +void pmu_post_el_change(ARMCPU *cpu, void *ignored); =20 /* SCTLR bit meanings. Several bits have been reused in newer * versions of the architecture; in that case we define constants diff --git a/target/arm/helper.c b/target/arm/helper.c index 0102357..95b09d6 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -908,6 +908,15 @@ static const ARMCPRegInfo v6_cp_reginfo[] =3D { #define PMCRC 0x4 #define PMCRE 0x1 =20 +#define PMXEVTYPER_P 0x80000000 +#define PMXEVTYPER_U 0x40000000 +#define PMXEVTYPER_NSK 0x20000000 +#define PMXEVTYPER_NSU 0x10000000 +#define PMXEVTYPER_NSH 0x08000000 +#define PMXEVTYPER_M 0x04000000 +#define PMXEVTYPER_MT 0x02000000 +#define PMXEVTYPER_EVTCOUNT 0x000003ff + #define PMU_NUM_COUNTERS(env) ((env->cp15.c9_pmcr & PMCRN_MASK) >> PMCRN_S= HIFT) /* Bits allowed to be set/cleared for PMCNTEN* and PMINTEN* */ #define PMU_COUNTER_MASK(env) ((1 << 31) | ((1 << PMU_NUM_COUNTERS(env)) -= 1)) @@ -998,7 +1007,7 @@ static CPAccessResult pmreg_access_ccntr(CPUARMState *= env, =20 static inline bool arm_ccnt_enabled(CPUARMState *env) { - /* This does not support checking PMCCFILTR_EL0 register */ + /* Does not check PMCCFILTR_EL0, which is handled by pmu_counter_filte= red */ =20 if (!(env->cp15.c9_pmcr & PMCRE) || !(env->cp15.c9_pmcnten & (1 << 31)= )) { return false; @@ -1006,6 +1015,44 @@ static inline bool arm_ccnt_enabled(CPUARMState *env) =20 return true; } + +/* Returns true if the counter corresponding to the passed-in pmevtyper or + * pmccfiltr value is filtered using the current state */ +static inline bool pmu_counter_filtered(CPUARMState *env, uint64_t pmxevty= per) +{ + bool secure =3D arm_is_secure(env); + int el =3D arm_current_el(env); + + bool P =3D pmxevtyper & PMXEVTYPER_P; + bool U =3D pmxevtyper & PMXEVTYPER_U; + bool NSK =3D pmxevtyper & PMXEVTYPER_NSK; + bool NSU =3D pmxevtyper & PMXEVTYPER_NSU; + bool NSH =3D pmxevtyper & PMXEVTYPER_NSH; + bool M =3D pmxevtyper & PMXEVTYPER_M; + + if (el =3D=3D 1 && P) { + return true; + } else if (el =3D=3D 0 && U) { + return true; + } + + if (arm_feature(env, ARM_FEATURE_EL3)) { + if (el =3D=3D 1 && !secure && NSK !=3D P) { + return true; + } else if (el =3D=3D 0 && !secure && NSU !=3D U) { + return true; + } else if (el =3D=3D 3 && secure && M !=3D P) { + return true; + } + } + + if (arm_feature(env, ARM_FEATURE_EL2) && el =3D=3D 2 && !secure && !NS= H) { + return true; + } + + return false; +} + /* * Ensure c15_ccnt is the guest-visible count so that operations such as * enabling/disabling the counter or filtering, modifying the count itself, @@ -1023,7 +1070,8 @@ uint64_t pmccntr_op_start(CPUARMState *env) ARM_CPU_FREQ, NANOSECONDS_PER_SECOND); #endif =20 - if (arm_ccnt_enabled(env)) { + if (arm_ccnt_enabled(env) && + !pmu_counter_filtered(env, env->cp15.pmccfiltr_el0)) { =20 uint64_t eff_cycles =3D cycles; if (env->cp15.c9_pmcr & PMCRD) { @@ -1043,7 +1091,8 @@ uint64_t pmccntr_op_start(CPUARMState *env) */ void pmccntr_op_finish(CPUARMState *env, uint64_t prev_cycles) { - if (arm_ccnt_enabled(env)) { + if (arm_ccnt_enabled(env) && + !pmu_counter_filtered(env, env->cp15.pmccfiltr_el0)) { =20 if (env->cp15.c9_pmcr & PMCRD) { /* Increment once every 64 processor clock cycles */ @@ -1054,10 +1103,30 @@ void pmccntr_op_finish(CPUARMState *env, uint64_t p= rev_cycles) } } =20 +uint64_t pmu_op_start(CPUARMState *env) +{ + return pmccntr_op_start(env); +} + +void pmu_op_finish(CPUARMState *env, uint64_t prev_cycles) +{ + pmccntr_op_finish(env, prev_cycles); +} + +void pmu_pre_el_change(ARMCPU *cpu, void *ignored) +{ + cpu->env.cp15.ccnt_cached_cycles =3D pmu_op_start(&cpu->env); +} + +void pmu_post_el_change(ARMCPU *cpu, void *ignored) +{ + pmu_op_finish(&cpu->env, cpu->env.cp15.ccnt_cached_cycles); +} + static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - uint64_t saved_cycles =3D pmccntr_op_start(env); + uint64_t saved_cycles =3D pmu_op_start(env); =20 if (value & PMCRC) { /* The counter has been reset */ @@ -1068,7 +1137,7 @@ static void pmcr_write(CPUARMState *env, const ARMCPR= egInfo *ri, env->cp15.c9_pmcr &=3D ~0x39; env->cp15.c9_pmcr |=3D (value & 0x39); =20 - pmccntr_op_finish(env, saved_cycles); + pmu_op_finish(env, saved_cycles); } =20 static uint64_t pmccntr_read(CPUARMState *env, const ARMCPRegInfo *ri) @@ -1117,6 +1186,14 @@ void pmccntr_op_finish(CPUARMState *env, uint64_t pr= ev_cycles) { } =20 +uint64_t pmu_op_start(CPUARMState *env) +{ +} + +void pmu_op_finish(CPUARMState *env, uint64_t prev_cycles) +{ +} + #endif =20 static void pmccfiltr_write(CPUARMState *env, const ARMCPRegInfo *ri, --=20 Qualcomm Datacenter Technologies as an affiliate of Qualcomm Technologies, = Inc. Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.