All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/9] KVM: lapic: Fix a variety of timer adv issues
@ 2019-04-16 20:32 Sean Christopherson
  2019-04-16 20:32 ` [PATCH v3 1/9] KVM: lapic: Hard cap the auto-calculated timer advancement Sean Christopherson
                   ` (9 more replies)
  0 siblings, 10 replies; 20+ messages in thread
From: Sean Christopherson @ 2019-04-16 20:32 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář; +Cc: kvm, Liran Alon, Wanpeng Li

The recent change to automatically calculate lapic_timer_advance_ns
introduced a handful of gnarly bugs, and also exposed a latent bug by
virtue of the advancement logic being enabled by default.  Inspection
and debug revealed several other opportunities for minor improvements.

The primary issue is that the auto-tuning of lapic_timer_advance_ns is
completely unbounded, e.g. there's nothing in the logic that prevents the
advancement from creeping up to hundreds of milliseconds.  Adjusting the
timers by large amounts creates major discrepancies in the guest, e.g. a
timer that was configured to fire after multiple milliseconds may arrive
before the guest executes a single instruction.  While technically correct
from a time perspective, it breaks a reasonable assumption from the guest
that it can execute some number of instructions between timer events.

The other major issue is that the advancement is global, while TSC scaling
is done on a per-vCPU basic.  Adjusting the advancement at runtime
exacerbates this as there is no protection against multiple vCPUs and/or
multiple VMs concurrently modifying the advancement value, e.g. it can
effectively become corrupted or never stabilize due to getting bounced all
over tarnation.

As for the latent bug, when timer advancement was applied to the hv_timer,
i.e. the VMX preemption timer, the logic to trigger wait_for_lapic_timer()
was not updated.  As a result, a timer interrupt emulated via the hv_timer
can easily arrive too early from a *time* perspective, as opposed to
simply arriving early from a "number of instructions executed" perspective.

v3:
 - Split the refactoring of start_hv_timer() and ->set_hv_timer
   into three separate patches instead of attempting to do a big
   refactor in a single patch to fix three separate issues.
    - Explicitly cancel the hv timer to avoid
    - Use a param for "expired" instead of overloading the return
      value of ->set_hv_timer().
    - Check for a pending non-periodic in restart_apic_timer(). [Liran]
 - Add more Reviewed-by tags.

v2:
 - https://patchwork.kernel.org/cover/10903613/
 - Add explicit param to control automatic tuning. [Liran]
 - Document the effect of per-vCPU tracking on the module params.
 - Use fancy math to convert guest clockcycles to host nanoseconds
   instead of brute forcing the delay with a for loop. [Liran]
 - Refactor start_hv_timer()'s return semantics to move the "expired
   timer" handling up a level. [Liran and Paolo]
 - Add Liran's Reviewed-by tags.

v1: https://patchwork.kernel.org/cover/10899101/

Sean Christopherson (9):
  KVM: lapic: Hard cap the auto-calculated timer advancement
  KVM: lapic: Convert guest TSC to host time domain when delaying
  KVM: lapic: Track lapic timer advance per vCPU
  KVM: lapic: Allow user to disable auto-tuning of timer advancement
  KVM: lapic: Busy wait for timer to expire when using hv_timer
  KVM: lapic: Explicitly cancel the hv timer if it's pre-expired
  KVM: lapic: Refactor ->set_hv_timer to use an explicit expired param
  KVM: lapic: Check for a pending timer intr prior to start_hv_timer()
  KVM: VMX: Skip delta_tsc shift-and-divide if the dividend is zero

 arch/x86/include/asm/kvm_host.h |  3 +-
 arch/x86/kvm/lapic.c            | 81 +++++++++++++++++++++------------
 arch/x86/kvm/lapic.h            |  5 +-
 arch/x86/kvm/vmx/vmx.c          | 15 +++---
 arch/x86/kvm/x86.c              | 11 +++--
 arch/x86/kvm/x86.h              |  2 -
 6 files changed, 73 insertions(+), 44 deletions(-)

-- 
2.21.0


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 1/9] KVM: lapic: Hard cap the auto-calculated timer advancement
  2019-04-16 20:32 [PATCH v3 0/9] KVM: lapic: Fix a variety of timer adv issues Sean Christopherson
@ 2019-04-16 20:32 ` Sean Christopherson
  2019-04-17 12:57   ` Paolo Bonzini
  2019-04-16 20:32 ` [PATCH v3 2/9] KVM: lapic: Convert guest TSC to host time domain when delaying Sean Christopherson
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Sean Christopherson @ 2019-04-16 20:32 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář; +Cc: kvm, Liran Alon, Wanpeng Li

To minimize the latency of timer interrupts as observed by the guest,
KVM adjusts the values it programs into the host timers to account for
the host's overhead of programming and handling the timer event.  Now
that the timer advancement is automatically tuned during runtime, it's
effectively unbounded by default, e.g. if KVM is running as L1 the
advancement can measure in hundreds of milliseconds.

Place a somewhat arbitrary hard cap of 5000ns on the auto-calculated
advancement, as large advancements can break reasonable assumptions of
the guest, e.g. that a timer configured to fire after 1ms won't arrive
on the next instruction.  Although KVM busy waits to mitigate the timer
event arriving too early, complications can arise when shifting the
interrupt too far, e.g. vmx.flat/interrupt in kvm-unit-tests will fail
when its "host" exits on interrupts (because the INTR is injected before
the gets executes STI+HLT).  Arguably the unit test is "broken" in the
sense that delaying the timer interrupt by 1ms doesn't technically
guarantee the interrupt will arrive after STI+HLT, but it's a reasonable
assumption that KVM should support.

Furthermore, an unbounded advancement also effectively unbounds the time
spent busy waiting, e.g. if the guest programs a timer with a very large
delay.

Arguably the advancement logic could simply be disabled when running as
L1, but KVM needs to bound the advancement time regardless, e.g. if the
TSC is unstable and the calculations get wildly out of whack.  And
allowing the advancement when running as L1 is a good stress test of
sorts for the logic.

Cc: Liran Alon <liran.alon@oracle.com>
Cc: Wanpeng Li <wanpengli@tencent.com>
Fixes: 3b8a5df6c4dc6 ("KVM: LAPIC: Tune lapic_timer_advance_ns automatically")
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/kvm/lapic.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 9bf70cf84564..92446cba9b24 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -74,6 +74,7 @@ static bool lapic_timer_advance_adjust_done = false;
 #define LAPIC_TIMER_ADVANCE_ADJUST_DONE 100
 /* step-by-step approximation to mitigate fluctuation */
 #define LAPIC_TIMER_ADVANCE_ADJUST_STEP 8
+#define LAPIC_TIMER_ADVANCE_MAX_NS	5000
 
 static inline int apic_test_vector(int vec, void *bitmap)
 {
@@ -1522,6 +1523,10 @@ void wait_lapic_expire(struct kvm_vcpu *vcpu)
 		}
 		if (abs(guest_tsc - tsc_deadline) < LAPIC_TIMER_ADVANCE_ADJUST_DONE)
 			lapic_timer_advance_adjust_done = true;
+		if (unlikely(lapic_timer_advance_ns > LAPIC_TIMER_ADVANCE_MAX_NS)) {
+			lapic_timer_advance_ns = LAPIC_TIMER_ADVANCE_MAX_NS;
+			lapic_timer_advance_adjust_done = true;
+		}
 	}
 }
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 2/9] KVM: lapic: Convert guest TSC to host time domain when delaying
  2019-04-16 20:32 [PATCH v3 0/9] KVM: lapic: Fix a variety of timer adv issues Sean Christopherson
  2019-04-16 20:32 ` [PATCH v3 1/9] KVM: lapic: Hard cap the auto-calculated timer advancement Sean Christopherson
