Re: [Qemu-devel] [PATCH 1/2] Add HPET emulation to qemu (v3)

Jamie Lokier
2008-11-05T14:49:06Z

Dor Laor wrote:
> Right, I think if this time drift fix approach is accepted, it should also be
> implemented for qemu_irq_pulse too.

I don't think simply injecting timer interrupts is the right approach.

I suspect doing that to compensate for lost ticks can _cause_ drift in
some guests.

Some guest kernels have lost-timer-interrupt detection. For example,
by reading the local TSC, local APIC timer, PM timer, and/or HPET
counter, they can determine (on a real machine) when some timer
interrupts were missed, and compensate for it.

If a burst of timer interrupts are sent by QEMU to compensate for lost
ones due to host scheduling delays, on servicing the first of those
interrupts the guest may read a timer value which indicates time has
jumped forward, and the guest may adjust it's clock to compensate for
missing interrupts. On servicing the remaining ones injected by QEMU,
the guest will read timer values which haven't increased by much, but
since _extra_ timer interrupts aren't expected on real hardware, the
guest may not implement reverse compensation.

The result will be QEMU sends a burst of timer interrupts, and the
guest clock moves _forward_ by a few ticks.

I think a better to handle this in QEMU is to still inject those
"lost" interrupts but also modify the values returned when the guest
reads timers, so they appear to increment by a normal amount between
each interrupt.

In other words, rather than counting ticks, modify the flow of virtual
time - stretch it when the virtual CPU is supposed to run but is
delayed, and compress it afterwards to resync with real time.

On some architectures, this may be even more important with "tickless"
guest kernels which are busily running high resolution timers with
different delays between each event. Simply counting missed
interrupts and injecting a burst doesn't work if the guest depends on
reprogramming a timer chip to a different delay between each interrupt
event (like x86 PIT), but it's fine with timer chips (like HPET) which
have a free-running counter and alarm register.

That method should work with all guests, whatever timers they use and
whatever their interrupt handler does, and result in _zero_ long term
drift as long as the virtual CPU is not persistantly starved. In the
case of timer chips like HPET, which have specified nominal frequency,
it may mean you don't have to run NTP on the guest at all.

-- Jamie