]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
LoongArch: KVM: Move unconditional delay into timer clear scenery
authorBibo Mao <maobibo@loongson.cn>
Mon, 4 May 2026 01:00:48 +0000 (09:00 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 14 May 2026 13:31:19 +0000 (15:31 +0200)
commit 5a873d77ba792410a796595a917be6a440f9b7d2 upstream.

When timer interrupt arrives in guest kernel, guest kernel clears the
timer interrupt and program timer with the next incoming event.

During this stage, timer tick is -1 and timer interrupt status is
disabled in ESTAT register. KVM hypervisor need write zero with timer
tick register and wait timer interrupt injection from HW side, and
then clear timer interrupt.

So there is 2 cycle delay in KVM hypervisor to emulate such scenery,
and the delay is unnecessary if there is no need to clear the timer
interrupt.

Here move 2 cycle delay into timer clear scenery and add timer ESTAT
checking after delay, and set max timer expire value if timer interrupt
does not arrive still.

Cc: stable@vger.kernel.org
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/loongarch/kvm/timer.c

index 29c2aaba63c33b9988f4f1e6dd4eec865afb8e9a..8356fce0043f6093a1e61d669871201c17e4859f 100644 (file)
@@ -96,15 +96,21 @@ void kvm_restore_timer(struct kvm_vcpu *vcpu)
                 * and set CSR TVAL with -1
                 */
                write_gcsr_timertick(0);
-               __delay(2); /* Wait cycles until timer interrupt injected */
 
                /*
                 * Writing CSR_TINTCLR_TI to LOONGARCH_CSR_TINTCLR will clear
                 * timer interrupt, and CSR TVAL keeps unchanged with -1, it
                 * avoids spurious timer interrupt
                 */
-               if (!(estat & CPU_TIMER))
+               if (!(estat & CPU_TIMER)) {
+                       __delay(2); /* Wait cycles until timer interrupt injected */
+
+                       /* Write TVAL with max value if no TI shot */
+                       estat = kvm_read_hw_gcsr(LOONGARCH_CSR_ESTAT);
+                       if (!(estat & CPU_TIMER))
+                               write_gcsr_timertick(CSR_TCFG_VAL);
                        gcsr_write(CSR_TINTCLR_TI, LOONGARCH_CSR_TINTCLR);
+               }
                return;
        }