From nobody Mon Feb 9 20:30:30 2026 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 152969972963631.06961482266172; Fri, 22 Jun 2018 13:35:29 -0700 (PDT) Received: from localhost ([::1]:36076 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fWSmG-0003nA-OR for importer@patchew.org; Fri, 22 Jun 2018 16:35:28 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54259) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fWSjb-00026f-82 for qemu-devel@nongnu.org; Fri, 22 Jun 2018 16:32:44 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fWSjZ-0005QJ-MJ for qemu-devel@nongnu.org; Fri, 22 Jun 2018 16:32:43 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:45100) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fWSjV-0005Ou-0V; Fri, 22 Jun 2018 16:32:37 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 1B31060B13; Fri, 22 Jun 2018 20:32:36 +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 A16F76063F; Fri, 22 Jun 2018 20:32:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1529699556; bh=InCWDuIij7WtZxZkLbiWmWFvCgJSfZZgl3ZVKcb3qpg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JH5uLBgxPclpcqCdK+u869EGUZOlDNtOUGlbVdiTZptDf3Wa6XcrWQLX4kq8Pc6Iv deodsSPbs7DObckvCT0aToq4/fruWN/et68/8LjvQeQTG7qimdpYxRKMITuyFIVux5 PYRpQjfSu8AW0wbNRhsz2YF5vDvyJGAxHm7CpnqE= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1529699555; bh=InCWDuIij7WtZxZkLbiWmWFvCgJSfZZgl3ZVKcb3qpg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NqBY7AZf/vaRlo4E6mGxdz3vcrtwrb3FgE8XctZGxfKVNHbCA02NKJEspVAiNALMz oiGK7GtjSVWyRlXrMolTXYl7DVRO9RfRUkL+Y7adV3gnqiqbi3bTGcEaAfUdR3kpr4 e4ssbzpIAYa5PwKwWK/2SsIDyMoY3ltA9MbQUdgE= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org A16F76063F 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, 22 Jun 2018 16:32:15 -0400 Message-Id: <1529699547-17044-2-git-send-email-alindsay@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1529699547-17044-1-git-send-email-alindsay@codeaurora.org> References: <1529699547-17044-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 v5 01/13] target/arm: Reorganize PMCCNTR accesses 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: Aaron Lindsay , 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" pmccntr_read and pmccntr_write contained duplicate code that was already being handled by pmccntr_sync. Consolidate the duplicated code into two functions: pmccntr_op_start and pmccntr_op_finish. Add a companion to c15_ccnt in CPUARMState so that we can simultaneously save both the architectural register value and the last underlying cycle count - this ensure time isn't lost and will also allow us to access the 'old' architectural register value in order to detect overflows in later patches. Signed-off-by: Aaron Lindsay --- target/arm/cpu.h | 28 ++++++++++----- target/arm/helper.c | 100 ++++++++++++++++++++++++++++--------------------= ---- 2 files changed, 73 insertions(+), 55 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 8488273..ba2c876 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -467,10 +467,20 @@ typedef struct CPUARMState { uint64_t oslsr_el1; /* OS Lock Status */ uint64_t mdcr_el2; uint64_t mdcr_el3; - /* If the counter is enabled, this stores the last time the counter - * was reset. Otherwise it stores the counter value + /* Stores the architectural value of the counter *the last time it= was + * updated* by pmccntr_op_start. Accesses should always be surroun= ded + * by pmccntr_op_start/pmccntr_op_finish to guarantee the latest + * architecturally-corect value is being read/set. */ uint64_t c15_ccnt; + /* Stores the delta between the architectural value and the underl= ying + * cycle count during normal operation. It is used to update c15_c= cnt + * to be the correct architectural value before accesses. During + * accesses, c15_ccnt_delta contains the underlying count being us= ed + * for the access, after which it reverts to the delta value in + * pmccntr_op_finish. + */ + uint64_t c15_ccnt_delta; uint64_t pmccfiltr_el0; /* Performance Monitor Filter Register */ uint64_t vpidr_el2; /* Virtualization Processor ID Register */ uint64_t vmpidr_el2; /* Virtualization Multiprocessor ID Register = */ @@ -924,15 +934,17 @@ 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. */ -void pmccntr_sync(CPUARMState *env); +void pmccntr_op_start(CPUARMState *env); +void pmccntr_op_finish(CPUARMState *env); =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 1248d84..23b3a16 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1044,28 +1044,53 @@ static inline bool arm_ccnt_enabled(CPUARMState *en= v) =20 return true; } - -void pmccntr_sync(CPUARMState *env) +/* + * Ensure c15_ccnt is the guest-visible count so that operations such as + * enabling/disabling the counter or filtering, modifying the count itself, + * etc. can be done logically. This is essentially a no-op if the counter = is + * not enabled at the time of the call. + */ +void pmccntr_op_start(CPUARMState *env) { - uint64_t temp_ticks; - - temp_ticks =3D muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), + uint64_t cycles =3D 0; + cycles =3D muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), ARM_CPU_FREQ, NANOSECONDS_PER_SECOND); =20 - if (env->cp15.c9_pmcr & PMCRD) { - /* Increment once every 64 processor clock cycles */ - temp_ticks /=3D 64; - } - if (arm_ccnt_enabled(env)) { - env->cp15.c15_ccnt =3D temp_ticks - env->cp15.c15_ccnt; + uint64_t eff_cycles =3D cycles; + if (env->cp15.c9_pmcr & PMCRD) { + /* Increment once every 64 processor clock cycles */ + eff_cycles /=3D 64; + } + + env->cp15.c15_ccnt =3D eff_cycles - env->cp15.c15_ccnt_delta; + } + env->cp15.c15_ccnt_delta =3D cycles; +} + +/* + * If PMCCNTR is enabled, recalculate the delta between the clock and the + * guest-visible count. A call to pmccntr_op_finish should follow every ca= ll to + * pmccntr_op_start. + */ +void pmccntr_op_finish(CPUARMState *env) +{ + if (arm_ccnt_enabled(env)) { + uint64_t prev_cycles =3D env->cp15.c15_ccnt_delta; + + if (env->cp15.c9_pmcr & PMCRD) { + /* Increment once every 64 processor clock cycles */ + prev_cycles /=3D 64; + } + + env->cp15.c15_ccnt_delta =3D prev_cycles - env->cp15.c15_ccnt; } } =20 static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - pmccntr_sync(env); + pmccntr_op_start(env); =20 if (value & PMCRC) { /* The counter has been reset */ @@ -1076,26 +1101,16 @@ static void pmcr_write(CPUARMState *env, const ARMC= PRegInfo *ri, env->cp15.c9_pmcr &=3D ~0x39; env->cp15.c9_pmcr |=3D (value & 0x39); =20 - pmccntr_sync(env); + pmccntr_op_finish(env); } =20 static uint64_t pmccntr_read(CPUARMState *env, const ARMCPRegInfo *ri) { - uint64_t total_ticks; - - if (!arm_ccnt_enabled(env)) { - /* Counter is disabled, do not change value */ - return env->cp15.c15_ccnt; - } - - total_ticks =3D muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - ARM_CPU_FREQ, NANOSECONDS_PER_SECOND); - - if (env->cp15.c9_pmcr & PMCRD) { - /* Increment once every 64 processor clock cycles */ - total_ticks /=3D 64; - } - return total_ticks - env->cp15.c15_ccnt; + uint64_t ret; + pmccntr_op_start(env); + ret =3D env->cp15.c15_ccnt; + pmccntr_op_finish(env); + return ret; } =20 static void pmselr_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -1112,22 +1127,9 @@ static void pmselr_write(CPUARMState *env, const ARM= CPRegInfo *ri, static void pmccntr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - uint64_t total_ticks; - - if (!arm_ccnt_enabled(env)) { - /* Counter is disabled, set the absolute value */ - env->cp15.c15_ccnt =3D value; - return; - } - - total_ticks =3D muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - ARM_CPU_FREQ, NANOSECONDS_PER_SECOND); - - if (env->cp15.c9_pmcr & PMCRD) { - /* Increment once every 64 processor clock cycles */ - total_ticks /=3D 64; - } - env->cp15.c15_ccnt =3D total_ticks - value; + pmccntr_op_start(env); + env->cp15.c15_ccnt =3D value; + pmccntr_op_finish(env); } =20 static void pmccntr_write32(CPUARMState *env, const ARMCPRegInfo *ri, @@ -1140,7 +1142,11 @@ static void pmccntr_write32(CPUARMState *env, const = ARMCPRegInfo *ri, =20 #else /* CONFIG_USER_ONLY */ =20 -void pmccntr_sync(CPUARMState *env) +void pmccntr_op_start(CPUARMState *env) +{ +} + +void pmccntr_op_finish(CPUARMState *env) { } =20 @@ -1149,9 +1155,9 @@ void pmccntr_sync(CPUARMState *env) static void pmccfiltr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - pmccntr_sync(env); + pmccntr_op_start(env); env->cp15.pmccfiltr_el0 =3D value & 0xfc000000; - pmccntr_sync(env); + pmccntr_op_finish(env); } =20 static void pmcntenset_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.