From patchwork Tue Jun 24 01:12:12 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alistair Francis X-Patchwork-Id: 363277 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id E41DC1400BE for ; Tue, 24 Jun 2014 11:13:08 +1000 (EST) Received: from localhost ([::1]:56910 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WzFIJ-0007u1-0M for incoming@patchwork.ozlabs.org; Mon, 23 Jun 2014 21:13:07 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43943) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WzFHd-0006cc-Kw for qemu-devel@nongnu.org; Mon, 23 Jun 2014 21:12:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WzFHX-00052F-MB for qemu-devel@nongnu.org; Mon, 23 Jun 2014 21:12:25 -0400 Received: from mail-yk0-x230.google.com ([2607:f8b0:4002:c07::230]:50707) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WzFHX-000529-H5 for qemu-devel@nongnu.org; Mon, 23 Jun 2014 21:12:19 -0400 Received: by mail-yk0-f176.google.com with SMTP id 131so5175680ykp.7 for ; Mon, 23 Jun 2014 18:12:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=n3mCX51nHVGwpH6jVik7QGBG0cc0+xbCGKTqtNkKq5Q=; b=D/WWZ3xHY3OrrPqKIYDpCx70uvX8wo2kbhAmjbnBq3psTUWtItAxivjvOGmkS7FAaT qySwrCTjxrfRmavW6VjkyrMlZWACuVkYkFkCN13Zhc1KRI9B26PXlkTYJYCDNa0GysrJ XS/IZsfOtoKdkFq35pTKi8g0AEpH1dCRFSgSTYTcDwXdNuadivsBiR71a2aqzVTwMoeX DRlkRJR1t6Yyc550Na4IPAkQz5Cszbws5xuV2qtGkc+x0HJWZ+1b6xUbcXgQaU1GXhSc uxYB92BdgM/UsquLuqdFfZa6mw2PuUW9Um0EtflFIgvAzDbqtuM7yk/7giPsxVNEO8it NjUw== X-Received: by 10.236.143.104 with SMTP id k68mr3593276yhj.143.1403572339203; Mon, 23 Jun 2014 18:12:19 -0700 (PDT) Received: from localhost ([203.126.243.116]) by mx.google.com with ESMTPSA id o69sm32326580yho.19.2014.06.23.18.12.16 for (version=TLSv1.1 cipher=RC4-SHA bits=128/128); Mon, 23 Jun 2014 18:12:18 -0700 (PDT) From: Alistair Francis To: qemu-devel@nongnu.org Date: Tue, 24 Jun 2014 11:12:12 +1000 Message-Id: X-Mailer: git-send-email 1.9.0 In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:4002:c07::230 Cc: peter.maydell@linaro.org, peter.crosthwaite@xilinx.com, alistair.francis@xilinx.com Subject: [Qemu-devel] [PATCH v1 4/7] target-arm: Implement pmccntr_sync function X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This is used to synchronise the PMCCNTR counter and swap its state between enabled and disabled if required. It must always be called twice, both before and after any logic that could change the state of the PMCCNTR counter. Signed-off-by: Alistair Francis --- Remembering that the c15_ccnt register stores the last time the counter was reset if enabled. If disabled it stores the counter value (when it was disabled). The three use cases are as below: -- Starts enabled/disabled and is staying enabled/disabled -- The two calls to pmccntr_sync cancel each other out. Each call implements this logic: env->cp15.c15_ccnt = temp_ticks - env->cp15.c15_ccnt Which expands to: env->cp15.c15_ccnt = temp_ticks - (temp_ticks - env->cp15.c15_ccnt) env->cp15.c15_ccnt = env->cp15.c15_ccnt -- Starts enabled, gets disabled -- The logic is run during the first call while during the second call it is not. That means that c15_ccnt changes from storing the last time the counter was reset, to storing the absolute value of the counter. -- Starts disabled, gets enabled -- During the fist call no changes are made, while during the second call the register is changed. This changes it from storing the absolute value to storing the last time the counter was reset. target-arm/cpu.h | 11 +++++++++++ target-arm/helper.c | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 0 deletions(-) diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 31aa09c..0984eda 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -1051,6 +1051,17 @@ static inline bool cp_access_ok(int current_pl, } /** + * pmccntr_sync + * @cpu: ARMCPU + * + * Syncronises the counter in the PMCCNTR. This must always be called twice, + * once before any action that might effect the timer and again afterwards. + * The fucntion is used to swap the state of the register if required. + * This only happens when not in user mode (!CONFIG_USER_ONLY) + */ +void pmccntr_sync(CPUARMState *env); + +/** * write_list_to_cpustate * @cpu: ARMCPU * diff --git a/target-arm/helper.c b/target-arm/helper.c index ce986ee..15169c4 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -546,6 +546,25 @@ static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri) return CP_ACCESS_OK; } +void pmccntr_sync(CPUARMState *env) +{ +#ifndef CONFIG_USER_ONLY + uint64_t temp_ticks; + + temp_ticks = muldiv64(qemu_clock_get_us(QEMU_CLOCK_VIRTUAL), + get_ticks_per_sec(), 1000000); + + if (env->cp15.c9_pmcr & PMCRD) { + /* Increment once every 64 processor clock cycles */ + temp_ticks /= 64; + } + + if (CCNT_ENABLED(env)) { + env->cp15.c15_ccnt = temp_ticks - env->cp15.c15_ccnt; + } +#endif +} + #ifndef CONFIG_USER_ONLY static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)