All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] KVM: lapic: optimize injection of already-expired timer
@ 2017-06-29 16:58 Paolo Bonzini
  2017-06-29 16:58 ` [PATCH 1/3] KVM: lapic: reorganize start_hv_timer Paolo Bonzini
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Paolo Bonzini @ 2017-06-29 16:58 UTC (permalink / raw)
  To: linux-kernel, kvm; +Cc: rkrcmar, wanpeng.li

This is my take on Wanpeng's optimization, whose effect I've now measured
with vmexit.flat.  Indeed, without patch 3 the new tscdeadline_immed
benchmark is 50% slower with preemption_timer=1 than with preemption_timer=0.

Patch 1 refactors start_hv_timer to prepare for the next one and to
simplify Wanpeng's patch (a lot).  Patch 2 avoids a bug that I didn't
catch in my earlier review: kvm_x86_ops->set_timer must not be called
directly when the TSC goes backwards.

Paolo

Paolo Bonzini (2):
  KVM: lapic: reorganize start_hv_timer
  KVM: lapic: reorganize restart_apic_timer

Wanpeng Li (1):
  KVM: LAPIC: Fix lapic timer injection delay

 arch/x86/kvm/lapic.c | 116 ++++++++++++++++++++++++++++-----------------------
 arch/x86/kvm/lapic.h |   2 +-
 arch/x86/kvm/vmx.c   |   3 +-
 arch/x86/kvm/x86.c   |   8 ++--
 4 files changed, 71 insertions(+), 58 deletions(-)

-- 
1.8.3.1

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

* [PATCH 1/3] KVM: lapic: reorganize start_hv_timer
  2017-06-29 16:58 [PATCH 0/3] KVM: lapic: optimize injection of already-expired timer Paolo Bonzini
@ 2017-06-29 16:58 ` Paolo Bonzini
  2017-06-29 16:58 ` [PATCH 2/3] KVM: lapic: reorganize restart_apic_timer Paolo Bonzini
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 11+ messages in thread
From: Paolo Bonzini @ 2017-06-29 16:58 UTC (permalink / raw)
  To: linux-kernel, kvm; +Cc: rkrcmar, wanpeng.li

There are many cases in which the hv timer must be canceled.  Split out
a new function to avoid duplication.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/kvm/lapic.c | 40 +++++++++++++++++++++++++++-------------
 1 file changed, 27 insertions(+), 13 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index d24c8742d9b0..b6689dcae1da 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1501,24 +1501,38 @@ static void cancel_hv_timer(struct kvm_lapic *apic)
 	preempt_enable();
 }
 
-static bool start_hv_timer(struct kvm_lapic *apic)
+static bool __start_hv_timer(struct kvm_lapic *apic)
 {
-	u64 tscdeadline = apic->lapic_timer.tscdeadline;
+	struct kvm_timer *ktimer = &apic->lapic_timer;
+	int r;
 
-	if ((atomic_read(&apic->lapic_timer.pending) &&
-		!apic_lvtt_period(apic)) ||
-		kvm_x86_ops->set_hv_timer(apic->vcpu, tscdeadline)) {
-		if (apic->lapic_timer.hv_timer_in_use)
-			cancel_hv_timer(apic);
-	} else {
-		apic->lapic_timer.hv_timer_in_use = true;
-		hrtimer_cancel(&apic->lapic_timer.timer);
+	if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending))
+		return false;
+
+	r = kvm_x86_ops->set_hv_timer(apic->vcpu, ktimer->tscdeadline);
+	if (r < 0)
+		return false;
+
+	ktimer->hv_timer_in_use = true;
+	hrtimer_cancel(&ktimer->timer);
 
-		/* In case the sw timer triggered in the window */
-		if (atomic_read(&apic->lapic_timer.pending) &&
-			!apic_lvtt_period(apic))
+	/*
+	 * 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.
+	 */
+	if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending))
+		return false;
+	return true;
+}
+
+static bool start_hv_timer(struct kvm_lapic *apic)
+{
+	if (!__start_hv_timer(apic)) {
+		if (apic->lapic_timer.hv_timer_in_use)
 			cancel_hv_timer(apic);
 	}
+
 	trace_kvm_hv_timer_state(apic->vcpu->vcpu_id,
 			apic->lapic_timer.hv_timer_in_use);
 	return apic->lapic_timer.hv_timer_in_use;
-- 
1.8.3.1

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

* [PATCH 2/3] KVM: lapic: reorganize restart_apic_timer
  2017-06-29 16:58 [PATCH 0/3] KVM: lapic: optimize injection of already-expired timer Paolo Bonzini
  2017-06-29 16:58 ` [PATCH 1/3] KVM: lapic: reorganize start_hv_timer Paolo Bonzini
