diff mbox series

[v2] KVM: x86: allow TSC to differ by NTP correction bounds without TSC scaling

Message ID 20200616114741.GA298183@fuller.cnet (mailing list archive)
State New, archived
Headers show
Series [v2] KVM: x86: allow TSC to differ by NTP correction bounds without TSC scaling | expand

Commit Message

Marcelo Tosatti June 16, 2020, 11:47 a.m. UTC
The Linux TSC calibration procedure is subject to small variations
(its common to see +-1 kHz difference between reboots on a given CPU, for example).

So migrating a guest between two hosts with identical processor can fail, in case
of a small variation in calibrated TSC between them.

Without TSC scaling, the current kernel interface will either return an error
(if user_tsc_khz <= tsc_khz) or enable TSC catchup mode.

This change enables the following TSC tolerance check to
accept KVM_SET_TSC_KHZ within tsc_tolerance_ppm (which is 250ppm by default).

        /*
         * Compute the variation in TSC rate which is acceptable
         * within the range of tolerance and decide if the
         * rate being applied is within that bounds of the hardware
         * rate.  If so, no scaling or compensation need be done.
         */
        thresh_lo = adjust_tsc_khz(tsc_khz, -tsc_tolerance_ppm);
        thresh_hi = adjust_tsc_khz(tsc_khz, tsc_tolerance_ppm);
        if (user_tsc_khz < thresh_lo || user_tsc_khz > thresh_hi) {
                pr_debug("kvm: requested TSC rate %u falls outside tolerance [%u,%u]\n", user_tsc_khz, thresh_lo, thresh_hi);
                use_scaling = 1;
        }

NTP daemon in the guest can correct this difference (NTP can correct upto 500ppm).

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

---

v2: improve changelog (Paolo Bonzini)

Comments

Paolo Bonzini June 23, 2020, 9:56 a.m. UTC | #1
On 16/06/20 13:47, Marcelo Tosatti wrote:
> v2: improve changelog (Paolo Bonzini)
> 
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 3156e25..39a6664 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -1772,6 +1772,8 @@ static int set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
>  
>  	/* TSC scaling supported? */
>  	if (!kvm_has_tsc_control) {
> +		if (!scale)
> +			return 0;

This cannot happen, there is an "if (!scale) right above.

>  		if (user_tsc_khz > tsc_khz) {
>  			vcpu->arch.tsc_catchup = 1;
>  			vcpu->arch.tsc_always_catchup = 1;
> @@ -4473,7 +4475,8 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
>  		r = -EINVAL;
>  		user_tsc_khz = (u32)arg;
>  
> -		if (user_tsc_khz >= kvm_max_guest_tsc_khz)
> +		if (kvm_has_tsc_control &&
> +		    user_tsc_khz >= kvm_max_guest_tsc_khz)
>  			goto out;
>  
>  		if (user_tsc_khz == 0)
> 

Queued this second hunk.

Paolo
diff mbox series

Patch

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 3156e25..39a6664 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1772,6 +1772,8 @@  static int set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
 
 	/* TSC scaling supported? */
 	if (!kvm_has_tsc_control) {
+		if (!scale)
+			return 0;
 		if (user_tsc_khz > tsc_khz) {
 			vcpu->arch.tsc_catchup = 1;
 			vcpu->arch.tsc_always_catchup = 1;
@@ -4473,7 +4475,8 @@  long kvm_arch_vcpu_ioctl(struct file *filp,
 		r = -EINVAL;
 		user_tsc_khz = (u32)arg;
 
-		if (user_tsc_khz >= kvm_max_guest_tsc_khz)
+		if (kvm_has_tsc_control &&
+		    user_tsc_khz >= kvm_max_guest_tsc_khz)
 			goto out;
 
 		if (user_tsc_khz == 0)