Re: [RFC PATCH v2] ptp: Add vDSO-style vmclock support

Peter Hilber
2024-06-28T11:33:18Z

On 27.06.24 16:52, David Woodhouse wrote:
> On Thu, 2024-06-27 at 15:50 +0200, Peter Hilber wrote:
>> On 25.06.24 21:01, David Woodhouse wrote:
>>> From: David Woodhouse <dwmw@amazon.co.uk>
>>>
>>> The vmclock "device" provides a shared memory region with precision clock
>>> information. By using shared memory, it is safe across Live Migration.
>>>
>>> Like the KVM PTP clock, this can convert TSC-based cross timestamps into
>>> KVM clock values. Unlike the KVM PTP clock, it does so only when such is
>>> actually helpful.
>>>
>>> The memory region of the device is also exposed to userspace so it can be
>>> read or memory mapped by application which need reliable notification of
>>> clock disruptions.
>>>
>>> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
>>> ---
>>>
>>> v2:
>>>  • Add gettimex64() support
>>>  • Convert TSC values to KVM clock when appropriate
>>>  • Require int128 support
>>>  • Add counter_period_shift
>>>  • Add timeout when seq_count is invalid
>>>  • Add flags field
>>>  • Better comments in vmclock ABI structure
>>>  • Explicitly forbid smearing (as clock rates would need to change)
>>
>> Leap second smearing information could still be conveyed through the
>> vmclock_abi. AFAIU, to cover the popular smearing variants, it should be
>> enough to indicate whether the driver should apply linear or cosine
>> smearing, and the start time and end time.
>
> Yes. The clock information actually conveyed through the {counter,
> time, rate} tuple should never be smeared, and should only ever be UTC.
>
> But we could provide a hint to the guest operating system about what
> type of smearing to perform, *if* it chooses to offer a clock other
> than the standard CLOCK_REALTIME to its users.
>
> I already added a flags field, so this might look something like:
>
> /*
> * Smearing flags. The UTC clock exposed through this structure
> * is only ever true UTC, but a guest operating system may
> * choose to offer a monotonic smeared clock to its users. This
> * merely offers a hint about what kind of smearing to perform,
> * for consistency with systems in the nearby environment.
> */
> #define VMCLOCK_FLAGS_SMEAR_UTC_SLS (1<<5) /* draft-kuhn-leapsecond-00.txt */
>
>
> (UTC-SLS is probably a bad example but are there formal definitions for
> anything else?)
>
>

I think it could also be more generic, like flags for linear smearing,
cosine smearing(?), and smear_start_sec and smear_end_sec fields (relative
to the leap second start). That could also represent UTC-SLS, and
noon-to-noon, and it would be well-defined.

This should reduce the likelihood that the guest doesn't know the smearing
variant.

[...]

