Re: [PATCH v6 15/36] KVM: x86: Fix compute_guest_tsc() to handle negative time deltas

Sean Christopherson <[email protected]>
Newsgroups org.xenproject.lists.xen-devel,org.kernel.vger.kvm,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel,org.kernel.vger.linux-kselftest
Message-ID <[email protected]>
On Fri, Jul 03, 2026, David Woodhouse wrote:
> From: David Woodhouse <[email protected]>
> 
> The compute_guest_tsc() function computes the guest TSC at a given
> kernel_ns timestamp. When the master clock reference point
> (master_kernel_ns) is earlier than vcpu->arch.this_tsc_nsec, the delta
> is negative. Since pvclock_scale_delta() takes a u64, the negative
> value wraps to a huge positive number, producing a wildly wrong result.
> 
> Handle negative deltas explicitly by negating the delta, scaling it,
> and subtracting from this_tsc_write.

Does this need 

  Cc: [email protected]

or is this a "technically a bug fix, but can't happen in practice" sort of thing?

> 
> Signed-off-by: David Woodhouse <[email protected]>
> ---
>  arch/x86/kvm/x86.c | 20 +++++++++++++++-----
>  1 file changed, 15 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 376b8dc2ade9..55fb19fb7a88 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -2588,11 +2588,21 @@ static int kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz)
>  
>  static u64 compute_guest_tsc(struct kvm_vcpu *vcpu, s64 kernel_ns)
>  {
> -	u64 tsc = pvclock_scale_delta(kernel_ns-vcpu->arch.this_tsc_nsec,
> -				      vcpu->arch.virtual_tsc_mult,
> -				      vcpu->arch.virtual_tsc_shift);
> -	tsc += vcpu->arch.this_tsc_write;
> -	return tsc;
> +	s64 delta_ns = kernel_ns - vcpu->arch.this_tsc_nsec;
> +	u64 tsc;
> +
> +	/* Handle negative deltas gracefully (master clock ref may be earlier) */
> +	if (delta_ns < 0) {
> +		tsc = pvclock_scale_delta(-delta_ns,
> +					  vcpu->arch.virtual_tsc_mult,
> +					  vcpu->arch.virtual_tsc_shift);
> +		return vcpu->arch.this_tsc_write - tsc;
> +	}
> +
> +	tsc = pvclock_scale_delta(delta_ns,
> +				  vcpu->arch.virtual_tsc_mult,
> +				  vcpu->arch.virtual_tsc_shift);
> +	return vcpu->arch.this_tsc_write + tsc;

To cut down on the duplicate code, and IMO to make it easier to identify the
differences, how about this?

	s64 delta_ns = kernel_ns - vcpu->arch.this_tsc_nsec;
	u64 tsc;
	
	/* Handle negative deltas gracefully (master clock ref may be earlier) */
	tsc = pvclock_scale_delta(abs(-delta_ns),
				  vcpu->arch.virtual_tsc_mult,
				  vcpu->arch.virtual_tsc_shift);

	return vcpu->arch.this_tsc_write + (delta_ns >= 0 ? tsc : -tsc);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.