From patchwork Sat Oct 19 21:36:06 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Macke X-Patchwork-Id: 284907 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)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 20CE72C00AD for ; Sun, 20 Oct 2013 08:36:41 +1100 (EST) Received: from localhost ([::1]:34476 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VXeCL-0001VQ-US for incoming@patchwork.ozlabs.org; Sat, 19 Oct 2013 17:36:37 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58751) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VXeC1-0001UQ-L9 for qemu-devel@nongnu.org; Sat, 19 Oct 2013 17:36:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VXeBv-0007cV-FA for qemu-devel@nongnu.org; Sat, 19 Oct 2013 17:36:17 -0400 Received: from www11.your-server.de ([213.133.104.11]:41216) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VXeBv-0007c4-64 for qemu-devel@nongnu.org; Sat, 19 Oct 2013 17:36:11 -0400 Received: from [142.103.140.43] by www11.your-server.de with esmtpa (Exim 4.74) (envelope-from ) id 1VXeBo-0004qy-H3; Sat, 19 Oct 2013 23:36:04 +0200 Message-ID: <5262FB46.4030606@macke.de> Date: Sat, 19 Oct 2013 14:36:06 -0700 From: Sebastian Macke User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Thunderbird/24.0.1 MIME-Version: 1.0 To: qemu-devel@nongnu.org, Jia Liu X-Authenticated-Sender: sebastian@macke.de X-Virus-Scanned: Clear (ClamAV 0.97.6/17974/Sat Oct 19 18:38:35 2013) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] X-Received-From: 213.133.104.11 Cc: openrisc , "openrisc@lists.opencores.org" Subject: [Qemu-devel] [PATCH] openrisc-timer: Reduce overhead, Separate clock update functions 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 The clock value is only evaluated when really necessary reducing the overhead of the timer handling. This also solves a problem in the way the Linux kernel handles the timer and the expected accuracy. The old version could lead to inaccurate timings. Signed-off-by: Sebastian Macke --- hw/openrisc/cputimer.c | 29 +++++++++++++++++++---------- target-openrisc/cpu.h | 1 + target-openrisc/sys_helper.c | 38 ++++++++++++++++++-------------------- 3 files changed, 38 insertions(+), 30 deletions(-) } - cpu_openrisc_count_start(cpu); + cpu_openrisc_timer_update(cpu); break; default: -- 1.7.9.5 diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c index 988ca20..9c54945 100644 --- a/hw/openrisc/cputimer.c +++ b/hw/openrisc/cputimer.c @@ -30,19 +30,28 @@ static int is_counting; void cpu_openrisc_count_update(OpenRISCCPU *cpu) { - uint64_t now, next; - uint32_t wait; + uint64_t now; - now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); if (!is_counting) { - timer_del(cpu->env.timer); - last_clk = now; return; } - + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ, get_ticks_per_sec()); last_clk = now; +} + +void cpu_openrisc_timer_update(OpenRISCCPU *cpu) +{ + uint32_t wait; + uint64_t now, next; + + if (!is_counting) { + return; + } + + cpu_openrisc_count_update(cpu); + now = last_clk; if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) { wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1; @@ -50,7 +59,6 @@ void cpu_openrisc_count_update(OpenRISCCPU *cpu) } else { wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP); } - next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ); timer_mod(cpu->env.timer, next); } @@ -63,8 +71,9 @@ void cpu_openrisc_count_start(OpenRISCCPU *cpu) void cpu_openrisc_count_stop(OpenRISCCPU *cpu) { - is_counting = 0; + timer_del(cpu->env.timer); cpu_openrisc_count_update(cpu); + is_counting = 0; } static void openrisc_timer_cb(void *opaque) @@ -84,15 +93,15 @@ static void openrisc_timer_cb(void *opaque) break; case TIMER_INTR: cpu->env.ttcr = 0; - cpu_openrisc_count_start(cpu); break; case TIMER_SHOT: cpu_openrisc_count_stop(cpu); break; case TIMER_CONT: - cpu_openrisc_count_start(cpu); break; } + + cpu_openrisc_timer_update(cpu); } void cpu_openrisc_clock_init(OpenRISCCPU *cpu) diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h index 8fd0bc0..0f9efdf 100644 --- a/target-openrisc/cpu.h +++ b/target-openrisc/cpu.h @@ -373,6 +373,7 @@ void cpu_openrisc_pic_init(OpenRISCCPU *cpu); /* hw/openrisc_timer.c */ void cpu_openrisc_clock_init(OpenRISCCPU *cpu); void cpu_openrisc_count_update(OpenRISCCPU *cpu); +void cpu_openrisc_timer_update(OpenRISCCPU *cpu); void cpu_openrisc_count_start(OpenRISCCPU *cpu); void cpu_openrisc_count_stop(OpenRISCCPU *cpu); diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c index cccbc0e..43fd93f 100644 --- a/target-openrisc/sys_helper.c +++ b/target-openrisc/sys_helper.c @@ -127,33 +127,31 @@ void HELPER(mtspr)(CPUOpenRISCState *env, break; case TO_SPR(10, 0): /* TTMR */ { + if ((env->ttmr & TTMR_M) ^ (rb & TTMR_M)) { + switch (rb & TTMR_M) { + case TIMER_NONE: + cpu_openrisc_count_stop(cpu); + break; + case TIMER_INTR: + case TIMER_SHOT: + case TIMER_CONT: + cpu_openrisc_count_start(cpu); + break; + default: + break; + } + } + int ip = env->ttmr & TTMR_IP; if (rb & TTMR_IP) { /* Keep IP bit. */ - env->ttmr = (rb & ~TTMR_IP) + ip; + env->ttmr = (rb & ~TTMR_IP) | ip; } else { /* Clear IP bit. */ env->ttmr = rb & ~TTMR_IP; cs->interrupt_request &= ~CPU_INTERRUPT_TIMER; } - cpu_openrisc_count_update(cpu); - - switch (env->ttmr & TTMR_M) { - case TIMER_NONE: - cpu_openrisc_count_stop(cpu); - break; - case TIMER_INTR: - cpu_openrisc_count_start(cpu); - break; - case TIMER_SHOT: - cpu_openrisc_count_start(cpu); - break; - case TIMER_CONT: - cpu_openrisc_count_start(cpu); - break; - default: - break; - } + cpu_openrisc_timer_update(cpu); } break; @@ -162,7 +160,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, if (env->ttmr & TIMER_NONE) { return;