>>> diff --git a/include/uapi/linux/vmclock.h b/include/uapi/linux/vmclock.h
>>> new file mode 100644
>>> index 000000000000..cf0f22205e79
>>> --- /dev/null
>>> +++ b/include/uapi/linux/vmclock.h
>>> @@ -0,0 +1,138 @@
>>> +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) */
>>> +
>>> +/*
>>> + * This structure provides a vDSO-style clock to VM guests, exposing the
>>> + * relationship (or lack thereof) between the CPU clock (TSC, timebase, arch
>>> + * counter, etc.) and real time. It is designed to address the problem of
>>> + * live migration, which other clock enlightenments do not.
>>> + *
>>> + * When a guest is live migrated, this affects the clock in two ways.
>>> + *
>>> + * First, even between identical hosts the actual frequency of the underlying
>>> + * counter will change within the tolerances of its specification (typically
>>> + * ±50PPM, or 4 seconds a day). The frequency also varies over time on the
>>> + * same host, but can be tracked by NTP as it generally varies slowly. With
>>> + * live migration there is a step change in the frequency, with no warning.
>>> + *
>>> + * Second, there may be a step change in the value of the counter itself, as
>>> + * its accuracy is limited by the precision of the NTP synchronization on the
>>> + * source and destination hosts.
>>> + *
>>> + * So any calibration (NTP, PTP, etc.) which the guest has done on the source
>>> + * host before migration is invalid, and needs to be redone on the new host.
>>> + *
>>> + * In its most basic mode, this structure provides only an indication to the
>>> + * guest that live migration has occurred. This allows the guest to know that
>>> + * its clock is invalid and take remedial action. For applications that need
>>> + * reliable accurate timestamps (e.g. distributed databases), the structure
>>> + * can be mapped all the way to userspace. This allows the application to see
>>> + * directly for itself that the clock is disrupted and take appropriate
>>> + * action, even when using a vDSO-style method to get the time instead of a
>>> + * system call.
>>> + *
>>> + * In its more advanced mode. this structure can also be used to expose the
>>> + * precise relationship of the CPU counter to real time, as calibrated by the
>>> + * host. This means that userspace applications can have accurate time
>>> + * immediately after live migration, rather than having to pause operations
>>> + * and wait for NTP to recover. This mode does, of course, rely on the
>>> + * counter being reliable and consistent across CPUs.
>>> + *
>>> + * Note that this must be true UTC, never with smeared leap seconds. If a
>>> + * guest wishes to construct a smeared clock, it can do so. Presenting a
>>> + * smeared clock through this interface would be problematic because it
>>> + * actually messes with the apparent counter *period*. A linear smearing
>>> + * of 1 ms per second would effectively tweak the counter period by 1000PPM
>>> + * at the start/end of the smearing period, while a sinusoidal smear would
>>> + * basically be impossible to represent.
>>
>> Clock types other than UTC could also be supported: TAI, monotonic.
>
> This exposes both TAI *and* UTC, by exposing the TAI offset. Or it can
> expose UTC only, without the TAI offset if that's unknown.
>
> Should we also have a mode for exposing TAI only, for when TAI is known
> but not the offset from UTC? Is that really a likely scenario? Isn't a
> host much more likely to know UTC and *not* the TAI offset?
>
> I suppose if we have *hardware* implementations of this, they could be
> based on an atomic clock and all they'll have is TAI? So OK, maybe that
> makes sense?
>
> (We'd have to add something like the ART as the counter to pair with
> over an actual PCI bus, of course.)
>
> We can add a type field like the one you have for virtio-rtc, yes?
>
>

Ack.

>>
>>> + */
>>> +
>>> +#ifndef __VMCLOCK_H__
>>> +#define __VMCLOCK_H__
>>> +
>>> +#ifdef __KERNEL
>>> +#include <linux/types.h>
>>> +#else
>>> +#include <stdint.h>
>>> +#endif
>>> +
>>> +struct vmclock_abi {
>>> +       uint32_t magic;
>>> +#define VMCLOCK_MAGIC  0x4b4c4356 /* "VCLK" */
>>> +       uint16_t size;          /* Size of page containing this structure */
>>> +       uint16_t version;       /* 1 */
>>> +
>>> +       /* Sequence lock. Low bit means an update is in progress. */
>>> +       uint64_t seq_count;
>>> +
>>> +       /*
>>> +        * This field changes to another non-repeating value when the CPU
>>> +        * counter is disrupted, for example on live migration.
>>> +        */
>>> +       uint64_t disruption_marker;
>>
>> The field could also change when the clock is stepped (leap seconds
>> excepted), or when the clock frequency is slewed.
>
> I'm not sure. The concept of the disruption marker is that it tells the
> guest to throw away any calibration of the counter that the guest has
> done for *itself* (with NTP, other PTP devices, etc.).
>
> One mode for this device would be not to populate the clock fields at
> all, but *only* to signal disruption when it occurs. So the guest can
> abort transactions until it's resynced its clocks (to avoid incurring
> fines if breaking databases, etc.).
>
> Exposing the host timekeeping through the structure means that the
> migrated guest can keep working because it can trust the timekeeping
> performed by the (new) host and exposed to it.
>
> If the counter is actually varying in frequency over time, and the host
> is slewing the clock frequency that it reports, that *isn't* a step
> change and doesn't mean that the guest should throw away any
> calibration that it's been doing for itself. One hopes that the guest
> would have detected the *same* frequency change, and be adapting for
> itself. So I don't think that should indicate a disruption.
>
> I think the same is even true if the clock is stepped by the host. The
> actual *counter* hasn't changed, so the guest is better off ignoring
> the vacillating host and continuing to derive its idea of time from the
> hardware counter itself, as calibrated against some external NTP/PTP
> sources. Surely we actively *don't* to tell the guest to throw its own
> calibrations away, in this case?

In case the guest is also considering other time sources, it might indeed
not be a good idea to mix host clock changes into the hardware counter
disruption marker.

But if the vmclock is the authoritative source of time, it can still be
helpful to know about such changes, maybe through another marker.