@ 2019-04-16 20:32 ` Sean Christopherson
  2019-04-17 12:56   ` Paolo Bonzini
  2019-04-16 20:32 ` [PATCH v3 3/9] KVM: lapic: Track lapic timer advance per vCPU Sean Christopherson
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Sean Christopherson @ 2019-04-16 20:32 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář; +Cc: kvm, Liran Alon, Wanpeng Li

To minimize the latency of timer interrupts as observed by the guest,
KVM adjusts the values it programs into the host timers to account for
the host's overhead of programming and handling the timer event.  In
the event that the adjustments are too aggressive, i.e. the timer fires
earlier than the guest expects, KVM busy waits immediately prior to
entering the guest.

Currently, KVM manually converts the delay from nanoseconds to clock
cycles.  But, the conversion is done in the guest's time domain, while
the delay occurs in the host's time domain, i.e. the delay may not be
accurate and could wait too little or too long.

Convert the delay from guest clock cycles to host nanoseconds and use
ndelay() instead of __delay() to provide more accurate timing.  This
also avoids the need to convert lapic_timer_advance_ns, which is used
to cap the delay, to guest clock cycles.

Cc: Liran Alon <liran.alon@oracle.com>
Cc: Wanpeng Li <wanpengli@tencent.com>
Reviewed-by: Liran Alon <liran.alon@oracle.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/kvm/lapic.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 92446cba9b24..5891c0badfa6 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1502,10 +1502,12 @@ void wait_lapic_expire(struct kvm_vcpu *vcpu)
 	guest_tsc = kvm_read_l1_tsc(vcpu, rdtsc());
 	trace_kvm_wait_lapic_expire(vcpu->vcpu_id, guest_tsc - tsc_deadline);
 
-	/* __delay is delay_tsc whenever the hardware has TSC, thus always.  */
-	if (guest_tsc < tsc_deadline)
-		__delay(min(tsc_deadline - guest_tsc,
-			nsec_to_cycles(vcpu, lapic_timer_advance_ns)));
+	/* ndelay uses delay_tsc whenever the hardware has TSC, thus always. */
+	if (guest_tsc < tsc_deadline) {
+		ns = (tsc_deadline - guest_tsc) * 1000000ULL;
+		do_div(ns, vcpu->arch.virtual_tsc_khz);
+		ndelay(min_t(u32, ns, lapic_timer_advance_ns));
+	}
 
 	if (!lapic_timer_advance_adjust_done) {
 		/* too early */
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 3/9] KVM: lapic: Track lapic timer advance per vCPU
  2019-04-16 20:32 [PATCH v3 0/9] KVM: lapic: Fix a variety of timer adv issues Sean Christopherson
  2019-04-16 20:32 ` [PATCH v3 1/9] KVM: lapic: Hard cap the auto-calculated timer advancement Sean Christopherson
  2019-04-16 20:32 ` [PATCH v3 2/9] KVM: lapic: Convert guest TSC to host time domain when delaying Sean Christopherson
@ 2019-04-16 20:32 ` Sean Christopherson
  2019-04-16 20:32 ` [PATCH v3 4/9] KVM: lapic: Allow user to disable auto-tuning of timer advancement Sean Christopherson
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 20+ messages in thread
From: Sean Christopherson @ 2019-04-16 20:32 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář; +Cc: kvm, Liran Alon, Wanpeng Li

Automatically adjusting the globally-shared timer advancement could
corrupt the timer, e.g. if multiple vCPUs are concurrently adjusting
the advancement value.  That could be partially fixed by using a local
variable for the arithmetic, but it would still be susceptible to a
race when setting timer_advance_adjust_done.

And because virtual_tsc_khz and tsc_scaling_ratio are per-vCPU, the
correct calibration for a given vCPU may not apply to all vCPUs.

Furthermore, lapic_timer_advance_ns is marked __read_mostly, which is
effectively violated when finding a stable advancement takes an extended
amount of timer.

Opportunistically change the definition of lapic_timer_advance_ns to
a u32 so that it matches the style of struct kvm_timer.  Explicitly
pass the param to kvm_create_lapic() so that it doesn't have to be
exposed to lapic.c, thus reducing the probability of unintentionally
using the global value instead of the per-vCPU value.

Fixes: 3b8a5df6c4dc6 ("KVM: LAPIC: Tune lapic_timer_advance_ns automatically")
Cc: Liran Alon <liran.alon@oracle.com>
Cc: Wanpeng Li <wanpengli@tencent.com>
Reviewed-by: Liran Alon <liran.alon@oracle.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/kvm/lapic.c   | 34 ++++++++++++++++++----------------
 arch/x86/kvm/lapic.h   |  4 +++-
 arch/x86/kvm/vmx/vmx.c |  4 +++-
 arch/x86/kvm/x86.c     |  7 +++----
 arch/x86/kvm/x86.h     |  2 --
 5 files changed, 27 insertions(+), 24 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 5891c0badfa6..3cd62edf8084 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -70,7 +70,6 @@
 #define APIC_BROADCAST			0xFF
 #define X2APIC_BROADCAST		0xFFFFFFFFul
 
-static bool lapic_timer_advance_adjust_done = false;
 #define LAPIC_TIMER_ADVANCE_ADJUST_DONE 100
 /* step-by-step approximation to mitigate fluctuation */
 #define LAPIC_TIMER_ADVANCE_ADJUST_STEP 8
@@ -1486,6 +1485,7 @@ static bool lapic_timer_int_injected(struct kvm_vcpu *vcpu)
 void wait_lapic_expire(struct kvm_vcpu *vcpu)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
+	u32 timer_advance_ns = apic->lapic_timer.timer_advance_ns;
 	u64 guest_tsc, tsc_deadline, ns;
 
 	if (!lapic_in_kernel(vcpu))
@@ -1506,35 +1506,37 @@ void wait_lapic_expire(struct kvm_vcpu *vcpu)
 	if (guest_tsc < tsc_deadline) {
 		ns = (tsc_deadline - guest_tsc) * 1000000ULL;
 		do_div(ns, vcpu->arch.virtual_tsc_khz);
-		ndelay(min_t(u32, ns, lapic_timer_advance_ns));
+		ndelay(min_t(u32, ns, timer_advance_ns));
 	}
 
-	if (!lapic_timer_advance_adjust_done) {
+	if (!apic->lapic_timer.timer_advance_adjust_done) {
 		/* too early */
 		if (guest_tsc < tsc_deadline) {
 			ns = (tsc_deadline - guest_tsc) * 1000000ULL;
 			do_div(ns, vcpu->arch.virtual_tsc_khz);
-			lapic_timer_advance_ns -= min((unsigned int)ns,
-				lapic_timer_advance_ns / LAPIC_TIMER_ADVANCE_ADJUST_STEP);
+			timer_advance_ns -= min((u32)ns,
+				timer_advance_ns / LAPIC_TIMER_ADVANCE_ADJUST_STEP);
 		} else {
 		/* too late */
 			ns = (guest_tsc - tsc_deadline) * 1000000ULL;
 			do_div(ns, vcpu->arch.virtual_tsc_khz);
-			lapic_timer_advance_ns += min((unsigned int)ns,
-				lapic_timer_advance_ns / LAPIC_TIMER_ADVANCE_ADJUST_STEP);
+			timer_advance_ns += min((u32)ns,
+				timer_advance_ns / LAPIC_TIMER_ADVANCE_ADJUST_STEP);
 		}
 		if (abs(guest_tsc - tsc_deadline) < LAPIC_TIMER_ADVANCE_ADJUST_DONE)
-			lapic_timer_advance_adjust_done = true;
-		if (unlikely(lapic_timer_advance_ns > LAPIC_TIMER_ADVANCE_MAX_NS)) {
-			lapic_timer_advance_ns = LAPIC_TIMER_ADVANCE_MAX_NS;
-			lapic_timer_advance_adjust_done = true;
+			apic->lapic_timer.timer_advance_adjust_done = true;
+		if (unlikely(timer_advance_ns > LAPIC_TIMER_ADVANCE_MAX_NS)) {
+			timer_advance_ns = LAPIC_TIMER_ADVANCE_MAX_NS;
+			apic->lapic_timer.timer_advance_adjust_done = true;
 		}
+		apic->lapic_timer.timer_advance_ns = timer_advance_ns;
 	}
 }
 
 static void start_sw_tscdeadline(struct kvm_lapic *apic)
 {
-	u64 guest_tsc, tscdeadline = apic->lapic_timer.tscdeadline;
+	struct kvm_timer *ktimer = &apic->lapic_timer;
+	u64 guest_tsc, tscdeadline = ktimer->tscdeadline;
 	u64 ns = 0;
 	ktime_t expire;
 	struct kvm_vcpu *vcpu = apic->vcpu;
@@ -1553,9 +1555,8 @@ static void start_sw_tscdeadline(struct kvm_lapic *apic)
 		ns = (tscdeadline - guest_tsc) * 1000000ULL;
 		do_div(ns, this_tsc_khz);
 		expire = ktime_add_ns(now, ns);
-		expire = ktime_sub_ns(expire, lapic_timer_advance_ns);
-		hrtimer_start(&apic->lapic_timer.timer,
-				expire, HRTIMER_MODE_ABS_PINNED);
+		expire = ktime_sub_ns(expire, ktimer->timer_advance_ns);
+		hrtimer_start(&ktimer->timer, expire, HRTIMER_MODE_ABS_PINNED);
 	} else
 		apic_timer_expired(apic);
 
@@ -2262,7 +2263,7 @@ static enum hrtimer_restart apic_timer_fn(struct hrtimer *data)
 		return HRTIMER_NORESTART;
 }
 
-int kvm_create_lapic(struct kvm_vcpu *vcpu)
+int kvm_create_lapic(struct kvm_vcpu *vcpu, u32 timer_advance_ns)
 {
 	struct kvm_lapic *apic;
 
@@ -2286,6 +2287,7 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu)
 	hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
 		     HRTIMER_MODE_ABS_PINNED);
 	apic->lapic_timer.timer.function = apic_timer_fn;
+	apic->lapic_timer.timer_advance_ns = timer_advance_ns;
 
 	/*
 	 * APIC is created enabled. This will prevent kvm_lapic_set_base from
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index ff6ef9c3d760..3e97f8a68967 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -31,8 +31,10 @@ struct kvm_timer {
 	u32 timer_mode_mask;
 	u64 tscdeadline;
 	u64 expired_tscdeadline;
+	u32 timer_advance_ns;
 	atomic_t pending;			/* accumulated triggered timers */
 	bool hv_timer_in_use;
+	bool timer_advance_adjust_done;
 };
 
 struct kvm_lapic {
@@ -62,7 +64,7 @@ struct kvm_lapic {
 
 struct dest_map;
 
-int kvm_create_lapic(struct kvm_vcpu *vcpu);
+int kvm_create_lapic(struct kvm_vcpu *vcpu, u32 timer_advance_ns);
 void kvm_free_lapic(struct kvm_vcpu *vcpu);
 
 int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 5f90616da275..a3211e3ee679 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -7031,6 +7031,7 @@ static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc)
 {
 	struct vcpu_vmx *vmx;
 	u64 tscl, guest_tscl, delta_tsc, lapic_timer_advance_cycles;
+	struct kvm_timer *ktimer = &vcpu->arch.apic->lapic_timer;
 
 	if (kvm_mwait_in_guest(vcpu->kvm))
 		return -EOPNOTSUPP;
@@ -7039,7 +7040,8 @@ static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc)
 	tscl = rdtsc();
 	guest_tscl = kvm_read_l1_tsc(vcpu, tscl);
 	delta_tsc = max(guest_deadline_tsc, guest_tscl) - guest_tscl;
-	lapic_timer_advance_cycles = nsec_to_cycles(vcpu, lapic_timer_advance_ns);
+	lapic_timer_advance_cycles = nsec_to_cycles(vcpu,
+						    ktimer->timer_advance_ns);
 
 	if (delta_tsc > lapic_timer_advance_cycles)
 		delta_tsc -= lapic_timer_advance_cycles;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 38440316a806..b303a21a2bc2 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -137,9 +137,8 @@ static u32 __read_mostly tsc_tolerance_ppm = 250;
 module_param(tsc_tolerance_ppm, uint, S_IRUGO | S_IWUSR);
 
 /* lapic timer advance (tscdeadline mode only) in nanoseconds */
-unsigned int __read_mostly lapic_timer_advance_ns = 1000;
+static u32 __read_mostly lapic_timer_advance_ns = 1000;
 module_param(lapic_timer_advance_ns, uint, S_IRUGO | S_IWUSR);
-EXPORT_SYMBOL_GPL(lapic_timer_advance_ns);
 
 static bool __read_mostly vector_hashing = true;
 module_param(vector_hashing, bool, S_IRUGO);
@@ -7891,7 +7890,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 	}
 
 	trace_kvm_entry(vcpu->vcpu_id);
-	if (lapic_timer_advance_ns)
+	if (vcpu->arch.apic->lapic_timer.timer_advance_ns)
 		wait_lapic_expire(vcpu);
 	guest_enter_irqoff();
 
@@ -9079,7 +9078,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 
 	if (irqchip_in_kernel(vcpu->kvm)) {
 		vcpu->arch.apicv_active = kvm_x86_ops->get_enable_apicv(vcpu);
-		r = kvm_create_lapic(vcpu);
+		r = kvm_create_lapic(vcpu, lapic_timer_advance_ns);
 		if (r < 0)
 			goto fail_mmu_destroy;
 	} else
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index eda954441213..a470ff0868c5 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -294,8 +294,6 @@ extern u64 kvm_supported_xcr0(void);
 
 extern unsigned int min_timer_period_us;
 
-extern unsigned int lapic_timer_advance_ns;
-
 extern bool enable_vmware_backdoor;
 
 extern struct static_key kvm_no_apic_vcpu;
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 4/9] KVM: lapic: Allow user to disable auto-tuning of timer advancement
  2019-04-16 20:32 [PATCH v3 0/9] KVM: lapic: Fix a variety of timer adv issues Sean Christopherson
                   ` (2 preceding siblings ...)
  2019-04-16 20:32 ` [PATCH v3 3/9] KVM: lapic: Track lapic timer advance per vCPU Sean Christopherson
@ 2019-04-16 20:32 ` Sean Christopherson
  2019-04-17 12:59   ` Paolo Bonzini
  2019-04-16 20:32 ` [PATCH v3 5/9] KVM: lapic: Busy wait for timer to expire when using hv_timer Sean Christopherson
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Sean Christopherson @ 2019-04-16 20:32 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář; +Cc: kvm, Liran Alon, Wanpeng Li

Add a new KVM param, lapic_timer_advance_autotune, to allow userspace
to disable auto-tuning the timer advancement, e.g. to manually tune the
delay.

Note, this does not completely restore the original behavior of
lapic_timer_advance_ns.  Prior to tracking the advancement per vCPU,
which is necessary to support autotuning, userspace could adjust
lapic_timer_advance_ns for *running* vCPU.  With per-vCPU tracking, the
module params are snapshotted at vCPU creation, i.e. applying a new
advancement effectively requires restarting a VM.

Dynamically updating a running vCPU is possible, e.g. a helper could be
added to retrieve the desired delay, choosing between the global module
param and the per-VCPU value depending on whether or not auto-tuning is
(globally) enabled, but introduces a great deal of complexity.  The
wrapper itself is not complex, but understanding and documenting the
effects of dynamically toggling auto-tuning and/or adjusting the timer
advancement is nigh impossible since the behavior would be dependent on
KVM's implementation as well as compiler optimizations.  In other words,
providing stable behavior would require extremely careful consideration
now and in the future.

Given that the expected use of a manually-tuned timer advancement is to
"tune once, run many", use the vastly simpler approach of recognizing
changes to the module params only when creating a new vCPU.

Fixes: 3b8a5df6c4dc6 ("KVM: LAPIC: Tune lapic_timer_advance_ns automatically")
Cc: Liran Alon <liran.alon@oracle.com>
Cc: Wanpeng Li <wanpengli@tencent.com>
Cc: stable@vger.kernel.org
Reviewed-by: Liran Alon <liran.alon@oracle.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/kvm/lapic.c | 4 +++-
 arch/x86/kvm/lapic.h | 3 ++-
 arch/x86/kvm/x86.c   | 6 +++++-
 3 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 3cd62edf8084..37d3489f68c9 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2263,7 +2263,8 @@ static enum hrtimer_restart apic_timer_fn(struct hrtimer *data)
 		return HRTIMER_NORESTART;
 }
 
-int kvm_create_lapic(struct kvm_vcpu *vcpu, u32 timer_advance_ns)
+int kvm_create_lapic(struct kvm_vcpu *vcpu, u32 timer_advance_ns,
+		     bool timer_advance_autotune)
 {
 	struct kvm_lapic *apic;
 
@@ -2288,6 +2289,7 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu, u32 timer_advance_ns)
 		     HRTIMER_MODE_ABS_PINNED);
 	apic->lapic_timer.timer.function = apic_timer_fn;
 	apic->lapic_timer.timer_advance_ns = timer_advance_ns;
+	apic->lapic_timer.timer_advance_adjust_done = !timer_advance_autotune;
 
 	/*
 	 * APIC is created enabled. This will prevent kvm_lapic_set_base from
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 3e97f8a68967..7fa1aed02c14 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -64,7 +64,8 @@ struct kvm_lapic {
 
 struct dest_map;
 
-int kvm_create_lapic(struct kvm_vcpu *vcpu, u32 timer_advance_ns);
+int kvm_create_lapic(struct kvm_vcpu *vcpu, u32 timer_advance_ns,
+		     bool timer_advance_autotune);
 void kvm_free_lapic(struct kvm_vcpu *vcpu);
 
 int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index b303a21a2bc2..60d80e354f62 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -140,6 +140,9 @@ module_param(tsc_tolerance_ppm, uint, S_IRUGO | S_IWUSR);
 static u32 __read_mostly lapic_timer_advance_ns = 1000;
 module_param(lapic_timer_advance_ns, uint, S_IRUGO | S_IWUSR);
 
+static bool __read_mostly lapic_timer_advance_autotune = true;
+module_param(lapic_timer_advance_autotune, bool, S_IRUGO | S_IWUSR);
+
 static bool __read_mostly vector_hashing = true;
 module_param(vector_hashing, bool, S_IRUGO);
 
@@ -9078,7 +9081,8 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 
 	if (irqchip_in_kernel(vcpu->kvm)) {
 		vcpu->arch.apicv_active = kvm_x86_ops->get_enable_apicv(vcpu);
-		r = kvm_create_lapic(vcpu, lapic_timer_advance_ns);
+		r = kvm_create_lapic(vcpu, lapic_timer_advance_ns,
+				     lapic_timer_advance_autotune);
 		if (r < 0)
 			goto fail_mmu_destroy;
 	} else
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 5/9] KVM: lapic: Busy wait for timer to expire when using hv_timer
  2019-04-16 20:32 [PATCH v3 0/9] KVM: lapic: Fix a variety of timer adv issues Sean Christopherson
                   ` (3 preceding siblings ...)
  2019-04-16 20:32 ` [PATCH v3 4/9] KVM: lapic: Allow user to disable auto-tuning of timer advancement Sean Christopherson
@ 2019-04-16 20:32 ` Sean Christopherson
  2019-04-16 20:32 ` [PATCH v3 6/9] KVM: lapic: Explicitly cancel the hv timer if it's pre-expired Sean Christopherson
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 20+ messages in thread
From: Sean Christopherson @ 2019-04-16 20:32 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář; +Cc: kvm, Liran Alon, Wanpeng Li

...now that VMX's preemption timer, i.e. the hv_timer, also adjusts its
programmed time based on lapic_timer_advance_ns.  Without the delay, a
guest can see a timer interrupt arrive before the requested time when
KVM is using the hv_timer to emulate the guest's interrupt.

Fixes: c5ce8235cffa0 ("KVM: VMX: Optimize tscdeadline timer latency")
Cc: <stable@vger.kernel.org>
Cc: Wanpeng Li <wanpengli@tencent.com>
Reviewed-by: Liran Alon <liran.alon@oracle.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/kvm/lapic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 37d3489f68c9..fa2dbca5ad6a 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1455,7 +1455,7 @@ static void apic_timer_expired(struct kvm_lapic *apic)
 	if (swait_active(q))
 		swake_up_one(q);
 
-	if (apic_lvtt_tscdeadline(apic))
+	if (apic_lvtt_tscdeadline(apic) || ktimer->hv_timer_in_use)
 		ktimer->expired_tscdeadline = ktimer->tscdeadline;
 }
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 6/9] KVM: lapic: Explicitly cancel the hv timer if it's pre-expired
  2019-04-16 20:32 [PATCH v3 0/9] KVM: lapic: Fix a variety of timer adv issues Sean Christopherson
                   ` (4 preceding siblings ...)
  2019-04-16 20:32 ` [PATCH v3 5/9] KVM: lapic: Busy wait for timer to expire when using hv_timer Sean Christopherson
@ 2019-04-16 20:32 ` Sean Christopherson
  2019-04-16 20:32 ` [PATCH v3 7/9] KVM: lapic: Refactor ->set_hv_timer to use an explicit expired param Sean Christopherson
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 20+ messages in thread
From: Sean Christopherson @ 2019-04-16 20:32 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář; +Cc: kvm, Liran Alon, Wanpeng Li

Explicitly call cancel_hv_timer() instead of returning %false to coerce
restart_apic_timer() into canceling it by way of start_sw_timer().

Functionally, the existing code is correct in the sense that it doesn't
doing anything visibily wrong, e.g. generate spurious interrupts or miss
an interrupt.  But it's extremely confusing and inefficient, e.g. there
are multiple extraneous calls to apic_timer_expired() that effectively
get dropped due to @timer_pending being %true.

Cc: Wanpeng Li <wanpengli@tencent.com>
Cc: Liran Alon <liran.alon@oracle.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/kvm/lapic.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index fa2dbca5ad6a..bdcf04689a80 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1701,17 +1701,25 @@ static bool start_hv_timer(struct kvm_lapic *apic)
 	hrtimer_cancel(&ktimer->timer);
 
 	/*
-	 * Also recheck ktimer->pending, in case the sw timer triggered in
-	 * the window.  For periodic timer, leave the hv timer running for
-	 * simplicity, and the deadline will be recomputed on the next vmexit.
+	 * To simplify handling the periodic timer, leave the hv timer running
+	 * even if the deadline timer has expired, i.e. rely on the resulting
+	 * VM-Exit to recompute the periodic timer's target expiration.
 	 */
-	if (!apic_lvtt_period(apic) && (r || atomic_read(&ktimer->pending))) {
-		if (r)
+	if (!apic_lvtt_period(apic)) {
+		/*
+		 * Cancel the hv timer if the sw timer fired while the hv timer
+		 * was being programmed, or if the hv timer itself expired.
+		 */
+		if (atomic_read(&ktimer->pending)) {
+			cancel_hv_timer(apic);
+		} else if (r) {
 			apic_timer_expired(apic);
-		return false;
+			cancel_hv_timer(apic);
+		}
 	}
 
-	trace_kvm_hv_timer_state(apic->vcpu->vcpu_id, true);
+	trace_kvm_hv_timer_state(apic->vcpu->vcpu_id, ktimer->hv_timer_in_use);
+
 	return true;
 }
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 7/9] KVM: lapic: Refactor ->set_hv_timer to use an explicit expired param
  2019-04-16 20:32 [PATCH v3 0/9] KVM: lapic: Fix a variety of timer adv issues Sean Christopherson
                   ` (5 preceding siblings ...)
  2019-04-16 20:32 ` [PATCH v3 6/9] KVM: lapic: Explicitly cancel the hv timer if it's pre-expired Sean Christopherson