@ 2017-06-29 16:58 ` Paolo Bonzini
  2017-06-29 16:58 ` [PATCH 3/3] KVM: LAPIC: Fix lapic timer injection delay Paolo Bonzini
  2017-06-30  1:30 ` [PATCH 0/3] KVM: lapic: optimize injection of already-expired timer Wanpeng Li
  3 siblings, 0 replies; 11+ messages in thread
From: Paolo Bonzini @ 2017-06-29 16:58 UTC (permalink / raw)
  To: linux-kernel, kvm; +Cc: rkrcmar, wanpeng.li

Move the code to cancel the hv timer into the caller, just before
it starts the hrtimer.  Check availability of the hv timer in
start_hv_timer.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/kvm/lapic.c | 85 +++++++++++++++++++++++++---------------------------
 arch/x86/kvm/lapic.h |  2 +-
 arch/x86/kvm/x86.c   |  8 ++---
 3 files changed, 45 insertions(+), 50 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index b6689dcae1da..a80e5a5d6f2f 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1495,17 +1495,21 @@ bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu)
 
 static void cancel_hv_timer(struct kvm_lapic *apic)
 {
+	WARN_ON(!apic->lapic_timer.hv_timer_in_use);
 	preempt_disable();
 	kvm_x86_ops->cancel_hv_timer(apic->vcpu);
 	apic->lapic_timer.hv_timer_in_use = false;
 	preempt_enable();
 }
 
-static bool __start_hv_timer(struct kvm_lapic *apic)
+static bool start_hv_timer(struct kvm_lapic *apic)
 {
 	struct kvm_timer *ktimer = &apic->lapic_timer;
 	int r;
 
+	if (!kvm_x86_ops->set_hv_timer)
+		return false;
+
 	if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending))
 		return false;
 
@@ -1523,19 +1527,30 @@ static bool __start_hv_timer(struct kvm_lapic *apic)
 	 */
 	if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending))
 		return false;
+
+	trace_kvm_hv_timer_state(apic->vcpu->vcpu_id, true);
 	return true;
 }
 
-static bool start_hv_timer(struct kvm_lapic *apic)
+static void start_sw_timer(struct kvm_lapic *apic)
 {
-	if (!__start_hv_timer(apic)) {
-		if (apic->lapic_timer.hv_timer_in_use)
-			cancel_hv_timer(apic);
-	}
+	struct kvm_timer *ktimer = &apic->lapic_timer;
+	if (apic->lapic_timer.hv_timer_in_use)
+		cancel_hv_timer(apic);
+	if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending))
+		return;
+
+	if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic))
+		start_sw_period(apic);
+	else if (apic_lvtt_tscdeadline(apic))
+		start_sw_tscdeadline(apic);
+	trace_kvm_hv_timer_state(apic->vcpu->vcpu_id, false);
+}
 
-	trace_kvm_hv_timer_state(apic->vcpu->vcpu_id,
-			apic->lapic_timer.hv_timer_in_use);
-	return apic->lapic_timer.hv_timer_in_use;
+static void restart_apic_timer(struct kvm_lapic *apic)
+{
+	if (!start_hv_timer(apic))
+		start_sw_timer(apic);
 }
 
 void kvm_lapic_expired_hv_timer(struct kvm_vcpu *vcpu)
@@ -1549,19 +1564,14 @@ void kvm_lapic_expired_hv_timer(struct kvm_vcpu *vcpu)
 
 	if (apic_lvtt_period(apic) && apic->lapic_timer.period) {
 		advance_periodic_target_expiration(apic);
-		if (!start_hv_timer(apic))
-			start_sw_period(apic);
+		restart_apic_timer(apic);
 	}
 }
 EXPORT_SYMBOL_GPL(kvm_lapic_expired_hv_timer);
 
 void kvm_lapic_switch_to_hv_timer(struct kvm_vcpu *vcpu)
 {
-	struct kvm_lapic *apic = vcpu->arch.apic;
-
-	WARN_ON(apic->lapic_timer.hv_timer_in_use);
-
-	start_hv_timer(apic);
+	restart_apic_timer(vcpu->arch.apic);
 }
 EXPORT_SYMBOL_GPL(kvm_lapic_switch_to_hv_timer);
 
@@ -1570,33 +1580,28 @@ void kvm_lapic_switch_to_sw_timer(struct kvm_vcpu *vcpu)
 	struct kvm_lapic *apic = vcpu->arch.apic;
 
 	/* Possibly the TSC deadline timer is not enabled yet */
-	if (!apic->lapic_timer.hv_timer_in_use)
-		return;
-
-	cancel_hv_timer(apic);
+	if (apic->lapic_timer.hv_timer_in_use)
+		start_sw_timer(apic);
+}
+EXPORT_SYMBOL_GPL(kvm_lapic_switch_to_sw_timer);
 
-	if (atomic_read(&apic->lapic_timer.pending))
-		return;
+void kvm_lapic_restart_hv_timer(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
 
-	if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic))
-		start_sw_period(apic);
-	else if (apic_lvtt_tscdeadline(apic))
-		start_sw_tscdeadline(apic);
+	WARN_ON(!apic->lapic_timer.hv_timer_in_use);
+	restart_apic_timer(apic);
 }
-EXPORT_SYMBOL_GPL(kvm_lapic_switch_to_sw_timer);
 
 static void start_apic_timer(struct kvm_lapic *apic)
 {
 	atomic_set(&apic->lapic_timer.pending, 0);
 
-	if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic)) {
-		if (set_target_expiration(apic) &&
-			!(kvm_x86_ops->set_hv_timer && start_hv_timer(apic)))
-			start_sw_period(apic);
-	} else if (apic_lvtt_tscdeadline(apic)) {
-		if (!(kvm_x86_ops->set_hv_timer && start_hv_timer(apic)))
-			start_sw_tscdeadline(apic);
-	}
+	if ((apic_lvtt_period(apic) || apic_lvtt_oneshot(apic))
+	    && !set_target_expiration(apic))
+		return;
+
+	restart_apic_timer(apic);
 }
 
 static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
@@ -1827,16 +1832,6 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu)
  * LAPIC interface
  *----------------------------------------------------------------------
  */
-u64 kvm_get_lapic_target_expiration_tsc(struct kvm_vcpu *vcpu)
-{
-	struct kvm_lapic *apic = vcpu->arch.apic;
-
-	if (!lapic_in_kernel(vcpu))
-		return 0;
-
-	return apic->lapic_timer.tscdeadline;
-}
-
 u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index bcbe811f3b97..29caa2c3dff9 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -87,7 +87,6 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
 int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
 
-u64 kvm_get_lapic_target_expiration_tsc(struct kvm_vcpu *vcpu);
 u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
 void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data);
 
@@ -216,4 +215,5 @@ int kvm_vector_to_index(u32 vector, u32 dest_vcpus,
 void kvm_lapic_switch_to_hv_timer(struct kvm_vcpu *vcpu);
 void kvm_lapic_expired_hv_timer(struct kvm_vcpu *vcpu);
 bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu);
+void kvm_lapic_restart_hv_timer(struct kvm_vcpu *vcpu);
 #endif
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index a2cd0997343c..81aa9c321be3 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2841,10 +2841,10 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 			kvm_vcpu_write_tsc_offset(vcpu, offset);
 			vcpu->arch.tsc_catchup = 1;
 		}
-		if (kvm_lapic_hv_timer_in_use(vcpu) &&
-				kvm_x86_ops->set_hv_timer(vcpu,
-					kvm_get_lapic_target_expiration_tsc(vcpu)))
-			kvm_lapic_switch_to_sw_timer(vcpu);
+
+		if (kvm_lapic_hv_timer_in_use(vcpu))
+			kvm_lapic_restart_hv_timer(vcpu);
+
 		/*
 		 * On a host with synchronized TSC, there is no need to update
 		 * kvmclock on vcpu->cpu migration
-- 
1.8.3.1

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

* [PATCH 3/3] KVM: LAPIC: Fix lapic timer injection delay
  2017-06-29 16:58 [PATCH 0/3] KVM: lapic: optimize injection of already-expired timer Paolo Bonzini
  2017-06-29 16:58 ` [PATCH 1/3] KVM: lapic: reorganize start_hv_timer Paolo Bonzini
  2017-06-29 16:58 ` [PATCH 2/3] KVM: lapic: reorganize restart_apic_timer Paolo Bonzini
@ 2017-06-29 16:58 ` Paolo Bonzini
  2017-07-02  1:35   ` Wanpeng Li
  2017-06-30  1:30 ` [PATCH 0/3] KVM: lapic: optimize injection of already-expired timer Wanpeng Li
  3 siblings, 1 reply; 11+ messages in thread
From: Paolo Bonzini @ 2017-06-29 16:58 UTC (permalink / raw)
  To: linux-kernel, kvm; +Cc: rkrcmar, wanpeng.li

From: Wanpeng Li <wanpeng.li@hotmail.com>

If the TSC deadline timer is programmed really close to the deadline or
even in the past, the computation in vmx_set_hv_timer will program the
absolute target tsc value to vmcs preemption timer field w/ delta == 0.
The next vmentry results in an immediate vmx preemption timer vmexit
and the lapic timer injection is delayed due to this duration.  Actually
the lapic timer which is emulated by hrtimer can handle this correctly.

This patch fixes it by firing the lapic timer and injecting a timer interrupt
immediately during the next vmentry if the TSC deadline timer is programmed
really close to the deadline or even in the past. This saves ~1200 cycles on
the tscdeadline_immed test of vmexit.flat.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com>
[Rebased on top of previous patch. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/kvm/lapic.c | 5 ++++-
 arch/x86/kvm/vmx.c   | 3 ++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index a80e5a5d6f2f..2819d4c123eb 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1525,8 +1525,11 @@ static bool start_hv_timer(struct kvm_lapic *apic)
 	 * the window.  For periodic timer, leave the hv timer running for
 	 * simplicity, and the deadline will be recomputed on the next vmexit.
 	 */
-	if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending))
+	if (!apic_lvtt_period(apic) && (r || atomic_read(&ktimer->pending))) {
+		if (r)
+			apic_timer_expired(apic);
 		return false;
+	}
 
 	trace_kvm_hv_timer_state(apic->vcpu->vcpu_id, true);
 	return true;
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index e8b61ad84a8e..92ddea08f999 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -11147,7 +11147,8 @@ static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc)
 	vmx->hv_deadline_tsc = tscl + delta_tsc;
 	vmcs_set_bits(PIN_BASED_VM_EXEC_CONTROL,
 			PIN_BASED_VMX_PREEMPTION_TIMER);
