From nobody Mon Nov 25 02:53:45 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1717825992; cv=none; d=zohomail.com; s=zohoarc; b=Oq09DlPe6Kr/56Uq8AE4Nkwh10/v+AxKficnqA+ojKkopxI2fYRuPIJmo0JuHCnkE1SvPqhXU92v1W4uq0XwfEXEjg6Nnt/vM+yfGca7UbCiiVD66pIE23/AgIT0GDPw2U7/R5zDgh6SBV1IsG0F4+T/AezE4uj6JX+rGB0YEWw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1717825992; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:Sender:Subject:Subject:To:To:Message-Id; bh=8FURphr+ffyAV4m2xwBv/8bknDaTQpO01ia6sOv8rVo=; b=dkgdeeJ7XPwuPXgddk66QnFcBuvQ/psF++QgePc3OI9HMdigK2NHBUi41Ipb/8/NDmkX8QYkGYTDbkpBR+eRoOPVG0DFZYjF+AcUuUbyBjX2Ece6lyTzexQ9s9dfhHhlkRrz0ehPlHytXRakVqQnZGVZiCMi5iqZxS4dz1O0Nu0= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1717825992079101.31097835868877; Fri, 7 Jun 2024 22:53:12 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sFozx-0003kB-Av; Sat, 08 Jun 2024 01:52:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sFi5o-0001rc-NJ for qemu-devel@nongnu.org; Fri, 07 Jun 2024 18:29:52 -0400 Received: from b-painless.mh.aa.net.uk ([2001:8b0:0:30::52]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sFi5m-000051-KX for qemu-devel@nongnu.org; Fri, 07 Jun 2024 18:29:52 -0400 Received: from thunderhill.nvidia.com ([216.228.112.22] helo=localhost.localdomain) by painless-b.tch.aa.net.uk with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1sFi5k-007UAh-0u; Fri, 07 Jun 2024 23:29:48 +0100 To: qemu-devel@nongnu.org Cc: Stafford Horne , Joel Holdsworth Subject: [PATCH] hw/openrisc: Fixed undercounting of TTCR in continuous mode Date: Fri, 7 Jun 2024 15:29:33 -0700 Message-ID: <20240607222933.45791-1-jholdsworth@nvidia.com> X-Mailer: git-send-email 2.44.1 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: softfail client-ip=2001:8b0:0:30::52; envelope-from=jholdsworth@nvidia.com; helo=b-painless.mh.aa.net.uk X-Spam_score_int: -34 X-Spam_score: -3.5 X-Spam_bar: --- X-Spam_report: (-3.5 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_SOFTFAIL=0.665, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Sat, 08 Jun 2024 01:52:16 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: Joel Holdsworth From: Joel Holdsworth via Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1717825992988100001 Content-Type: text/plain; charset="utf-8" In the existing design, TTCR is prone to undercounting when running in continuous mode. This manifests as a timer interrupt appearing to trigger a few cycles prior to the deadline set in SPR_TTMR_TP. When the timer triggers, the virtual time delta in nanoseconds between the time when the timer was set, and when it triggers is calculated. This nanoseconds value is then divided by TIMER_PERIOD (50) to compute an increment of cycles to apply to TTCR. However, this calculation rounds down the number of cycles causing the undercounting. A simplistic solution would be to instead round up the number of cycles, however this will result in the accumulation of timing error over time. This patch corrects the issue by calculating the time delta in nanoseconds between when the timer was last reset and the timer event. This approach allows the TTCR value to be rounded up, but without accumulating error over time. Signed-off-by: Joel Holdsworth --- hw/openrisc/cputimer.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c index 835986c4db..ddc129aa48 100644 --- a/hw/openrisc/cputimer.c +++ b/hw/openrisc/cputimer.c @@ -29,7 +29,8 @@ /* Tick Timer global state to allow all cores to be in sync */ typedef struct OR1KTimerState { uint32_t ttcr; - uint64_t last_clk; + uint32_t ttcr_offset; + uint64_t clk_offset; } OR1KTimerState; =20 static OR1KTimerState *or1k_timer; @@ -37,6 +38,8 @@ static OR1KTimerState *or1k_timer; void cpu_openrisc_count_set(OpenRISCCPU *cpu, uint32_t val) { or1k_timer->ttcr =3D val; + or1k_timer->ttcr_offset =3D val; + or1k_timer->clk_offset =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); } =20 uint32_t cpu_openrisc_count_get(OpenRISCCPU *cpu) @@ -53,9 +56,8 @@ void cpu_openrisc_count_update(OpenRISCCPU *cpu) return; } now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - or1k_timer->ttcr +=3D (uint32_t)((now - or1k_timer->last_clk) - / TIMER_PERIOD); - or1k_timer->last_clk =3D now; + or1k_timer->ttcr =3D (now - or1k_timer->clk_offset + TIMER_PERIOD - 1)= / TIMER_PERIOD + + or1k_timer->ttcr_offset; } =20 /* Update the next timeout time as difference between ttmr and ttcr */ @@ -69,7 +71,7 @@ void cpu_openrisc_timer_update(OpenRISCCPU *cpu) } =20 cpu_openrisc_count_update(cpu); - now =3D or1k_timer->last_clk; + now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); =20 if ((cpu->env.ttmr & TTMR_TP) <=3D (or1k_timer->ttcr & TTMR_TP)) { wait =3D TTMR_TP - (or1k_timer->ttcr & TTMR_TP) + 1; @@ -110,7 +112,8 @@ static void openrisc_timer_cb(void *opaque) case TIMER_NONE: break; case TIMER_INTR: - or1k_timer->ttcr =3D 0; + /* Zero the count by applying a negative offset to the counter */ + or1k_timer->ttcr_offset +=3D UINT32_MAX - (cpu->env.ttmr & TTMR_TP= ); break; case TIMER_SHOT: cpu_openrisc_count_stop(cpu); @@ -137,8 +140,8 @@ static void openrisc_count_reset(void *opaque) /* Reset the global timer state. */ static void openrisc_timer_reset(void *opaque) { - or1k_timer->ttcr =3D 0x00000000; - or1k_timer->last_clk =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + OpenRISCCPU *cpu =3D opaque; + cpu_openrisc_count_set(cpu, 0); } =20 static const VMStateDescription vmstate_or1k_timer =3D { @@ -147,7 +150,8 @@ static const VMStateDescription vmstate_or1k_timer =3D { .minimum_version_id =3D 1, .fields =3D (const VMStateField[]) { VMSTATE_UINT32(ttcr, OR1KTimerState), - VMSTATE_UINT64(last_clk, OR1KTimerState), + VMSTATE_UINT32(ttcr_offset, OR1KTimerState), + VMSTATE_UINT64(clk_offset, OR1KTimerState), VMSTATE_END_OF_LIST() } }; --=20 2.44.1