Module pvclock

Source
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:

  1. 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.
  1. 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§

MainWorkerReturn 🔒
PvClock
A struct that represents virtio-pvclock device.
PvClockState 🔒
Serializable part of the PvClock struct which will be used by the virtio_snapshot / restore.
PvClockWorker 🔒
Worker struct for the virtio-pvclock device.
PvClockWorkerSnapshot 🔒
The unique data retained by PvClockWorker which can be used to re-create an identical worker.
PvclockInstant 🔒
Represents a moment in time including the TSC counter value at that time.
PvclockSharedData 🔒
StubWorkerReturn 🔒
virtio_pvclock_config 🔒
virtio_pvclock_set_pvclock_page_req 🔒

Enums§

PvClockWorkerState 🔒
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_delta in the guest kernel and satisfy the following (approximate) equality: n * scaled_hz / base_hz ~= ((n << shift) * multiplier) >> 32 The logic here is roughly based on kvm_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.