mips: Expire late timers when reading cp0_count

When reading cp0_count from a timer with a late trigger that should
already have expired, expire it and raise the timer irq.

This makes it possible for guest code (e.g, Linux) that first read
cp0_count, then compare it with cp0_compare and check for raised
timer interrupt lines to run reliably.

Acked-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
This commit is contained in:
Edgar E. Iglesias 2011-01-18 00:12:22 +01:00
parent b1dfe6437c
commit e027e1f075

View File

@ -69,9 +69,17 @@ uint32_t cpu_mips_get_count (CPUState *env)
if (env->CP0_Cause & (1 << CP0Ca_DC)) { if (env->CP0_Cause & (1 << CP0Ca_DC)) {
return env->CP0_Count; return env->CP0_Count;
} else { } else {
uint64_t now;
now = qemu_get_clock(vm_clock);
if (qemu_timer_pending(env->timer)
&& qemu_timer_expired(env->timer, now)) {
/* The timer has already expired. */
cpu_mips_timer_expire(env);
}
return env->CP0_Count + return env->CP0_Count +
(uint32_t)muldiv64(qemu_get_clock(vm_clock), (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
TIMER_FREQ, get_ticks_per_sec());
} }
} }