Kernel KVM virtualization development
 help / color / mirror / Atom feed
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

  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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox