Re: [PATCH v2] target/loongarch: Fix SWI interrupt delivery via CSR_ESTAT

Song Gao <[email protected]> Wed, 5 Aug 2026 17:11:43 +0800
Newsgroups gmane.comp.emulators.qemu
Message-ID <[email protected]>
在 2026/8/5 下午4:47, Bibo Mao 写道:
> In TCG mode, helper_csrwr_estat() updates CSR.ESTAT.IS[1:0] (SWI0/SWI1)
> when the guest writes CSR_ESTAT, but it did not update the CPU interrupt
> request state. As a result, software interrupts could be observed as pending
> in CSR.ESTAT while no interrupt exception was taken.
>
> Update CPU_INTERRUPT_HARD after modifying CSR_ESTAT, matching the behavior of
> loongarch_cpu_set_irq(). The helper runs without the Big QEMU Lock (BQL), so
> take the BQL while calling cpu_interrupt().
>
> Fixes: 5b1dedfe848b ("target/loongarch: Add LoongArch CSR instruction")
> Reported-by: Andrew S. Rightenburg <[email protected]>
> Signed-off-by: Andrew S. Rightenburg <[email protected]>
> Signed-off-by: Bibo Mao <[email protected]>
> ---
>   target/loongarch/cpu.c            | 20 ++++++++++++++------
>   target/loongarch/internals.h      |  1 +
>   target/loongarch/tcg/csr_helper.c | 10 ++++++++++
>   3 files changed, 25 insertions(+), 6 deletions(-)

Reviewed-by:  Song Gao <[email protected]>

Thanks.
Song Gao
> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
> index fb03424ffa..4d9f7b08de 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -57,11 +57,23 @@ static vaddr loongarch_cpu_get_pc(CPUState *cs)
>   #ifndef CONFIG_USER_ONLY
>   #include "hw/loongarch/virt.h"
>   
> +void loongarch_cpu_update_irq(LoongArchCPU *cpu)
> +{
> +    CPULoongArchState *env = &cpu->env;
> +    CPUState *cs = CPU(cpu);
> +    CPUSysState *sys = env_sys(env);
> +
> +    if (FIELD_EX64(sys->CSR_ESTAT, CSR_ESTAT, IS)) {
> +        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
> +    } else {
> +        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
> +    }
> +}
> +
>   void loongarch_cpu_set_irq(void *opaque, int irq, int level)
>   {
>       LoongArchCPU *cpu = opaque;
>       CPULoongArchState *env = &cpu->env;
> -    CPUState *cs = CPU(cpu);
>       CPUSysState *sys = env_sys(env);
>   
>       if (irq < 0 || irq >= N_IRQS) {
> @@ -72,11 +84,7 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level)
>           kvm_loongarch_set_interrupt(cpu, irq, level);
>       } else if (tcg_enabled()) {
>           sys->CSR_ESTAT = deposit64(sys->CSR_ESTAT, irq, 1, level != 0);
> -        if (FIELD_EX64(sys->CSR_ESTAT, CSR_ESTAT, IS)) {
> -            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
> -        } else {
> -            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
> -        }
> +        loongarch_cpu_update_irq(cpu);
>       }
>   }
>   
> diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
> index e01dbed40f..40565ee91b 100644
> --- a/target/loongarch/internals.h
> +++ b/target/loongarch/internals.h
> @@ -31,6 +31,7 @@ void restore_fp_status(CPULoongArchState *env);
>   #ifndef CONFIG_USER_ONLY
>   extern const VMStateDescription vmstate_loongarch_cpu;
>   
> +void loongarch_cpu_update_irq(LoongArchCPU *cpu);
>   void loongarch_cpu_set_irq(void *opaque, int irq, int level);
>   
>   void loongarch_constant_timer_cb(void *opaque);
> diff --git a/target/loongarch/tcg/csr_helper.c b/target/loongarch/tcg/csr_helper.c
> index 7dc33bc180..a9db071098 100644
> --- a/target/loongarch/tcg/csr_helper.c
> +++ b/target/loongarch/tcg/csr_helper.c
> @@ -106,6 +106,16 @@ target_ulong helper_csrwr_estat(CPULoongArchState *env, target_ulong val)
>   
>       /* Only IS[1:0] can be written */
>       sys->CSR_ESTAT = deposit64(sys->CSR_ESTAT, 0, 2, val);
> +    /*
> +     * Software interrupts (SWI0/SWI1) are latched in CSR.ESTAT.IS[1:0].
> +     * Make sure the CPU interrupt request state tracks the pending bits,
> +     * matching the behavior of loongarch_cpu_set_irq().
> +     */
> +    if ((old_v ^ val) & 0x3) {
> +        bql_lock();
> +        loongarch_cpu_update_irq(env_archcpu(env));
> +        bql_unlock();
> +    }
>   
>       return old_v;
>   }
>
> base-commit: b428fe036233cbd15d37e3c027ab6ca4d3661a80