@samitouri / QOSamiQemu / commits / 1505535e2a

hw/intc: riscv_aplic: Fix level trigger IRQ in direct delivery mode

According to the AIA spec ch4.7 ("Precise effects on interrupt-pending bits"), pending bit of APLIC should be set/cleared whenever the rectified input value is high/low in the both level-trigger mode and direct delivery mode. Currently, QEMU APLIC only clears the pending bit when interrupt is claimed in APLIC, but not clears it when the rectified input value is low. (e.g. IRQ source signal is low in the LEVEL_HIGH/Level1 mode). The software may receive an additional IRQ if the peripheral triggers one after the software clears the APLIC IRQ but before it clears the peripheral's IRQ. Thus, we also clear the pending bit via the rectified input value in the level-trigger mode. This change doesn't affect MSI delivery mode. Calling riscv_aplic_msi_irq_update() when IRQ pending is low will do nothing. Signed-off-by: Jim Shu <jim.shu@sifive.com> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260428160103.3551125-2-jim.shu@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

Jim Shu committed Apr 29, 2026 at 00:01 UTC 1505535e2a759d2863c6f9335fdce92ca46ccb45
1 file changed +4 -4
hw/intc/riscv_aplic.c
+4 -4
@@ -591,14 +591,14 @@ static void riscv_aplic_request(void *opaque, int irq, int level)
591 }
592 break;
593 case APLIC_SOURCECFG_SM_LEVEL_HIGH:
594 - if ((level > 0) && !(state & APLIC_ISTATE_PENDING)) {
595 - riscv_aplic_set_pending_raw(aplic, irq, true);
594 + if ((level > 0) != !!(state & APLIC_ISTATE_PENDING)) {
595 + riscv_aplic_set_pending_raw(aplic, irq, level > 0);
596 update = true;
597 }
598 break;
599 case APLIC_SOURCECFG_SM_LEVEL_LOW:
600 - if ((level <= 0) && !(state & APLIC_ISTATE_PENDING)) {
601 - riscv_aplic_set_pending_raw(aplic, irq, true);
600 + if ((level <= 0) != !!(state & APLIC_ISTATE_PENDING)) {
601 + riscv_aplic_set_pending_raw(aplic, irq, level <= 0);
602 update = true;
603 }
604 break;