@ 2019-04-16 20:32 ` Sean Christopherson
  2019-04-17 13:02   ` Paolo Bonzini
  2019-04-16 20:32 ` [PATCH v3 8/9] KVM: lapic: Check for a pending timer intr prior to start_hv_timer() Sean Christopherson
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Sean Christopherson @ 2019-04-16 20:32 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář; +Cc: kvm, Liran Alon, Wanpeng Li

Refactor kvm_x86_ops->set_hv_timer to use an explicit parameter for
stating that the timer has expired.  Overloading the return value is
unnecessarily clever, e.g. can lead to confusion over the proper return
value from start_hv_timer() when r==1.

Cc: Wanpeng Li <wanpengli@tencent.com>
Cc: Liran Alon <liran.alon@oracle.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/include/asm/kvm_host.h |  3 ++-
 arch/x86/kvm/lapic.c            | 10 +++++-----
 arch/x86/kvm/vmx/vmx.c          |  6 ++++--
 3 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index a9d03af34030..501a8209285b 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1167,7 +1167,8 @@ struct kvm_x86_ops {
 			      uint32_t guest_irq, bool set);
 	void (*apicv_post_state_restore)(struct kvm_vcpu *vcpu);
 
-	int (*set_hv_timer)(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc);
+	int (*set_hv_timer)(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc,
+			    bool *expired);
 	void (*cancel_hv_timer)(struct kvm_vcpu *vcpu);
 
 	void (*setup_mce)(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index bdcf04689a80..9a09a41000c3 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1681,7 +1681,8 @@ static void cancel_hv_timer(struct kvm_lapic *apic)
 static bool start_hv_timer(struct kvm_lapic *apic)
 {
 	struct kvm_timer *ktimer = &apic->lapic_timer;
-	int r;
+	struct kvm_vcpu *vcpu = apic->vcpu;
+	bool expired;
 
 	WARN_ON(preemptible());
 	if (!kvm_x86_ops->set_hv_timer)
@@ -1693,8 +1694,7 @@ static bool start_hv_timer(struct kvm_lapic *apic)
 	if (!ktimer->tscdeadline)
 		return false;
 
-	r = kvm_x86_ops->set_hv_timer(apic->vcpu, ktimer->tscdeadline);
-	if (r < 0)
+	if (kvm_x86_ops->set_hv_timer(vcpu, ktimer->tscdeadline, &expired))
 		return false;
 
 	ktimer->hv_timer_in_use = true;
@@ -1712,13 +1712,13 @@ static bool start_hv_timer(struct kvm_lapic *apic)
 		 */
 		if (atomic_read(&ktimer->pending)) {
 			cancel_hv_timer(apic);
-		} else if (r) {
+		} else if (expired) {
 			apic_timer_expired(apic);
 			cancel_hv_timer(apic);
 		}
 	}
 
-	trace_kvm_hv_timer_state(apic->vcpu->vcpu_id, ktimer->hv_timer_in_use);
+	trace_kvm_hv_timer_state(vcpu->vcpu_id, ktimer->hv_timer_in_use);
 
 	return true;
 }
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index a3211e3ee679..f3c326e3c324 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -7027,7 +7027,8 @@ static inline int u64_shl_div_u64(u64 a, unsigned int shift,
 	return 0;
 }
 
-static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc)
+static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc,
+			    bool *expired)
 {
 	struct vcpu_vmx *vmx;
 	u64 tscl, guest_tscl, delta_tsc, lapic_timer_advance_cycles;
@@ -7066,7 +7067,8 @@ static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc)
 		return -ERANGE;
 
 	vmx->hv_deadline_tsc = tscl + delta_tsc;
-	return delta_tsc == 0;
+	*expired = !delta_tsc;
+	return 0;
 }
 
 static void vmx_cancel_hv_timer(struct kvm_vcpu *vcpu)
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 8/9] KVM: lapic: Check for a pending timer intr prior to start_hv_timer()
  2019-04-16 20:32 [PATCH v3 0/9] KVM: lapic: Fix a variety of timer adv issues Sean Christopherson
                   ` (6 preceding siblings ...)
  2019-04-16 20:32 ` [PATCH v3 7/9] KVM: lapic: Refactor ->set_hv_timer to use an explicit expired param Sean Christopherson
@ 2019-04-16 20:32 ` Sean Christopherson
  2019-04-16 20:32 ` [PATCH v3 9/9] KVM: VMX: Skip delta_tsc shift-and-divide if the dividend is zero Sean Christopherson
  2019-04-17 13:06 ` [PATCH v3 0/9] KVM: lapic: Fix a variety of timer adv issues Paolo Bonzini
  9 siblings, 0 replies; 20+ messages in thread
From: Sean Christopherson @ 2019-04-16 20:32 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář; +Cc: kvm, Liran Alon, Wanpeng Li

Checking for a pending non-periodic interrupt in start_hv_timer() leads
to restart_apic_timer() making an unnecessary call to start_sw_timer()
due to start_hv_timer() returning false.

Alternatively, start_hv_timer() could return %true when there is a
pending non-periodic interrupt, but that approach is less intuitive,
i.e. would require a beefy comment to explain an otherwise simple check.

Cc: Liran Alon <liran.alon@oracle.com>
Cc: Wanpeng Li <wanpengli@tencent.com>
Suggested-by: Liran Alon <liran.alon@oracle.com>
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/kvm/lapic.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 9a09a41000c3..32b05ca2f70a 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1688,9 +1688,6 @@ static bool start_hv_timer(struct kvm_lapic *apic)
 	if (!kvm_x86_ops->set_hv_timer)
 		return false;
 
-	if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending))
-		return false;
-
 	if (!ktimer->tscdeadline)
 		return false;
 
@@ -1743,8 +1740,13 @@ static void start_sw_timer(struct kvm_lapic *apic)
 static void restart_apic_timer(struct kvm_lapic *apic)
 {
 	preempt_disable();
+
+	if (!apic_lvtt_period(apic) && atomic_read(&apic->lapic_timer.pending))
+		goto out;
+
 	if (!start_hv_timer(apic))
 		start_sw_timer(apic);
+out:
 	preempt_enable();
 }
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 9/9] KVM: VMX: Skip delta_tsc shift-and-divide if the dividend is zero
  2019-04-16 20:32 [PATCH v3 0/9] KVM: lapic: Fix a variety of timer adv issues Sean Christopherson
                   ` (7 preceding siblings ...)
  2019-04-16 20:32 ` [PATCH v3 8/9] KVM: lapic: Check for a pending timer intr prior to start_hv_timer() Sean Christopherson
@ 2019-04-16 20:32 ` Sean Christopherson
  2019-04-17 13:06 ` [PATCH v3 0/9] KVM: lapic: Fix a variety of timer adv issues Paolo Bonzini
  9 siblings, 0 replies; 20+ messages in thread
From: Sean Christopherson @ 2019-04-16 20:32 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář; +Cc: kvm, Liran Alon, Wanpeng Li

Ten percent of nothin' is... let me do the math here.  Nothin' into
nothin', carry the nothin'...

Cc: Wanpeng Li <wanpengli@tencent.com>
Reviewed-by: Liran Alon <liran.alon@oracle.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/kvm/vmx/vmx.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index f3c326e3c324..58961a35fe6f 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -7051,10 +7051,9 @@ static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc,
 
 	/* Convert to host delta tsc if tsc scaling is enabled */
 	if (vcpu->arch.tsc_scaling_ratio != kvm_default_tsc_scaling_ratio &&
-			u64_shl_div_u64(delta_tsc,
+	    delta_tsc && u64_shl_div_u64(delta_tsc,
 				kvm_tsc_scaling_ratio_frac_bits,
-				vcpu->arch.tsc_scaling_ratio,
-				&delta_tsc))
+				vcpu->arch.tsc_scaling_ratio, &delta_tsc))
 		return -ERANGE;
 
 	/*
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 2/9] KVM: lapic: Convert guest TSC to host time domain when delaying
  2019-04-16 20:32 ` [PATCH v3 2/9] KVM: lapic: Convert guest TSC to host time domain when delaying Sean Christopherson
@ 2019-04-17 12:56   ` Paolo Bonzini
  2019-04-17 14:33     ` Sean Christopherson
  0 siblings, 1 reply; 20+ messages in thread
From: Paolo Bonzini @ 2019-04-17 12:56 UTC (permalink / raw)
  To: Sean Christopherson, Radim Krčmář
  Cc: kvm, Liran Alon, Wanpeng Li

On 16/04/19 22:32, Sean Christopherson wrote:
> +	/* ndelay uses delay_tsc whenever the hardware has TSC, thus always. */
> +	if (guest_tsc < tsc_deadline) {
> +		ns = (tsc_deadline - guest_tsc) * 1000000ULL;
> +		do_div(ns, vcpu->arch.virtual_tsc_khz);
> +		ndelay(min_t(u32, ns, lapic_timer_advance_ns));
> +	}
>  

