drivers/timer/hpet: Work around crazy qemu behavior
At least twice (to be fair: twice among thousands of test runs), I've seen this device return "backwards" times in SMP, where the counter value read from one CPU is behind the saved value already seen on the other. On hardware this should obviously never happen, HPET is a single global device. Add a simple workaround on QEMU targets so the math doesn't blow up. Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
parent
d1200d2155
commit
bab348e915
1 changed files with 14 additions and 0 deletions
|
@ -38,6 +38,20 @@ static void hpet_isr(void *arg)
|
||||||
ARG_UNUSED(arg);
|
ARG_UNUSED(arg);
|
||||||
k_spinlock_key_t key = k_spin_lock(&lock);
|
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||||
u32_t now = MAIN_COUNTER_REG;
|
u32_t now = MAIN_COUNTER_REG;
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_SMP) &&
|
||||||
|
IS_ENABLED(CONFIG_QEMU_TARGET)) {
|
||||||
|
/* Qemu in SMP mode has observed the clock going
|
||||||
|
* "backwards" relative to interrupts already received
|
||||||
|
* on the other CPU, despite the HPET being
|
||||||
|
* theoretically a global device.
|
||||||
|
*/
|
||||||
|
s32_t diff = (s32_t)(now - last_count);
|
||||||
|
|
||||||
|
if (last_count && diff < 0) {
|
||||||
|
now = last_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
u32_t dticks = (now - last_count) / cyc_per_tick;
|
u32_t dticks = (now - last_count) / cyc_per_tick;
|
||||||
|
|
||||||
last_count += dticks * cyc_per_tick;
|
last_count += dticks * cyc_per_tick;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue