KVM Clock

Roger Pau Monné roger.pau at citrix.com
Wed Jan 15 16:04:40 UTC 2014


On 15/01/14 14:45, Julian Stecklina wrote:
> On Mi, 2014-01-15 at 14:08 +0100, Roger Pau Monné wrote:
>> On 15/01/14 13:05, Julian Stecklina wrote:
>>> On 01/14/2014 05:13 PM, Peter Grehan wrote:
>>>> Hi Julian,
>>>>
>>>>> is anyone working on KVM clock support for FreeBSD? If not, I
>>>>> might take a shot at it.
>>>>
>>>> None I know of: go for it :)
>>>
>>> Works for me so far: 
>>> https://github.com/blitz/freebsd/commit/cdc5f872b3e48cc0dda031fc7d6bdedc65c3148f
>>
>> Looking
>>>
>> at the code it seems some common routines could be shared
>> between the KVM PV clock and the Xen PV clock
>> (sys/dev/xen/timer/timer.c). The data passed from the hypervisor to
>> the guest has exactly the same format (see struct vcpu_time_info in
>> Xen public headers).
> 
> Yes, I know. Didn't get around to making it pretty yesterday evening. ;)
> I'll post an updated patch, when I have some time. Any suggestions where
> to put the two common functions?
> 
>> At a first sight the KVM clock can benefit from using scale_delta
>> (which is going to be faster than the C version implemented in
>> kvmclock_get_timecount),
> 
> At least somewhat on amd64. 32-bit looks pretty identical.
> 
>>  and xen_fetch_vcpu_tinfo is exactly the same
>> as kvmclock_fetch.
> 
> I think xen_fetch_vcpu_tinfo has a subtle bug:
>   217         do {
>   218                 dst->version = src->version;
>   219                 rmb();
>   220                 dst->tsc_timestamp = src->tsc_timestamp;
>   221                 dst->system_time = src->system_time;
>   222                 dst->tsc_to_system_mul = src->tsc_to_system_mul;
>   223                 dst->tsc_shift = src->tsc_shift;
>   224                 rmb();
>   225         } while ((src->version & 1) | (dst->version ^
> src->version));
> 
> In line 225 src->version is potentially read twice. If you consider the
> following schedule:
> 
> host starts updating data, sets src->version to 1
> guest reads src->version (1) and stores it into dst->version.
> guest copies inconsistent data
> guest reads src->version (1) and computes xor with dst->version.
> host finishes updating data and sets src->version to 2
> guest reads src->version (2) and checks whether lower bit is not set.
> while loop exits with inconsistent data!
> 
> I think the C standard (at least C11) permits this as it does not
> specify in which order the two reads in line 225 need to happen.

According to the operator precedence and associativity in C
(http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence),
if I'm reading it right, the condition in the while line will be
evaluated as follows (because of the left-to-right associativity of the
| operator):

1. (src->version & 1)
2. (dst->version ^ src->version)
3. result of 1 | result of 2

So AFAICT the flow that you describe could never happen, because
(src->version & 1) is always done before (dst->version ^ src->version).

Roger.


More information about the freebsd-virtualization mailing list