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

Andrew S. Rightenburg via qemu development posted 1 patch 2 weeks ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260415111738.3264448-1-andrew@rail5.org
Maintainers: Song Gao <gaosong@loongson.cn>
target/loongarch/tcg/csr_helper.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
[PATCH] target/loongarch: Fix SWI interrupt delivery via CSR_ESTAT
Posted by Andrew S. Rightenburg via qemu development 2 weeks ago
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 <andrew@rail5.org>
Signed-off-by: Andrew S. Rightenburg <andrew@rail5.org>
---
 target/loongarch/tcg/csr_helper.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/target/loongarch/tcg/csr_helper.c b/target/loongarch/tcg/csr_helper.c
index cd35ca93c7..0a5ed52eb6 100644
--- a/target/loongarch/tcg/csr_helper.c
+++ b/target/loongarch/tcg/csr_helper.c
@@ -98,10 +98,22 @@ target_ulong helper_csrrd_msgir(CPULoongArchState *env)
 target_ulong helper_csrwr_estat(CPULoongArchState *env, target_ulong val)
 {
     int64_t old_v = env->CSR_ESTAT;
+    CPUState *cs = env_cpu(env);
 
     /* Only IS[1:0] can be written */
     env->CSR_ESTAT = deposit64(env->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 (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
+        bql_lock();
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+        bql_unlock();
+    }
+
     return old_v;
 }
 
-- 
2.47.3