[1/2] LoongArch: KVM: Start SW timer only when vcpu is blocking

Message ID 20240130072238.2829831-2-maobibo@loongson.cn
State New
Headers
Series LoongArch: KVM: Start SW timer only when vcpu is blocking |

Commit Message

maobibo Jan. 30, 2024, 7:22 a.m. UTC
  SW timer is enabled when vcpu thread is scheduled out, and it is
to wake up vcpu from blocked queue. If vcpu thread is scheduled out
however is not blocked, such as it is preempted by other threads,
it is not necessary to enable SW timer. Since vcpu thread is still
on running queue if preempted and SW timer is only to wake up vcpu
on blocking queue, so SW timer is not useful in this situation.

This patch enables SW timer only when vcpu is scheduled out and
is blocking.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
 arch/loongarch/kvm/timer.c | 22 ++++++++--------------
 1 file changed, 8 insertions(+), 14 deletions(-)
  

Comments

Huacai Chen Feb. 26, 2024, 12:58 p.m. UTC | #1
Queued for loongarch-kvm, thanks.

Huacai

On Tue, Jan 30, 2024 at 3:22 PM Bibo Mao <maobibo@loongson.cn> wrote:
>
> SW timer is enabled when vcpu thread is scheduled out, and it is
> to wake up vcpu from blocked queue. If vcpu thread is scheduled out
> however is not blocked, such as it is preempted by other threads,
> it is not necessary to enable SW timer. Since vcpu thread is still
> on running queue if preempted and SW timer is only to wake up vcpu
> on blocking queue, so SW timer is not useful in this situation.
>
> This patch enables SW timer only when vcpu is scheduled out and
> is blocking.
>
> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
> ---
>  arch/loongarch/kvm/timer.c | 22 ++++++++--------------
>  1 file changed, 8 insertions(+), 14 deletions(-)
>
> diff --git a/arch/loongarch/kvm/timer.c b/arch/loongarch/kvm/timer.c
> index 111328f60872..a9125f0a12d1 100644
> --- a/arch/loongarch/kvm/timer.c
> +++ b/arch/loongarch/kvm/timer.c
> @@ -93,7 +93,8 @@ void kvm_restore_timer(struct kvm_vcpu *vcpu)
>         /*
>          * Freeze the soft-timer and sync the guest stable timer with it.
>          */
> -       hrtimer_cancel(&vcpu->arch.swtimer);
> +       if (kvm_vcpu_is_blocking(vcpu))
> +               hrtimer_cancel(&vcpu->arch.swtimer);
>
>         /*
>          * From LoongArch Reference Manual Volume 1 Chapter 7.6.2
> @@ -168,26 +169,19 @@ static void _kvm_save_timer(struct kvm_vcpu *vcpu)
>          * Here judge one-shot timer fired by checking whether TVAL is larger
>          * than TCFG
>          */
> -       if (ticks < cfg) {
> +       if (ticks < cfg)
>                 delta = tick_to_ns(vcpu, ticks);
> -               expire = ktime_add_ns(ktime_get(), delta);
> -               vcpu->arch.expire = expire;
> +       else
> +               delta = 0;
> +       expire = ktime_add_ns(ktime_get(), delta);
> +       vcpu->arch.expire = expire;
> +       if (kvm_vcpu_is_blocking(vcpu)) {
>
>                 /*
>                  * HRTIMER_MODE_PINNED is suggested since vcpu may run in
>                  * the same physical cpu in next time
>                  */
>                 hrtimer_start(&vcpu->arch.swtimer, expire, HRTIMER_MODE_ABS_PINNED);
> -       } else if (vcpu->stat.generic.blocking) {
> -               /*
> -                * Inject timer interrupt so that halt polling can dectect and exit.
> -                * VCPU is scheduled out already and sleeps in rcuwait queue and
> -                * will not poll pending events again. kvm_queue_irq() is not enough,
> -                * hrtimer swtimer should be used here.
> -                */
> -               expire = ktime_add_ns(ktime_get(), 10);
> -               vcpu->arch.expire = expire;
> -               hrtimer_start(&vcpu->arch.swtimer, expire, HRTIMER_MODE_ABS_PINNED);
>         }
>  }
>
> --
> 2.39.3
>
  

Patch

diff --git a/arch/loongarch/kvm/timer.c b/arch/loongarch/kvm/timer.c
index 111328f60872..a9125f0a12d1 100644
--- a/arch/loongarch/kvm/timer.c
+++ b/arch/loongarch/kvm/timer.c
@@ -93,7 +93,8 @@  void kvm_restore_timer(struct kvm_vcpu *vcpu)
 	/*
 	 * Freeze the soft-timer and sync the guest stable timer with it.
 	 */
-	hrtimer_cancel(&vcpu->arch.swtimer);
+	if (kvm_vcpu_is_blocking(vcpu))
+		hrtimer_cancel(&vcpu->arch.swtimer);
 
 	/*
 	 * From LoongArch Reference Manual Volume 1 Chapter 7.6.2
@@ -168,26 +169,19 @@  static void _kvm_save_timer(struct kvm_vcpu *vcpu)
 	 * Here judge one-shot timer fired by checking whether TVAL is larger
 	 * than TCFG
 	 */
-	if (ticks < cfg) {
+	if (ticks < cfg)
 		delta = tick_to_ns(vcpu, ticks);
-		expire = ktime_add_ns(ktime_get(), delta);
-		vcpu->arch.expire = expire;
+	else
+		delta = 0;
+	expire = ktime_add_ns(ktime_get(), delta);
+	vcpu->arch.expire = expire;
+	if (kvm_vcpu_is_blocking(vcpu)) {
 
 		/*
 		 * HRTIMER_MODE_PINNED is suggested since vcpu may run in
 		 * the same physical cpu in next time
 		 */
 		hrtimer_start(&vcpu->arch.swtimer, expire, HRTIMER_MODE_ABS_PINNED);
-	} else if (vcpu->stat.generic.blocking) {
-		/*
-		 * Inject timer interrupt so that halt polling can dectect and exit.
-		 * VCPU is scheduled out already and sleeps in rcuwait queue and
-		 * will not poll pending events again. kvm_queue_irq() is not enough,
-		 * hrtimer swtimer should be used here.
-		 */
-		expire = ktime_add_ns(ktime_get(), 10);
-		vcpu->arch.expire = expire;
-		hrtimer_start(&vcpu->arch.swtimer, expire, HRTIMER_MODE_ABS_PINNED);
 	}
 }