This min_t would allow the timer to expire in advance of the indicated
deadline.  If this happens, wouldn't it be a bug elsewhere?

Paolo

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 1/9] KVM: lapic: Hard cap the auto-calculated timer advancement
  2019-04-16 20:32 ` [PATCH v3 1/9] KVM: lapic: Hard cap the auto-calculated timer advancement Sean Christopherson
@ 2019-04-17 12:57   ` Paolo Bonzini
  2019-04-17 14:34     ` Sean Christopherson
  0 siblings, 1 reply; 20+ messages in thread
From: Paolo Bonzini @ 2019-04-17 12:57 UTC (permalink / raw)
  To: Sean Christopherson, Radim Krčmář
  Cc: kvm, Liran Alon, Wanpeng Li

On 16/04/19 22:32, Sean Christopherson wrote:
> To minimize the latency of timer interrupts as observed by the guest,
> KVM adjusts the values it programs into the host timers to account for
> the host's overhead of programming and handling the timer event.  Now
> that the timer advancement is automatically tuned during runtime, it's
> effectively unbounded by default, e.g. if KVM is running as L1 the
> advancement can measure in hundreds of milliseconds.
> 
> Place a somewhat arbitrary hard cap of 5000ns on the auto-calculated
> advancement, as large advancements can break reasonable assumptions of
> the guest, e.g. that a timer configured to fire after 1ms won't arrive
> on the next instruction.  Although KVM busy waits to mitigate the timer
> event arriving too early, complications can arise when shifting the
> interrupt too far, e.g. vmx.flat/interrupt in kvm-unit-tests will fail
> when its "host" exits on interrupts (because the INTR is injected before
> the gets executes STI+HLT).  Arguably the unit test is "broken" in the
> sense that delaying the timer interrupt by 1ms doesn't technically
> guarantee the interrupt will arrive after STI+HLT, but it's a reasonable
> assumption that KVM should support.
> 
> Furthermore, an unbounded advancement also effectively unbounds the time
> spent busy waiting, e.g. if the guest programs a timer with a very large
> delay.
> 
> Arguably the advancement logic could simply be disabled when running as
> L1, but KVM needs to bound the advancement time regardless, e.g. if the
> TSC is unstable and the calculations get wildly out of whack.  And
> allowing the advancement when running as L1 is a good stress test of
> sorts for the logic.
> 
> Cc: Liran Alon <liran.alon@oracle.com>
> Cc: Wanpeng Li <wanpengli@tencent.com>
> Fixes: 3b8a5df6c4dc6 ("KVM: LAPIC: Tune lapic_timer_advance_ns automatically")
> Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> ---
>  arch/x86/kvm/lapic.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
> index 9bf70cf84564..92446cba9b24 100644
> --- a/arch/x86/kvm/lapic.c
> +++ b/arch/x86/kvm/lapic.c
> @@ -74,6 +74,7 @@ static bool lapic_timer_advance_adjust_done = false;
>  #define LAPIC_TIMER_ADVANCE_ADJUST_DONE 100
>  /* step-by-step approximation to mitigate fluctuation */
>  #define LAPIC_TIMER_ADVANCE_ADJUST_STEP 8
> +#define LAPIC_TIMER_ADVANCE_MAX_NS	5000
>  
>  static inline int apic_test_vector(int vec, void *bitmap)
>  {
> @@ -1522,6 +1523,10 @@ void wait_lapic_expire(struct kvm_vcpu *vcpu)
>  		}
>  		if (abs(guest_tsc - tsc_deadline) < LAPIC_TIMER_ADVANCE_ADJUST_DONE)
>  			lapic_timer_advance_adjust_done = true;
> +		if (unlikely(lapic_timer_advance_ns > LAPIC_TIMER_ADVANCE_MAX_NS)) {
> +			lapic_timer_advance_ns = LAPIC_TIMER_ADVANCE_MAX_NS;
> +			lapic_timer_advance_adjust_done = true;
> +		}

I would treat this case as "advancing the timer has failed miserably"
and reset lapic_timer_advance_ns to 0.

Paolo

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 4/9] KVM: lapic: Allow user to disable auto-tuning of timer advancement
  2019-04-16 20:32 ` [PATCH v3 4/9] KVM: lapic: Allow user to disable auto-tuning of timer advancement Sean Christopherson
@ 2019-04-17 12:59   ` Paolo Bonzini
  2019-04-17 15:22     ` Sean Christopherson
  0 siblings, 1 reply; 20+ messages in thread
From: Paolo Bonzini @ 2019-04-17 12:59 UTC (permalink / raw)
  To: Sean Christopherson, Radim Krčmář
  Cc: kvm, Liran Alon, Wanpeng Li

On 16/04/19 22:32, Sean Christopherson wrote:
> +static bool __read_mostly lapic_timer_advance_autotune = true;
> +module_param(lapic_timer_advance_autotune, bool, S_IRUGO | S_IWUSR);
> +

Could we just have lapic_timer_advance_ns = 0 mean "adaptive tuning,
starting from a default of 1000" and anything else mean "no tuning, just
use this value"?

Paolo

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 7/9] KVM: lapic: Refactor ->set_hv_timer to use an explicit expired param
  2019-04-16 20:32 ` [PATCH v3 7/9] KVM: lapic: Refactor ->set_hv_timer to use an explicit expired param Sean Christopherson
@ 2019-04-17 13:02   ` Paolo Bonzini
  0 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2019-04-17 13:02 UTC (permalink / raw)
  To: Sean Christopherson, Radim Krčmář
  Cc: kvm, Liran Alon, Wanpeng Li

On 16/04/19 22:32, Sean Christopherson wrote:
> Refactor kvm_x86_ops->set_hv_timer to use an explicit parameter for
> stating that the timer has expired.  Overloading the return value is
> unnecessarily clever, e.g. can lead to confusion over the proper return
> value from start_hv_timer() when r==1.

I guess it's also in the eye of the beholder; I don't like out
parameters very much in general but this time I think I don't disagree
enough to argue. ;)

Paolo