-	return 0;
+
+	return delta_tsc == 0;
 }
 
 static void vmx_cancel_hv_timer(struct kvm_vcpu *vcpu)
-- 
1.8.3.1

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

* Re: [PATCH 0/3] KVM: lapic: optimize injection of already-expired timer
  2017-06-29 16:58 [PATCH 0/3] KVM: lapic: optimize injection of already-expired timer Paolo Bonzini
                   ` (2 preceding siblings ...)
  2017-06-29 16:58 ` [PATCH 3/3] KVM: LAPIC: Fix lapic timer injection delay Paolo Bonzini
@ 2017-06-30  1:30 ` Wanpeng Li
  3 siblings, 0 replies; 11+ messages in thread
From: Wanpeng Li @ 2017-06-30  1:30 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: linux-kernel, kvm, Radim Krcmar, Wanpeng Li

2017-06-30 0:58 GMT+08:00 Paolo Bonzini <pbonzini@redhat.com>:
> This is my take on Wanpeng's optimization, whose effect I've now measured
> with vmexit.flat.  Indeed, without patch 3 the new tscdeadline_immed
> benchmark is 50% slower with preemption_timer=1 than with preemption_timer=0.
>
> Patch 1 refactors start_hv_timer to prepare for the next one and to
> simplify Wanpeng's patch (a lot).  Patch 2 avoids a bug that I didn't
> catch in my earlier review: kvm_x86_ops->set_timer must not be called
> directly when the TSC goes backwards.
>

The patchset looks good to me and thanks for the benchmark.

Regards,
Wanpeng Li

>
> Paolo Bonzini (2):
>   KVM: lapic: reorganize start_hv_timer
>   KVM: lapic: reorganize restart_apic_timer
>
> Wanpeng Li (1):
>   KVM: LAPIC: Fix lapic timer injection delay
>
>  arch/x86/kvm/lapic.c | 116 ++++++++++++++++++++++++++++-----------------------
>  arch/x86/kvm/lapic.h |   2 +-
>  arch/x86/kvm/vmx.c   |   3 +-
>  arch/x86/kvm/x86.c   |   8 ++--
>  4 files changed, 71 insertions(+), 58 deletions(-)
>
> --
> 1.8.3.1
>

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

* Re: [PATCH 3/3] KVM: LAPIC: Fix lapic timer injection delay
  2017-06-29 16:58 ` [PATCH 3/3] KVM: LAPIC: Fix lapic timer injection delay Paolo Bonzini
