Skip to content

Commit d8dd9f1

Browse files
committed
RISC-V: KVM: Fix APLIC setipnum_le/be write emulation
The writes to setipnum_le/be register for APLIC in MSI-mode have special consideration for level-triggered interrupts as-per the 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 AIA specification defines the behaviour of writes to setipnum_le/be register 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/be write emulation for in-kernel APLIC by implementing the above behaviour in aplic_write_pending() function. Cc: [email protected] Fixes: 74967aa ("RISC-V: KVM: Add in-kernel emulation of AIA APLIC") Signed-off-by: Anup Patel <[email protected]> Signed-off-by: Anup Patel <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 7fd99b7 commit d8dd9f1

File tree

1 file changed

+13
-3
lines changed

1 file changed

+13
-3
lines changed

arch/riscv/kvm/aia_aplic.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,21 @@ static void aplic_write_pending(struct aplic *aplic, u32 irq, bool pending)
137137
raw_spin_lock_irqsave(&irqd->lock, flags);
138138

139139
sm = irqd->sourcecfg & APLIC_SOURCECFG_SM_MASK;
140-
if (!pending &&
141-
((sm == APLIC_SOURCECFG_SM_LEVEL_HIGH) ||
142-
(sm == APLIC_SOURCECFG_SM_LEVEL_LOW)))
140+
if (sm == APLIC_SOURCECFG_SM_INACTIVE)
143141
goto skip_write_pending;
144142

143+
if (sm == APLIC_SOURCECFG_SM_LEVEL_HIGH ||
144+
sm == APLIC_SOURCECFG_SM_LEVEL_LOW) {
145+
if (!pending)
146+
goto skip_write_pending;
147+
if ((irqd->state & APLIC_IRQ_STATE_INPUT) &&
148+
sm == APLIC_SOURCECFG_SM_LEVEL_LOW)
149+
goto skip_write_pending;
150+
if (!(irqd->state & APLIC_IRQ_STATE_INPUT) &&
151+
sm == APLIC_SOURCECFG_SM_LEVEL_HIGH)
152+
goto skip_write_pending;
153+
}
154+
145155
if (pending)
146156
irqd->state |= APLIC_IRQ_STATE_PENDING;
147157
else

0 commit comments

Comments
 (0)