aboutsummaryrefslogtreecommitdiff
path: root/target/arm/helper.c
diff options
context:
space:
mode:
authorAndrew Jeffery <andrew@aj.id.au>2019-12-20 14:02:59 +0000
committerPeter Maydell <peter.maydell@linaro.org>2019-12-20 14:02:59 +0000
commit7def87548272f6f3831c7ae5ba713c5ccbd5d547 (patch)
tree0cefbe1358746d78f058e62cd67154e3ac6b0771 /target/arm/helper.c
parent4a0245b62502ee9ca7774712de4bb05d9bf47152 (diff)
target/arm: Abstract the generic timer frequency
Prepare for SoCs such as the ASPEED AST2600 whose firmware configures CNTFRQ to values significantly larger than the static 62.5MHz value currently derived from GTIMER_SCALE. As the OS potentially derives its timer periods from the CNTFRQ value the lack of support for running QEMUTimers at the appropriate rate leads to sticky behaviour in the guest. Substitute the GTIMER_SCALE constant with use of a helper to derive the period from gt_cntfrq_hz stored in struct ARMCPU. Initially set gt_cntfrq_hz to the frequency associated with GTIMER_SCALE so current behaviour is maintained. Signed-off-by: Andrew Jeffery <andrew@aj.id.au> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Message-id: 40bd8df043f66e1ccfb3e9482999d099ac72bb2e.1576215453.git-series.andrew@aj.id.au Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/helper.c')
-rw-r--r--target/arm/helper.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 31fab098c5..85963789f7 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2449,7 +2449,9 @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
static uint64_t gt_get_countervalue(CPUARMState *env)
{
- return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE;
+ ARMCPU *cpu = env_archcpu(env);
+
+ return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / gt_cntfrq_period_ns(cpu);
}
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
@@ -2485,7 +2487,7 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
* set the timer for as far in the future as possible. When the
* timer expires we will reset the timer for any remaining period.
*/
- if (nexttick > INT64_MAX / GTIMER_SCALE) {
+ if (nexttick > INT64_MAX / gt_cntfrq_period_ns(cpu)) {
timer_mod_ns(cpu->gt_timer[timeridx], INT64_MAX);
} else {
timer_mod(cpu->gt_timer[timeridx], nexttick);
@@ -2914,11 +2916,13 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
+ ARMCPU *cpu = env_archcpu(env);
+
/* Currently we have no support for QEMUTimer in linux-user so we
* can't call gt_get_countervalue(env), instead we directly
* call the lower level functions.
*/
- return cpu_get_clock() / GTIMER_SCALE;
+ return cpu_get_clock() / gt_cntfrq_period_ns(cpu);
}
static const ARMCPRegInfo generic_timer_cp_reginfo[] = {