@ 2017-07-02  1:35   ` Wanpeng Li
  2017-07-02  1:56     ` Wanpeng Li
  0 siblings, 1 reply; 11+ messages in thread
From: Wanpeng Li @ 2017-07-02  1:35 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: linux-kernel, kvm, Radim Krcmar, Wanpeng Li

2017-06-30 0:58 GMT+08:00 Paolo Bonzini <pbonzini@redhat.com>:
> From: Wanpeng Li <wanpeng.li@hotmail.com>
>
> If the TSC deadline timer is programmed really close to the deadline or
> even in the past, the computation in vmx_set_hv_timer will program the
> absolute target tsc value to vmcs preemption timer field w/ delta == 0.
> The next vmentry results in an immediate vmx preemption timer vmexit
> and the lapic timer injection is delayed due to this duration.  Actually
> the lapic timer which is emulated by hrtimer can handle this correctly.
>
> This patch fixes it by firing the lapic timer and injecting a timer interrupt
> immediately during the next vmentry if the TSC deadline timer is programmed
> really close to the deadline or even in the past. This saves ~1200 cycles on
> the tscdeadline_immed test of vmexit.flat.
>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Radim Krčmář <rkrcmar@redhat.com>
> Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com>
> [Rebased on top of previous patch. - Paolo]
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  arch/x86/kvm/lapic.c | 5 ++++-
>  arch/x86/kvm/vmx.c   | 3 ++-
>  2 files changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
> index a80e5a5d6f2f..2819d4c123eb 100644
> --- a/arch/x86/kvm/lapic.c
> +++ b/arch/x86/kvm/lapic.c
> @@ -1525,8 +1525,11 @@ static bool start_hv_timer(struct kvm_lapic *apic)
>          * the window.  For periodic timer, leave the hv timer running for
>          * simplicity, and the deadline will be recomputed on the next vmexit.
>          */
> -       if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending))
> +       if (!apic_lvtt_period(apic) && (r || atomic_read(&ktimer->pending))) {
> +               if (r)
> +                       apic_timer_expired(apic);
>                 return false;
> +       }

This logic is not the same as in my v4
http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1434040.html
. You return false for the expired timer and actually it will switch
to sw timer.

>
>         trace_kvm_hv_timer_state(apic->vcpu->vcpu_id, true);
>         return true;
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index e8b61ad84a8e..92ddea08f999 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -11147,7 +11147,8 @@ static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc)
>         vmx->hv_deadline_tsc = tscl + delta_tsc;
>         vmcs_set_bits(PIN_BASED_VM_EXEC_CONTROL,
>                         PIN_BASED_VMX_PREEMPTION_TIMER);
> -       return 0;
> +
> +       return delta_tsc == 0;
>  }
>
>  static void vmx_cancel_hv_timer(struct kvm_vcpu *vcpu)
> --
> 1.8.3.1
>

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

* Re: [PATCH 3/3] KVM: LAPIC: Fix lapic timer injection delay
  2017-07-02  1:35   ` Wanpeng Li
@ 2017-07-02  1:56     ` Wanpeng Li
  2017-07-03  7:30       ` Paolo Bonzini
  0 siblings, 1 reply; 11+ messages in thread
From: Wanpeng Li @ 2017-07-02  1:56 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: linux-kernel, kvm, Radim Krcmar, Wanpeng Li

2017-07-02 9:35 GMT+08:00 Wanpeng Li <kernellwp@gmail.com>:
> 2017-06-30 0:58 GMT+08:00 Paolo Bonzini <pbonzini@redhat.com>:
>> From: Wanpeng Li <wanpeng.li@hotmail.com>
>>
>> If the TSC deadline timer is programmed really close to the deadline or
>> even in the past, the computation in vmx_set_hv_timer will program the
>> absolute target tsc value to vmcs preemption timer field w/ delta == 0.
>> The next vmentry results in an immediate vmx preemption timer vmexit
>> and the lapic timer injection is delayed due to this duration.  Actually
>> the lapic timer which is emulated by hrtimer can handle this correctly.
>>
>> This patch fixes it by firing the lapic timer and injecting a timer interrupt
>> immediately during the next vmentry if the TSC deadline timer is programmed
>> really close to the deadline or even in the past. This saves ~1200 cycles on
>> the tscdeadline_immed test of vmexit.flat.
>>
>> Cc: Paolo Bonzini <pbonzini@redhat.com>
>> Cc: Radim Krčmář <rkrcmar@redhat.com>
>> Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com>
>> [Rebased on top of previous patch. - Paolo]
>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>> ---
>>  arch/x86/kvm/lapic.c | 5 ++++-
>>  arch/x86/kvm/vmx.c   | 3 ++-
>>  2 files changed, 6 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
>> index a80e5a5d6f2f..2819d4c123eb 100644
>> --- a/arch/x86/kvm/lapic.c
>> +++ b/arch/x86/kvm/lapic.c
>> @@ -1525,8 +1525,11 @@ static bool start_hv_timer(struct kvm_lapic *apic)
>>          * the window.  For periodic timer, leave the hv timer running for
>>          * simplicity, and the deadline will be recomputed on the next vmexit.
>>          */
>> -       if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending))
>> +       if (!apic_lvtt_period(apic) && (r || atomic_read(&ktimer->pending))) {
>> +               if (r)
>> +                       apic_timer_expired(apic);
>>                 return false;
>> +       }
>
> This logic is not the same as in my v4
> http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1434040.html
> . You return false for the expired timer and actually it will switch
> to sw timer.

Ah, I miss read it, the rebase is correct.

Regards,
Wanpeng Li

>
>>
>>         trace_kvm_hv_timer_state(apic->vcpu->vcpu_id, true);
>>         return true;
>> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
>> index e8b61ad84a8e..92ddea08f999 100644
>> --- a/arch/x86/kvm/vmx.c
>> +++ b/arch/x86/kvm/vmx.c
>> @@ -11147,7 +11147,8 @@ static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc)
>>         vmx->hv_deadline_tsc = tscl + delta_tsc;
>>         vmcs_set_bits(PIN_BASED_VM_EXEC_CONTROL,
>>                         PIN_BASED_VMX_PREEMPTION_TIMER);
>> -       return 0;
>> +
>> +       return delta_tsc == 0;
>>  }
>>
>>  static void vmx_cancel_hv_timer(struct kvm_vcpu *vcpu)
>> --
>> 1.8.3.1
>>

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

* Re: [PATCH 3/3] KVM: LAPIC: Fix lapic timer injection delay
  2017-07-02  1:56     ` Wanpeng Li
@ 2017-07-03  7:30       ` Paolo Bonzini
  2017-07-03  8:08         ` Wanpeng Li
  0 siblings, 1 reply; 11+ messages in thread
From: Paolo Bonzini @ 2017-07-03  7:30 UTC (permalink / raw)
  To: Wanpeng Li; +Cc: linux-kernel, kvm, Radim Krcmar, Wanpeng Li



On 02/07/2017 03:56, Wanpeng Li wrote:
>>> -       if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending))
>>> +       if (!apic_lvtt_period(apic) && (r || atomic_read(&ktimer->pending))) {
>>> +               if (r)
>>> +                       apic_timer_expired(apic);
>>>                 return false;
>>> +       }
>>
>> This logic is not the same as in my v4
>> http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1434040.html
>> . You return false for the expired timer and actually it will switch
>> to sw timer.
>
> Ah, I miss read it, the rebase is correct.

Yeah, I'm not entirely satisfied with it but it's working: start_sw
timer will see ktimer->pending and do nothing.

But thinking more about it, maybe the "if (r)" can be omitted
completely?  We need to benchmark it but it can be done.

Paolo

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

