[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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



On Fri, Jul 03, 2026, David Woodhouse wrote:
> From: David Woodhouse <dwmw@xxxxxxxxxxxx>
> 
> 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: stable@xxxxxxxxxxxxxxx

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

> 
> Signed-off-by: David Woodhouse <dwmw@xxxxxxxxxxxx>
> ---
>  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);



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.