From: sashiko-bot@kernel.org
To: "David Woodhouse" <dwmw2@infradead.org>, kvm@vger.kernel.org
Subject: Re: [PATCH v12 11/24] KVM: x86: Activate master clock from kvm_arch_init_vm()
Date: Mon, 09 Nov 2026 01:56:56 +0000 [thread overview]
Message-ID: <sashiko-outbox-204336@kernel.org> (raw)
In-Reply-To: <20261109012112.3415328-12-dwmw2@infradead.org>
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Medium] KVM: x86: host-guest clock divergence in
__get_kvmclock_master_clock()
- [Low] KVM: x86: dead initial TSC generation stores in
kvm_arch_init_vm()
--
commit 862c03c2a3fcfa08f8c8dedc05fb896a0f4d58c9
Author: David Woodhouse <dwmw@amazon.co.uk>
KVM: x86: Activate master clock from kvm_arch_init_vm()
This commit initializes the master clock snapshot in kvm_arch_init_vm(),
adds a sanity check against raw clock divergence in
__get_kvmclock_master_clock(), and refreshes the master clock when the
first vCPU is created.
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index a357efbf1d941..4afafe7ed8b8a 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
[ ... ]
> @@ -1927,13 +1932,34 @@ static bool __get_kvmclock_master_clock(struct kvm *kvm,
> u64 tsc_delta = data->host_tsc - ka->master_cycle_now;
>
> tsc_delta = kvm_scale_tsc(tsc_delta, ka->master_tsc_scaling_ratio);
> - data->clock = hv_clock.system_time +
> - pvclock_scale_delta(tsc_delta,
> - hv_clock.tsc_to_system_mul,
> - hv_clock.tsc_shift);
> + clock = hv_clock.system_time +
> + pvclock_scale_delta(tsc_delta,
> + hv_clock.tsc_to_system_mul,
> + hv_clock.tsc_shift);
> } else {
> - data->clock = __pvclock_read_cycles(&hv_clock, data->host_tsc);
> + clock = __pvclock_read_cycles(&hv_clock, data->host_tsc);
> }
> +
> + /*
> + * Sanity-check the snapshot: if the elapsed time it computes from
> + * the host TSC disagrees with the raw clock by more than a second,
> + * the TSC was reset (suspend/resume — possibly re-inited by
> + * firmware to an arbitrary value, including an underflowing one
> + * below master_cycle_now) while nothing refreshed the snapshot.
> + * That can happen while the VM has no vCPUs, since both the
> + * resume compensation and the clocksource notifier work through
> + * vCPUs. Use the fallback clock rather than returning a
> + * discontinuity flagged KVM_CLOCK_TSC_STABLE.
> + */
> + if (unlikely(abs((s64)(clock - hv_clock.system_time) -
> + (get_kvmclock_base_ns() - ka->master_kernel_ns)) >
> + NSEC_PER_SEC))
> + return false;
[Severity: Medium]
Can this sanity check trigger while vCPUs are active and cause a 1-second
divergence between host-side get_kvmclock() and guest pvclock?
Although the comment describes the no-vCPU window, this check runs even
when vCPUs exist and ka->use_master_clock remains true. While the master
clock is active, ka->master_cycle_now and ka->master_kernel_ns are not
re-anchored. Because tk_core.timekeeper.tkr_raw uses a 22- or 23-bit
multiplier from clocks_calc_mult_shift() whereas ka->master_tsc_mul uses a
32-bit multiplier from kvm_get_time_scale() (plus intermediate rounding in
kvm_scale_tsc() when TSC scaling is active), the two elapsed times drift
apart over long uninterrupted uptime until their difference exceeds
NSEC_PER_SEC.
Once that threshold is crossed, __get_kvmclock_master_clock() returns
false, causing get_kvmclock() (and KVM_GET_CLOCK) to jump by at least a
second to get_kvmclock_base_ns() + ka->kvmclock_offset and drop
KVM_CLOCK_TSC_STABLE, KVM_CLOCK_REALTIME, and KVM_CLOCK_HOST_TSC, while
leaving data->host_tsc modified from the earlier
kvm_get_walltime_and_clockread() call. Meanwhile, kvm_guest_time_update()
continues populating the guest's pvclock from the master clock snapshot
with PVCLOCK_TSC_STABLE_BIT set.
Should this check be gated on having no online/created vCPUs, or should
ka->master_cycle_now and ka->master_kernel_ns be refreshed when the first
vCPU is created so no fallback check is needed in
__get_kvmclock_master_clock()?
[ ... ]
> @@ -10271,14 +10314,46 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
> kvm->arch.cur_tsc_scaling_ratio = kvm_caps.default_tsc_scaling_ratio;
>
> raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags);
> +
> + /*
> + * Establish an initial TSC generation so that the master clock
> + * snapshot taken below is immediately valid and KVM_GET_CLOCK
> + * works before any vCPU exists. The snapshot is refreshed again
> + * when the first vCPU is created, in case the host clocksource
> + * changed (and changed back) in between: pvclock_gtod_update_fn()
> + * does not notify a VM with no vCPUs.
> + *
> + * This generation is deliberately not matchable: cur_tsc_khz is
> + * left at zero, which no vCPU frequency ever equals, so the first
> + * vCPU opens its own generation with its TSC starting at zero,
> + * exactly as it always has. Letting it match would make the first
> + * vCPU's TSC start at the cycles elapsed since KVM_CREATE_VM — a
> + * silent guest-visible change over an unbounded window — and
> + * would hand it this offset verbatim even when a host suspend
> + * reset the TSC in between, since the backwards-TSC compensation
> + * in kvm_arch_enable_virtualization_cpu() detects the jump only
> + * through existing vCPUs.
> + */
> +#ifdef CONFIG_X86_64
> + if (!kvm_get_time_and_clockread(&kvmclock_ns, &kvmclock_host_tsc))
> +#endif
> + {
> + /*
> + * If not simultaneous, we want the TSC to be zero slightly
> + * *after* the kvmclock is zero.
> + */
> + kvmclock_ns = get_kvmclock_base_ns();
> + kvmclock_host_tsc = rdtsc();
> + }
> + kvm->arch.cur_tsc_write = 0;
> + kvm->arch.cur_tsc_offset = -(s64)kvmclock_host_tsc;
> + kvm->arch.cur_tsc_nsec = kvmclock_ns;
> + kvm->arch.cur_tsc_generation = 1;
> + kvm->arch.kvmclock_offset = -kvmclock_ns;
> +
> pvclock_update_vm_gtod_copy(kvm);
> raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags);
[Severity: Low]
Are the stores to cur_tsc_write, cur_tsc_offset, cur_tsc_nsec, and
cur_tsc_generation (along with the kvmclock_host_tsc read) dead code?
pvclock_update_vm_gtod_copy() takes its own snapshot into master_kernel_ns
and master_cycle_now and does not read any of the cur_tsc_* fields.
Because cur_tsc_khz is left at 0 and user_set_tsc is false, no caller can
match or consume this initial generation before the first vCPU's
__kvm_synchronize_tsc() call runs with matched == false and overwrites
cur_tsc_generation, cur_tsc_nsec, cur_tsc_write, and cur_tsc_offset.
Also, the commit message states that this patch makes
pvclock_update_vm_gtod_copy() succeed in kvm_arch_init_vm(), but earlier
commits in the series (commit "KVM: x86: Replace nr_vcpus_matched_tsc
count with all_vcpus_matched_tsc bool" and commit "KVM: x86: Allow KVM
master clock mode when TSCs are offset from each other") already
initialized all_vcpus_matched_tsc, cur_tsc_scaling_ratio, and
all_vcpus_matched_freq in kvm_arch_init_vm().
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261109012112.3415328-1-dwmw2@infradead.org?part=11
next prev parent reply other threads:[~2026-11-09 1:56 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-09 1:20 [PATCH v12 00/24] KVM: x86: Cleaning up the KVM clock mess, part 2 David Woodhouse
2026-11-09 1:20 ` [PATCH v12 01/24] KVM: x86: Improve synchronization in kvm_synchronize_tsc() David Woodhouse
2026-11-09 1:20 ` [PATCH v12 02/24] KVM: x86: Kill last_tsc_{nsec,write,offset} fields David Woodhouse
2026-11-09 1:20 ` [PATCH v12 03/24] KVM: x86: Replace nr_vcpus_matched_tsc count with all_vcpus_matched_tsc bool David Woodhouse
2026-11-09 1:53 ` sashiko-bot
2026-11-09 1:20 ` [PATCH v12 04/24] KVM: x86: Allow KVM master clock mode when TSCs are offset from each other David Woodhouse
2026-11-09 1:45 ` sashiko-bot
2026-11-09 1:20 ` [PATCH v12 05/24] KVM: x86: Factor out kvm_use_master_clock() David Woodhouse
2026-11-09 1:20 ` [PATCH v12 06/24] KVM: x86: Avoid gratuitous global clock updates David Woodhouse
2026-11-09 1:20 ` [PATCH v12 07/24] KVM: x86: Avoid redundant masterclock updates from multiple vCPUs David Woodhouse
2026-11-09 1:53 ` sashiko-bot
2026-11-09 1:20 ` [PATCH v12 08/24] KVM: x86: Re-synchronize TSC after KVM_SET_TSC_KHZ David Woodhouse
2026-11-09 1:53 ` sashiko-bot
2026-11-09 6:24 ` kernel test robot
2026-11-10 5:21 ` kernel test robot
2026-11-09 1:20 ` [PATCH v12 09/24] KVM: x86: Cache host vclock_mode for masterclock eligibility checks David Woodhouse
2026-11-09 1:20 ` [PATCH v12 10/24] KVM: x86: Remove pvclock_gtod_data and private timekeeping code David Woodhouse
2026-11-09 1:20 ` [PATCH v12 11/24] KVM: x86: Activate master clock from kvm_arch_init_vm() David Woodhouse
2026-11-09 1:56 ` sashiko-bot [this message]
2026-11-09 1:20 ` [PATCH v12 12/24] UAPI: x86: Move pvclock-abi to UAPI for x86 platforms David Woodhouse
2026-11-09 1:20 ` [PATCH v12 13/24] KVM: selftests: Use UAPI pvclock-abi.h in xen_shinfo_test David Woodhouse
2026-11-09 1:21 ` [PATCH v12 14/24] KVM: x86: Add KVM_[GS]ET_CLOCK_GUEST for accurate KVM clock migration David Woodhouse
2026-11-09 1:53 ` sashiko-bot
2026-11-09 1:21 ` [PATCH v12 15/24] KVM: selftests: Add library helpers for clock and TSC-offset ioctls David Woodhouse
2026-11-09 1:21 ` [PATCH v12 16/24] KVM: x86: Add KVM_VCPU_TSC_SCALE and fix the documentation on TSC migration David Woodhouse
2026-11-09 1:44 ` sashiko-bot
2026-11-09 1:21 ` [PATCH v12 17/24] KVM: selftests: Add KVM/PV clock selftest to prove timer correction David Woodhouse
2026-11-09 1:21 ` [PATCH v12 18/24] KVM: selftests: Add master clock offset test David Woodhouse
2026-11-09 1:47 ` sashiko-bot
2026-11-09 1:21 ` [PATCH v12 19/24] KVM: selftests: Add Xen/generic CPUID timing leaf test David Woodhouse
2026-11-09 1:21 ` [PATCH v12 20/24] KVM: selftests: Add Xen runstate migration test David Woodhouse
2026-11-09 1:21 ` [PATCH v12 21/24] KVM: selftests: Test that the first user TSC write is honoured exactly David Woodhouse
2026-11-09 1:21 ` [PATCH v12 22/24] KVM: x86/xen: Drop open-coded fallback clock read in kvm_xen_start_timer() David Woodhouse
2026-11-09 1:21 ` [PATCH v12 23/24] KVM: x86: Use a single time snapshot in kvm_vm_ioctl_set_clock() David Woodhouse
2026-11-09 1:21 ` [PATCH v12 24/24] KVM: x86: Keep master clock for guests using legacy MSR_KVM_SYSTEM_TIME David Woodhouse
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-204336@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=dwmw2@infradead.org \
--cc=kvm@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.