* Re: [PATCH 3/3] KVM: LAPIC: Fix lapic timer injection delay
  2017-07-03  7:30       ` Paolo Bonzini
@ 2017-07-03  8:08         ` Wanpeng Li
  2017-07-03  8:16           ` Paolo Bonzini
  0 siblings, 1 reply; 11+ messages in thread
From: Wanpeng Li @ 2017-07-03  8:08 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: linux-kernel, kvm, Radim Krcmar, Wanpeng Li

2017-07-03 15:30 GMT+08:00 Paolo Bonzini <pbonzini@redhat.com>:
>
>
> On 02/07/2017 03:56, Wanpeng Li wrote:
>>>> -       if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending))
>>>> +       if (!apic_lvtt_period(apic) && (r || atomic_read(&ktimer->pending))) {
>>>> +               if (r)
>>>> +                       apic_timer_expired(apic);
>>>>                 return false;
>>>> +       }
>>>
>>> This logic is not the same as in my v4
>>> http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1434040.html
>>> . You return false for the expired timer and actually it will switch
>>> to sw timer.
>>
>> Ah, I miss read it, the rebase is correct.
>
> Yeah, I'm not entirely satisfied with it but it's working: start_sw
> timer will see ktimer->pending and do nothing.
>
> But thinking more about it, maybe the "if (r)" can be omitted
> completely?  We need to benchmark it but it can be done.

"if (r)" makes codes more understandable, in addition, calling expired
the pending timer here looks weird though ktimer->pending.

Regards,
Wanpeng Li

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

* Re: [PATCH 3/3] KVM: LAPIC: Fix lapic timer injection delay
  2017-07-03  8:08         ` Wanpeng Li
@ 2017-07-03  8:16           ` Paolo Bonzini
  2017-07-03  8:41             ` Wanpeng Li
  0 siblings, 1 reply; 11+ messages in thread
From: Paolo Bonzini @ 2017-07-03  8:16 UTC (permalink / raw)
  To: Wanpeng Li; +Cc: linux-kernel, kvm, Radim Krcmar, Wanpeng Li



On 03/07/2017 10:08, Wanpeng Li wrote:
>> Yeah, I'm not entirely satisfied with it but it's working: start_sw
>> timer will see ktimer->pending and do nothing.
>>
>> But thinking more about it, maybe the "if (r)" can be omitted
>> completely?  We need to benchmark it but it can be done.
> "if (r)" makes codes more understandable, in addition, calling expired
> the pending timer here looks weird though ktimer->pending.

We can remove the call to apic_timer_expired too (sorry if I was too
terse). :)  start_sw_period and start_sw_tscdeadline would take care of it.

Paolo

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

* Re: [PATCH 3/3] KVM: LAPIC: Fix lapic timer injection delay
  2017-07-03  8:16           ` Paolo Bonzini
@ 2017-07-03  8:41             ` Wanpeng Li
  0 siblings, 0 replies; 11+ messages in thread
From: Wanpeng Li @ 2017-07-03  8:41 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: linux-kernel, kvm, Radim Krcmar, Wanpeng Li

2017-07-03 16:16 GMT+08:00 Paolo Bonzini <pbonzini@redhat.com>:
>
>
> On 03/07/2017 10:08, Wanpeng Li wrote:
>>> Yeah, I'm not entirely satisfied with it but it's working: start_sw
>>> timer will see ktimer->pending and do nothing.
>>>
>>> But thinking more about it, maybe the "if (r)" can be omitted
>>> completely?  We need to benchmark it but it can be done.
>> "if (r)" makes codes more understandable, in addition, calling expired
>> the pending timer here looks weird though ktimer->pending.
>
> We can remove the call to apic_timer_expired too (sorry if I was too
> terse). :)  start_sw_period and start_sw_tscdeadline would take care of it.

IRQ disable and ktime_get() in start_sw_tscdeadline() are more
expensive. So maybe current status is a better choice. :)

Regards,
Wanpeng Li

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

end of thread, other threads:[~2017-07-03  8:41 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-29 16:58 [PATCH 0/3] KVM: lapic: optimize injection of already-expired timer Paolo Bonzini
2017-06-29 16:58 ` [PATCH 1/3] KVM: lapic: reorganize start_hv_timer Paolo Bonzini
2017-06-29 16:58 ` [PATCH 2/3] KVM: lapic: reorganize restart_apic_timer Paolo Bonzini
2017-06-29 16:58 ` [PATCH 3/3] KVM: LAPIC: Fix lapic timer injection delay Paolo Bonzini
2017-07-02  1:35   ` Wanpeng Li
2017-07-02  1:56     ` Wanpeng Li
2017-07-03  7:30       ` Paolo Bonzini
2017-07-03  8:08         ` Wanpeng Li
2017-07-03  8:16           ` Paolo Bonzini
2017-07-03  8:41             ` Wanpeng Li
2017-06-30  1:30 ` [PATCH 0/3] KVM: lapic: optimize injection of already-expired timer Wanpeng Li

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.