summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTENGZIJUN <[email protected]>2026-11-10 16:58:20 +0800
committerGitHub <[email protected]>2026-11-10 16:58:20 +0800
commitf50c9bf7fbfcd2cc5eb7990b82464c0331868fb7 (patch)
tree6d26854171bc2e53631a8f7f51649676d87ebf1c
parentaee8d01b15a6613cb3b3650927193843058e62a0 (diff)
Fix APLIC MSI retriggering for deasserted level interrupts #11966HEADmaster
-rw-r--r--libcpu/risc-v/common/pic/pic-riscv-aplic.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/libcpu/risc-v/common/pic/pic-riscv-aplic.c b/libcpu/risc-v/common/pic/pic-riscv-aplic.c
index 8cc1d39997..9482809dee 100644
--- a/libcpu/risc-v/common/pic/pic-riscv-aplic.c
+++ b/libcpu/risc-v/common/pic/pic-riscv-aplic.c
@@ -236,12 +236,25 @@ static void aplic_irq_mask(struct rt_pic_irq *pirq)
static void aplic_msi_irq_eoi(struct rt_pic_irq *pirq)
{
struct riscv_aplic *aplic = pirq->pic->priv_data;
+ rt_uint32_t input;
switch (pirq->mode)
{
case RT_IRQ_MODE_LEVEL_HIGH:
case RT_IRQ_MODE_LEVEL_LOW:
- HWREG32(aplic->regs + APLIC_SETIPNUM_LE) = pirq->hwirq;
+ /*
+ * in_clrip reads the rectified input, including source polarity.
+ * Retrigger only while the device still asserts its interrupt.
+ * Older QEMU versions also set pending for deasserted inputs on
+ * setipnum_le writes, causing an endless stream of spurious MSIs.
+ */
+ input = HWREG32(aplic->regs + APLIC_CLRIP_BASE +
+ (pirq->hwirq / APLIC_IRQBITS_PER_REG) * sizeof(rt_uint32_t));
+
+ if (input & RT_BIT(pirq->hwirq % APLIC_IRQBITS_PER_REG))
+ {
+ HWREG32(aplic->regs + APLIC_SETIPNUM_LE) = pirq->hwirq;
+ }
break;
default: