Re: [PATCH 14/21] MIPS: KVM: Add nanosecond count bias KVM register

James Hogan
2014-05-28T14:21:28Z

Hi Paolo, David, Andreas,

On 26/04/14 10:37, Paolo Bonzini wrote:
> Il 26/04/2014 00:34, James Hogan ha scritto:
>> So yes, you could technically manage without (4) by using (2) ((4) was
>> implemented first), but I think it probably still has some value since
>> you can
>> do it with a single ioctl rather than 4 ioctls (freeze timer, read
>> resume_time, read or write count, unfreeze timer).
>>
>> Enough value to be worthwhile? I haven't really made up my mind yet
>> but I'm
>> leaning towards yes.
>
> It would be interesting to see how the userspace patches use this
> independent of COUNT_RESUME.

The implementation in QEMU that I've settled upon makes do with just
COUNT_CTL and COUNT_RESUME, but with a slight kernel modification so
that COUNT_RESUME is writeable (to any positive monotonic nanosecond
value <= now). It works fairly cleanly and correctly even with stopping
and starting VM clock (gdb, stop/cont, savevm/loadvm, live migration),
to match the behaviour of the existing mips cpu timer emulation, so I
plan to drop this bias patch, and will post a v2 patchset soon with just
a few modifications.

QEMU saves the state of the KVM timer from kvm_arch_get_registers() or
when the VM clock is stopped (via a vmstate notifier) - whichever comes
first. It then restores the KVM timer from kvm_arch_put_registers() or
when the VM clock is started - whichever comes last.
Example sequence:
stop VM - SAVE
get regs - vm clock already stopped, not saved again
start VM - regs dirty, not restored
put regs - vm clock running, RESTORE

Saving involves:
COUNT_CTL.DC = 1 (freeze KVM timer)
get CP0_Cause, CP0_Count and COUNT_RESUME
store a copy of the calculated VM clock @COUNT_RESUME nanoseconds
(i.e. the VM clock corresponding to the saved CP0_Count)

Restoring involves:
put COUNT_RESUME = now - (vm clock @now - saved vm clock)
(resume occurs at the same interval into the past that the VM clock has
increased since saving)
put CP0_Cause, CP0_Count
(the stored CP0_Count applies at that resume time)
COUNT_CTL.DC = 0 (resume KVM timer from CP0_Count at COUNT_RESUME)

I'll post an updated QEMU patchset ASAP after the KVM patchset, but
wanted to explain how this API can actually be used. Does it sound
reasonable?

Thanks
James