> Cc: Wanpeng Li <wanpengli@tencent.com>
> Cc: Liran Alon <liran.alon@oracle.com>
> Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> ---
>  arch/x86/include/asm/kvm_host.h |  3 ++-
>  arch/x86/kvm/lapic.c            | 10 +++++-----
>  arch/x86/kvm/vmx/vmx.c          |  6 ++++--
>  3 files changed, 11 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index a9d03af34030..501a8209285b 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -1167,7 +1167,8 @@ struct kvm_x86_ops {
>  			      uint32_t guest_irq, bool set);
>  	void (*apicv_post_state_restore)(struct kvm_vcpu *vcpu);
>  
> -	int (*set_hv_timer)(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc);
> +	int (*set_hv_timer)(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc,
> +			    bool *expired);
>  	void (*cancel_hv_timer)(struct kvm_vcpu *vcpu);
>  
>  	void (*setup_mce)(struct kvm_vcpu *vcpu);
> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
> index bdcf04689a80..9a09a41000c3 100644
> --- a/arch/x86/kvm/lapic.c
> +++ b/arch/x86/kvm/lapic.c
> @@ -1681,7 +1681,8 @@ static void cancel_hv_timer(struct kvm_lapic *apic)
>  static bool start_hv_timer(struct kvm_lapic *apic)
>  {
>  	struct kvm_timer *ktimer = &apic->lapic_timer;
> -	int r;
> +	struct kvm_vcpu *vcpu = apic->vcpu;
> +	bool expired;
>  
>  	WARN_ON(preemptible());
>  	if (!kvm_x86_ops->set_hv_timer)
> @@ -1693,8 +1694,7 @@ static bool start_hv_timer(struct kvm_lapic *apic)
>  	if (!ktimer->tscdeadline)
>  		return false;
>  
> -	r = kvm_x86_ops->set_hv_timer(apic->vcpu, ktimer->tscdeadline);
> -	if (r < 0)
> +	if (kvm_x86_ops->set_hv_timer(vcpu, ktimer->tscdeadline, &expired))
>  		return false;
>  
>  	ktimer->hv_timer_in_use = true;
> @@ -1712,13 +1712,13 @@ static bool start_hv_timer(struct kvm_lapic *apic)
>  		 */
>  		if (atomic_read(&ktimer->pending)) {
>  			cancel_hv_timer(apic);
> -		} else if (r) {
> +		} else if (expired) {
>  			apic_timer_expired(apic);
>  			cancel_hv_timer(apic);
>  		}
>  	}
>  
> -	trace_kvm_hv_timer_state(apic->vcpu->vcpu_id, ktimer->hv_timer_in_use);
> +	trace_kvm_hv_timer_state(vcpu->vcpu_id, ktimer->hv_timer_in_use);
>  
>  	return true;
>  }
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index a3211e3ee679..f3c326e3c324 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -7027,7 +7027,8 @@ static inline int u64_shl_div_u64(u64 a, unsigned int shift,
>  	return 0;
>  }
>  
> -static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc)
> +static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc,
> +			    bool *expired)
>  {
>  	struct vcpu_vmx *vmx;
>  	u64 tscl, guest_tscl, delta_tsc, lapic_timer_advance_cycles;
> @@ -7066,7 +7067,8 @@ static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc)
>  		return -ERANGE;
>  
>  	vmx->hv_deadline_tsc = tscl + delta_tsc;
> -	return delta_tsc == 0;
> +	*expired = !delta_tsc;
> +	return 0;
>  }
>  
>  static void vmx_cancel_hv_timer(struct kvm_vcpu *vcpu)
> 


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 0/9] KVM: lapic: Fix a variety of timer adv issues
  2019-04-16 20:32 [PATCH v3 0/9] KVM: lapic: Fix a variety of timer adv issues Sean Christopherson
                   ` (8 preceding siblings ...)
  2019-04-16 20:32 ` [PATCH v3 9/9] KVM: VMX: Skip delta_tsc shift-and-divide if the dividend is zero Sean Christopherson
@ 2019-04-17 13:06 ` Paolo Bonzini
  9 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2019-04-17 13:06 UTC (permalink / raw)
  To: Sean Christopherson, Radim Krčmář
  Cc: kvm, Liran Alon, Wanpeng Li

On 16/04/19 22:32, Sean Christopherson wrote:
> The recent change to automatically calculate lapic_timer_advance_ns
> introduced a handful of gnarly bugs, and also exposed a latent bug by
> virtue of the advancement logic being enabled by default.  Inspection
> and debug revealed several other opportunities for minor improvements.
> 
> The primary issue is that the auto-tuning of lapic_timer_advance_ns is
> completely unbounded, e.g. there's nothing in the logic that prevents the
> advancement from creeping up to hundreds of milliseconds.  Adjusting the
> timers by large amounts creates major discrepancies in the guest, e.g. a
> timer that was configured to fire after multiple milliseconds may arrive
> before the guest executes a single instruction.  While technically correct
> from a time perspective, it breaks a reasonable assumption from the guest
> that it can execute some number of instructions between timer events.
> 
> The other major issue is that the advancement is global, while TSC scaling
> is done on a per-vCPU basic.  Adjusting the advancement at runtime
> exacerbates this as there is no protection against multiple vCPUs and/or
> multiple VMs concurrently modifying the advancement value, e.g. it can
> effectively become corrupted or never stabilize due to getting bounced all
> over tarnation.
> 
> As for the latent bug, when timer advancement was applied to the hv_timer,
> i.e. the VMX preemption timer, the logic to trigger wait_for_lapic_timer()
> was not updated.  As a result, a timer interrupt emulated via the hv_timer
> can easily arrive too early from a *time* perspective, as opposed to
> simply arriving early from a "number of instructions executed" perspective.

In a surprising twist of events, I've queued the last 5 patches.  For
the first four, I still plan to get them in 5.1 but I had some comments.
 They will have to wait for next week since I'll have a (short) Easter
vacation, but there should be plenty of time.

Paolo

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 2/9] KVM: lapic: Convert guest TSC to host time domain when delaying
  2019-04-17 12:56   ` Paolo Bonzini
@ 2019-04-17 14:33     ` Sean Christopherson
  2019-04-17 15:05       ` Paolo Bonzini
  0 siblings, 1 reply; 20+ messages in thread
From: Sean Christopherson @ 2019-04-17 14:33 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Radim Krčmář, kvm, Liran Alon, Wanpeng Li

On Wed, Apr 17, 2019 at 02:56:53PM +0200, Paolo Bonzini wrote:
> On 16/04/19 22:32, Sean Christopherson wrote:
> > +	/* ndelay uses delay_tsc whenever the hardware has TSC, thus always. */
> > +	if (guest_tsc < tsc_deadline) {
> > +		ns = (tsc_deadline - guest_tsc) * 1000000ULL;
> > +		do_div(ns, vcpu->arch.virtual_tsc_khz);
> > +		ndelay(min_t(u32, ns, lapic_timer_advance_ns));
> > +	}
> >  
> 
> This min_t would allow the timer to expire in advance of the indicated
> deadline.  If this happens, wouldn't it be a bug elsewhere?

Maybe?

In this exact variation of the code, no, since userspace can modify
lapic_timer_advance_ns while the vCPU is running.  Obviously that case
goes away when lapic_timer_advance_ns is no longer directly consumed by
vCPUS.

Originally, the check was added because lockup occurred if the guest's
TSC was sent backwards[1].  The discussion surrounding the bugfix patch[2]
is probably more interesting/amusing/relevant.  We're basically rehashing
that discussion. :-)

Anyways, capping at a KVM controlled value is prudent since not doing
so can hang the host if something does go wrong.  As for the __delay()
vs ndelay() discussion, I'll try to dig more into how/why I saw the timer
fire with an incorrect TSC, i.e. why ndelay() "works" but __delay() does
not.

