Expand description
Virtio version of a linux pvclock clocksource.
Driver source is here: https://android.googlesource.com/kernel/common/+/ebaa2c516811825b141de844cee7a38653058ef5/drivers/virtio/virtio_pvclock.c
§Background
Userland applications often rely on CLOCK_MONOTONIC to be relatively continuous. Large jumps can signal problems (e.g., triggering Android watchdogs). This assumption breaks down in virtualized environments, where a VM’s suspension isn’t inherently linked to the guest kernel’s concept of “suspend”. Since fixing all userland code is impractical, virtio-pvclock allows the VMM and guest kernel to collaborate on emulating the expected clock behavior around suspend/resume.
§How it works
§Core functions of virtio-pvclock device:
- Adjusts hardware clocksource offsets to make the guest clocks appear suspended when the VM is suspended.
- This is achieved through the pvclock mechanism implemented in x86 KVM used by kvm-clock.
- Provides the guest kernel with the duration of VM suspension, allowing the guest to adjust its clocks accordingly.
- Since the offset between the CLOCK_MONOTONIC and CLOCK_BOOTTIME is maintained by the guest kernel, applying the adjustment is the guest driver’s responsibility.
§Expected guest clock behaviors under virtio-pvclock is enabled
- Monotonicity of CLOCK_MONOTONIC and CLOCK_BOOTTIME is maintained.
- CLOCK_MONOTONIC will not include the time passed during crosvm is suspended from its run mode perspective.
- CLOCK_BOOTTIME will be adjusted to include the time passed during crosvm is suspended.
§Why it is needed
Because the existing solution does not cover some expectations we need.
kvm-clock is letting the host to manage the offsets of CLOCK_MONOTONIC. However, it doesn’t address the difference between CLOCK_BOOTTIME and CLOCK_MONOTONIC related to host’s suspend/resume, as it is designed to maintain the CLOCK_REALTIME in sync mainly.
Structs§
- Main
Worker 🔒Return - PvClock
- A struct that represents virtio-pvclock device.
- PvClock
State 🔒 - Serializable part of the PvClock struct which will be used by the virtio_snapshot / restore.
- PvClock
Worker 🔒 - Worker struct for the virtio-pvclock device.
- PvClock
Worker 🔒Snapshot - The unique data retained by PvClockWorker which can be used to re-create an identical worker.
- Pvclock
Instant 🔒 - Represents a moment in time including the TSC counter value at that time.
- Pvclock
Shared 🔒Data - Stub
Worker 🔒Return - virtio_
pvclock_ 🔒config - virtio_
pvclock_ 🔒set_ pvclock_ page_ req
Enums§
- PvClock
Worker 🔒State - An enum to keep dynamic state of pvclock workers in a type safe manner.
Constants§
- PVCLOCK_
GUEST_ 🔒STOPPED - PVCLOCK_
TSC_ 🔒STABLE_ BIT - QUEUE_
SIZE 🔒 - QUEUE_
SIZES 🔒 - VIRTIO_
PVCLOCK_ 🔒CLOCKSOURCE_ RATING - VIRTIO_
PVCLOCK_ 🔒F_ CLOCKSOURCE_ RATING - VIRTIO_
PVCLOCK_ 🔒F_ INJECT_ SLEEP - VIRTIO_
PVCLOCK_ 🔒F_ TSC_ STABLE - VIRTIO_
PVCLOCK_ 🔒S_ IOERR - VIRTIO_
PVCLOCK_ 🔒S_ OK
Functions§
- freq_
scale_ 🔒shift - Calculate a (multiplier, shift) pair for scaled math of clocks.
The values are passed on to
pvclock_scale_deltain the guest kernel and satisfy the following (approximate) equality:n * scaled_hz / base_hz ~= ((n << shift) * multiplier) >> 32The logic here is roughly based onkvm_get_time_scale(but simplified as we can use u128). - pvclock_
response_ 🔒error_ from_ anyhow - read_
clock_ 🔒counter - run_
main_ 🔒worker - A worker to process PvClockCommand requests
- run_
stub_ 🔒worker - A stub worker to respond any requests when the device is inactive.