On Tue, Jul 28, 2026, David Woodhouse wrote:
> From: David Woodhouse <[email protected]>
>
> Previously, a guest writing different TSC values on different vCPUs could
> force KVM out of master clock mode. With this change, only a frequency
> mismatch disables master clock. The only ways for non-master-clock mode
> to happen now are archaic hardware without a TSC-based clocksource, a
> VMM that sets different TSC frequencies across vCPUs, or a guest using
> the legacy MSR_KVM_SYSTEM_TIME (which could be addressed in future by
> simply updating tsc_timestamp more frequently rather than falling out of
> master clock mode entirely).
>
> Running at a different frequency would lead to a systemic skew between
> the clock(s) as observed by different vCPUs due to arithmetic precision
> in the scaling. So that should indeed force the clock to be based on the
> host's CLOCK_MONOTONIC_RAW instead of being in masterclock mode where it
> is defined by the guest TSC.
>
> But when the vCPUs merely have a different TSC *offset*, that's not a
> problem. The offset is applied to that vCPU's kvmclock->tsc_timestamp
> field, and it all comes out in the wash.
It's not though? The value stored in kvmclock->tsc_timestamp is per-VM, not
per-vCPU, when using the master clock. It's a little easier to see once the
master clock TSC isn't shoved into host_tsc:
do {
seq = read_seqcount_begin(&ka->pvclock_sc);
use_master_clock = ka->use_master_clock;
if (!use_master_clock)
continue;
if (!kvm_get_time_and_clockread(&kernel_ns, &host_tsc)) {
use_master_clock = false;
continue;
}
master_tsc = ka->master_cycle_now;
master_ns = ka->master_kernel_ns;
} while (read_seqcount_retry(&ka->pvclock_sc, seq));
...
if (use_master_clock) {
hv_clock.tsc_timestamp = kvm_read_l1_tsc(v, master_tsc);
hv_clock.system_time = master_ns + v->kvm->arch.kvmclock_offset;
} else {
hv_clock.tsc_timestamp = tsc_timestamp;
hv_clock.system_time = kernel_ns + v->kvm->arch.kvmclock_offset;
}
To allow different offsets, KVM would need to track a per-vCPU offset to the
master clock and apply that in kvm_guest_time_update() (and maybe other
places?).
Which is doable, but it's not clear to me why we'd want to support that (though
I haven't fully processed the back half ot his series, so it's very possible I'm
missing something obvious).