https://bugzilla.redhat.com/show_bug.cgi?id=1337667
https://patchwork.kernel.org/patch/9130687/

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 1/9] KVM: lapic: Hard cap the auto-calculated timer advancement
  2019-04-17 12:57   ` Paolo Bonzini
@ 2019-04-17 14:34     ` Sean Christopherson
  2019-04-17 15:00       ` Paolo Bonzini
  0 siblings, 1 reply; 20+ messages in thread
From: Sean Christopherson @ 2019-04-17 14:34 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Radim Krčmář, kvm, Liran Alon, Wanpeng Li

On Wed, Apr 17, 2019 at 02:57:55PM +0200, Paolo Bonzini wrote:
> On 16/04/19 22:32, Sean Christopherson wrote:
> > To minimize the latency of timer interrupts as observed by the guest,
> > KVM adjusts the values it programs into the host timers to account for
> > the host's overhead of programming and handling the timer event.  Now
> > that the timer advancement is automatically tuned during runtime, it's
> > effectively unbounded by default, e.g. if KVM is running as L1 the
> > advancement can measure in hundreds of milliseconds.
> > 
> > Place a somewhat arbitrary hard cap of 5000ns on the auto-calculated
> > advancement, as large advancements can break reasonable assumptions of
> > the guest, e.g. that a timer configured to fire after 1ms won't arrive
> > on the next instruction.  Although KVM busy waits to mitigate the timer
> > event arriving too early, complications can arise when shifting the
> > interrupt too far, e.g. vmx.flat/interrupt in kvm-unit-tests will fail
> > when its "host" exits on interrupts (because the INTR is injected before
> > the gets executes STI+HLT).  Arguably the unit test is "broken" in the
> > sense that delaying the timer interrupt by 1ms doesn't technically
> > guarantee the interrupt will arrive after STI+HLT, but it's a reasonable
> > assumption that KVM should support.
> > 
> > Furthermore, an unbounded advancement also effectively unbounds the time
> > spent busy waiting, e.g. if the guest programs a timer with a very large
> > delay.
> > 
> > Arguably the advancement logic could simply be disabled when running as
> > L1, but KVM needs to bound the advancement time regardless, e.g. if the
> > TSC is unstable and the calculations get wildly out of whack.  And
> > allowing the advancement when running as L1 is a good stress test of
> > sorts for the logic.
> > 
> > Cc: Liran Alon <liran.alon@oracle.com>
> > Cc: Wanpeng Li <wanpengli@tencent.com>
> > Fixes: 3b8a5df6c4dc6 ("KVM: LAPIC: Tune lapic_timer_advance_ns automatically")
> > Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> > ---
> >  arch/x86/kvm/lapic.c | 5 +++++
> >  1 file changed, 5 insertions(+)
> > 
> > diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
> > index 9bf70cf84564..92446cba9b24 100644
> > --- a/arch/x86/kvm/lapic.c
> > +++ b/arch/x86/kvm/lapic.c
> > @@ -74,6 +74,7 @@ static bool lapic_timer_advance_adjust_done = false;
> >  #define LAPIC_TIMER_ADVANCE_ADJUST_DONE 100
> >  /* step-by-step approximation to mitigate fluctuation */
> >  #define LAPIC_TIMER_ADVANCE_ADJUST_STEP 8
> > +#define LAPIC_TIMER_ADVANCE_MAX_NS	5000
> >  
> >  static inline int apic_test_vector(int vec, void *bitmap)
> >  {
> > @@ -1522,6 +1523,10 @@ void wait_lapic_expire(struct kvm_vcpu *vcpu)
> >  		}
> >  		if (abs(guest_tsc - tsc_deadline) < LAPIC_TIMER_ADVANCE_ADJUST_DONE)
> >  			lapic_timer_advance_adjust_done = true;
> > +		if (unlikely(lapic_timer_advance_ns > LAPIC_TIMER_ADVANCE_MAX_NS)) {
> > +			lapic_timer_advance_ns = LAPIC_TIMER_ADVANCE_MAX_NS;
> > +			lapic_timer_advance_adjust_done = true;
> > +		}
> 
> I would treat this case as "advancing the timer has failed miserably"
> and reset lapic_timer_advance_ns to 0.

As in, disable the feature, correct?  That works for me.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 1/9] KVM: lapic: Hard cap the auto-calculated timer advancement
  2019-04-17 14:34     ` Sean Christopherson
@ 2019-04-17 15:00       ` Paolo Bonzini
  0 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2019-04-17 15:00 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Radim Krčmář, kvm, Liran Alon, Wanpeng Li

On 17/04/19 16:34, Sean Christopherson wrote:
>>> @@ -1522,6 +1523,10 @@ void wait_lapic_expire(struct kvm_vcpu *vcpu)
>>>  		}
>>>  		if (abs(guest_tsc - tsc_deadline) < LAPIC_TIMER_ADVANCE_ADJUST_DONE)
>>>  			lapic_timer_advance_adjust_done = true;
>>> +		if (unlikely(lapic_timer_advance_ns > LAPIC_TIMER_ADVANCE_MAX_NS)) {
>>> +			lapic_timer_advance_ns = LAPIC_TIMER_ADVANCE_MAX_NS;
>>> +			lapic_timer_advance_adjust_done = true;
>>> +		}
>> I would treat this case as "advancing the timer has failed miserably"
>> and reset lapic_timer_advance_ns to 0.
> As in, disable the feature, correct?  That works for me.

Yes.

Paolo

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 2/9] KVM: lapic: Convert guest TSC to host time domain when delaying
  2019-04-17 14:33     ` Sean Christopherson
@ 2019-04-17 15:05       ` Paolo Bonzini
  0 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2019-04-17 15:05 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Radim Krčmář, kvm, Liran Alon, Wanpeng Li

On 17/04/19 16:33, Sean Christopherson wrote:
> In this exact variation of the code, no, since userspace can modify
> lapic_timer_advance_ns while the vCPU is running.  Obviously that case
> goes away when lapic_timer_advance_ns is no longer directly consumed by
> vCPUS.

Indeed, and if we weren't about to add per-vCPU lapic_timer_advance_ns,
the old suggestion of making lapic_timer_advance_ns read-only would stand.

> Anyways, capping at a KVM controlled value is prudent since not doing
> so can hang the host if something does go wrong.  

Yes---for the per-vCPU lapic_timer_advance_ns it is completely reasonable.

Paolo

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 4/9] KVM: lapic: Allow user to disable auto-tuning of timer advancement
  2019-04-17 12:59   ` Paolo Bonzini
@ 2019-04-17 15:22     ` Sean Christopherson
  0 siblings, 0 replies; 20+ messages in thread
From: Sean Christopherson @ 2019-04-17 15:22 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Radim Krčmář, kvm, Liran Alon, Wanpeng Li

On Wed, Apr 17, 2019 at 02:59:43PM +0200, Paolo Bonzini wrote:
> On 16/04/19 22:32, Sean Christopherson wrote:
> > +static bool __read_mostly lapic_timer_advance_autotune = true;
> > +module_param(lapic_timer_advance_autotune, bool, S_IRUGO | S_IWUSR);
> > +
> 
> Could we just have lapic_timer_advance_ns = 0 mean "adaptive tuning,
> starting from a default of 1000" and anything else mean "no tuning, just
> use this value"?

Originally I implemented a variation of that, except I disabled autotuning
if lapic_timer_advance_ns was set to anything other than the default.
Liran requested a separate param since the behavior was admittedly a bit
sneaky, and I didn't have a strong opinion either way, so here we are.

I think 'lapic_timer_advance_ns = 0' should be used to disable the
advancement.  What if we make the param a signed int and have '-1' select
the "adaptive tuning ..." option?  That could also be the default.  It
saves a param and is hopefully more intuitive than what I originally
proposed.

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2019-04-17 15:22 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-16 20:32 [PATCH v3 0/9] KVM: lapic: Fix a variety of timer adv issues Sean Christopherson
2019-04-16 20:32 ` [PATCH v3 1/9] KVM: lapic: Hard cap the auto-calculated timer advancement Sean Christopherson
2019-04-17 12:57   ` Paolo Bonzini
2019-04-17 14:34     ` Sean Christopherson
2019-04-17 15:00       ` Paolo Bonzini
2019-04-16 20:32 ` [PATCH v3 2/9] KVM: lapic: Convert guest TSC to host time domain when delaying Sean Christopherson
2019-04-17 12:56   ` Paolo Bonzini
2019-04-17 14:33     ` Sean Christopherson
2019-04-17 15:05       ` Paolo Bonzini
2019-04-16 20:32 ` [PATCH v3 3/9] KVM: lapic: Track lapic timer advance per vCPU Sean Christopherson
2019-04-16 20:32 ` [PATCH v3 4/9] KVM: lapic: Allow user to disable auto-tuning of timer advancement Sean Christopherson
2019-04-17 12:59   ` Paolo Bonzini
2019-04-17 15:22     ` Sean Christopherson
2019-04-16 20:32 ` [PATCH v3 5/9] KVM: lapic: Busy wait for timer to expire when using hv_timer Sean Christopherson
2019-04-16 20:32 ` [PATCH v3 6/9] KVM: lapic: Explicitly cancel the hv timer if it's pre-expired Sean Christopherson
2019-04-16 20:32 ` [PATCH v3 7/9] KVM: lapic: Refactor ->set_hv_timer to use an explicit expired param Sean Christopherson
2019-04-17 13:02   ` Paolo Bonzini
2019-04-16 20:32 ` [PATCH v3 8/9] KVM: lapic: Check for a pending timer intr prior to start_hv_timer() Sean Christopherson
2019-04-16 20:32 ` [PATCH v3 9/9] KVM: VMX: Skip delta_tsc shift-and-divide if the dividend is zero Sean Christopherson
2019-04-17 13:06 ` [PATCH v3 0/9] KVM: lapic: Fix a variety of timer adv issues Paolo Bonzini

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.