[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <564a2fd3-ffba-3bc5-70b9-8a9fa9a0f1c6@loongson.cn>
Date: Mon, 4 Dec 2023 16:48:01 +0800
From: zhaotianrui <zhaotianrui@...ngson.cn>
To: Bibo Mao <maobibo@...ngson.cn>, Huacai Chen <chenhuacai@...nel.org>
Cc: WANG Xuerui <kernel@...0n.name>, kvm@...r.kernel.org,
loongarch@...ts.linux.dev, linux-kernel@...r.kernel.org
Subject: Re: [PATCH v4 1/3] LoongArch: KVM: Remove SW timer switch when vcpu
is halt polling
Reviewed-by: Tianrui Zhao <zhaotianrui@...ngson.cn>
在 2023/11/16 上午10:30, Bibo Mao 写道:
> With halt-polling supported, there is checking for pending events
> or interrupts when vcpu executes idle instruction. Pending interrupts
> include injected SW interrupts and passthrough HW interrupts, such as
> HW timer interrupts, since HW timer works still even if vcpu exists
> from VM mode.
>
> Since HW timer pending interrupt can be set directly with CSR status
> register, and pending HW timer interrupt checking is used in vcpu block
> checking function, it is not necessary to switch to sw timer during
> halt-polling. This patch adds preemption disabling in function
> kvm_cpu_has_pending_timer, and removes SW timer switching in idle
> instruction emulation function.
>
> Signed-off-by: Bibo Mao <maobibo@...ngson.cn>
> ---
> arch/loongarch/kvm/exit.c | 13 ++-----------
> arch/loongarch/kvm/timer.c | 13 ++++++++++---
> arch/loongarch/kvm/vcpu.c | 9 ++++++++-
> 3 files changed, 20 insertions(+), 15 deletions(-)
>
> diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
> index ce8de3fa472c..e708a1786d6b 100644
> --- a/arch/loongarch/kvm/exit.c
> +++ b/arch/loongarch/kvm/exit.c
> @@ -200,17 +200,8 @@ int kvm_emu_idle(struct kvm_vcpu *vcpu)
> ++vcpu->stat.idle_exits;
> trace_kvm_exit_idle(vcpu, KVM_TRACE_EXIT_IDLE);
>
> - if (!kvm_arch_vcpu_runnable(vcpu)) {
> - /*
> - * Switch to the software timer before halt-polling/blocking as
> - * the guest's timer may be a break event for the vCPU, and the
> - * hypervisor timer runs only when the CPU is in guest mode.
> - * Switch before halt-polling so that KVM recognizes an expired
> - * timer before blocking.
> - */
> - kvm_save_timer(vcpu);
> - kvm_vcpu_block(vcpu);
> - }
> + if (!kvm_arch_vcpu_runnable(vcpu))
> + kvm_vcpu_halt(vcpu);
>
> return EMULATE_DONE;
> }
> diff --git a/arch/loongarch/kvm/timer.c b/arch/loongarch/kvm/timer.c
> index 284bf553fefe..437e960d8fdb 100644
> --- a/arch/loongarch/kvm/timer.c
> +++ b/arch/loongarch/kvm/timer.c
> @@ -155,11 +155,18 @@ static void _kvm_save_timer(struct kvm_vcpu *vcpu)
> */
> hrtimer_cancel(&vcpu->arch.swtimer);
> hrtimer_start(&vcpu->arch.swtimer, expire, HRTIMER_MODE_ABS_PINNED);
> - } else
> + } else if (vcpu->stat.generic.blocking) {
> /*
> - * Inject timer interrupt so that hall polling can dectect and exit
> + * Inject timer interrupt so that hall 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.
> */
> - kvm_queue_irq(vcpu, INT_TI);
> + expire = ktime_add_ns(ktime_get(), 10); // 10ns is enough here?
> + vcpu->arch.expire = expire;
> + hrtimer_start(&vcpu->arch.swtimer, expire, HRTIMER_MODE_ABS_PINNED);
> + }
> }
>
> /*
> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
> index 73d0c2b9c1a5..42663a345bd1 100644
> --- a/arch/loongarch/kvm/vcpu.c
> +++ b/arch/loongarch/kvm/vcpu.c
> @@ -187,8 +187,15 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
>
> int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
> {
> - return kvm_pending_timer(vcpu) ||
> + int ret;
> +
> + /* protect from TOD sync and vcpu_load/put */
> + preempt_disable();
> + ret = kvm_pending_timer(vcpu) ||
> kvm_read_hw_gcsr(LOONGARCH_CSR_ESTAT) & (1 << INT_TI);
> + preempt_enable();
> +
> + return ret;
> }
>
> int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu)
Powered by blists - more mailing lists