Commit 77b91aca61 for qemu.org
commit 77b91aca6148fafcade41516f12a3309f1e1f552
Author: Bibo Mao <maobibo@loongson.cn>
Date: Tue Jul 14 10:55:16 2026 +0800
target/loongarch: Set timer tick value even if disabled
If constant timer is enabled, its tick value is remained value from
the next expired time. However if timer is not enabled, its value
should be CONSTANT_TIMER_TICK_MASK or zero.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Reviewed-by: Xianglai Li <lixianglai@loongson.cn>
diff --git a/target/loongarch/tcg/constant_timer.c b/target/loongarch/tcg/constant_timer.c
index f56e76d482..b91ad1de69 100644
--- a/target/loongarch/tcg/constant_timer.c
+++ b/target/loongarch/tcg/constant_timer.c
@@ -22,12 +22,18 @@ uint64_t cpu_loongarch_get_constant_timer_counter(LoongArchCPU *cpu)
uint64_t cpu_loongarch_get_constant_timer_ticks(LoongArchCPU *cpu)
{
+ CPULoongArchState *env = &cpu->env;
+ CPUSysState *sys = env_sys(env);
uint64_t now, expire;
- now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- expire = timer_expire_time_ns(&cpu->timer);
+ if ((sys->CSR_TCFG & CONSTANT_TIMER_ENABLE) &&
+ (sys->CSR_TVAL < sys->CSR_TCFG)) {
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ expire = timer_expire_time_ns(&cpu->timer);
+ sys->CSR_TVAL = (expire - now) / TIMER_PERIOD;
+ }
- return (expire - now) / TIMER_PERIOD;
+ return sys->CSR_TVAL;
}
void cpu_loongarch_store_constant_timer_config(LoongArchCPU *cpu,
@@ -42,8 +48,10 @@ void cpu_loongarch_store_constant_timer_config(LoongArchCPU *cpu,
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
next = now + (value & CONSTANT_TIMER_TICK_MASK) * TIMER_PERIOD;
timer_mod(&cpu->timer, next);
+ sys->CSR_TVAL = sys->CSR_TCFG & CONSTANT_TIMER_TICK_MASK;
} else {
timer_del(&cpu->timer);
+ sys->CSR_TVAL = 0;
}
}
@@ -58,8 +66,9 @@ void loongarch_constant_timer_cb(void *opaque)
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
next = now + (sys->CSR_TCFG & CONSTANT_TIMER_TICK_MASK) * TIMER_PERIOD;
timer_mod(&cpu->timer, next);
+ sys->CSR_TVAL = sys->CSR_TCFG & CONSTANT_TIMER_TICK_MASK;
} else {
- sys->CSR_TCFG = FIELD_DP64(sys->CSR_TCFG, CSR_TCFG, EN, 0);
+ sys->CSR_TVAL = CONSTANT_TIMER_TICK_MASK;
}
loongarch_cpu_set_irq(opaque, IRQ_TIMER, 1);