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