aboutsummaryrefslogtreecommitdiff
path: root/hw/intc
diff options
context:
space:
mode:
authorAnup Patel <apatel@ventanamicro.com>2024-03-06 15:27:21 +0530
committerAlistair Francis <alistair.francis@wdc.com>2024-03-08 20:48:03 +1000
commitbf31cf06eb5e709a1a7b082dc7956baadc4b70fa (patch)
treeb8ac06e1713f8c488248be60c950718b9449fc24 /hw/intc
parent938dd05ea1f3a9e3c713b1d73dc2992d62efb830 (diff)
downloadqemu-bf31cf06eb5e709a1a7b082dc7956baadc4b70fa.zip
qemu-bf31cf06eb5e709a1a7b082dc7956baadc4b70fa.tar.gz
qemu-bf31cf06eb5e709a1a7b082dc7956baadc4b70fa.tar.bz2
hw/intc/riscv_aplic: Fix setipnum_le write emulation for APLIC MSI-mode
The writes to setipnum_le register in APLIC MSI-mode have special consideration for level-triggered interrupts as-per section "4.9.2 Special consideration for level-sensitive interrupt sources" of the RISC-V AIA specification. Particularly, the below text from the RISC-V specification defines the behaviour of writes to setipnum_le for level-triggered interrupts: "A second option is for the interrupt service routine to write the APLIC’s source identity number for the interrupt to the domain’s setipnum register just before exiting. This will cause the interrupt’s pending bit to be set to one again if the source is still asserting an interrupt, but not if the source is not asserting an interrupt." Fix setipnum_le write emulation for APLIC MSI-mode by implementing the above behaviour in riscv_aplic_set_pending() function. Fixes: e8f79343cfc8 ("hw/intc: Add RISC-V AIA APLIC device emulation") Signed-off-by: Anup Patel <apatel@ventanamicro.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Message-ID: <20240306095722.463296-2-apatel@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Diffstat (limited to 'hw/intc')
-rw-r--r--hw/intc/riscv_aplic.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index e98e258..775bb96 100644
--- a/hw/intc/riscv_aplic.c
+++ b/hw/intc/riscv_aplic.c
@@ -218,13 +218,25 @@ static void riscv_aplic_set_pending(RISCVAPLICState *aplic,
}
sm = sourcecfg & APLIC_SOURCECFG_SM_MASK;
- if ((sm == APLIC_SOURCECFG_SM_INACTIVE) ||
- ((!aplic->msimode || (aplic->msimode && !pending)) &&
- ((sm == APLIC_SOURCECFG_SM_LEVEL_HIGH) ||
- (sm == APLIC_SOURCECFG_SM_LEVEL_LOW)))) {
+ if (sm == APLIC_SOURCECFG_SM_INACTIVE) {
return;
}
+ if ((sm == APLIC_SOURCECFG_SM_LEVEL_HIGH) ||
+ (sm == APLIC_SOURCECFG_SM_LEVEL_LOW)) {
+ if (!aplic->msimode || (aplic->msimode && !pending)) {
+ return;
+ }
+ if ((aplic->state[irq] & APLIC_ISTATE_INPUT) &&
+ (sm == APLIC_SOURCECFG_SM_LEVEL_LOW)) {
+ return;
+ }
+ if (!(aplic->state[irq] & APLIC_ISTATE_INPUT) &&
+ (sm == APLIC_SOURCECFG_SM_LEVEL_HIGH)) {
+ return;
+ }
+ }
+
riscv_aplic_set_pending_raw(aplic, irq, pending);
}