[PATCH 1/2] hw/intc/riscv_aplic: Fix setipnum_le write emulation for APLIC MSI-mode

Anup Patel posted 2 patches 8 months, 3 weeks ago
Maintainers: Palmer Dabbelt <palmer@dabbelt.com>, Alistair Francis <alistair.francis@wdc.com>, Bin Meng <bin.meng@windriver.com>, Weiwei Li <liwei1518@gmail.com>, Daniel Henrique Barboza <dbarboza@ventanamicro.com>, Liu Zhiwei <zhiwei_liu@linux.alibaba.com>
[PATCH 1/2] hw/intc/riscv_aplic: Fix setipnum_le write emulation for APLIC MSI-mode
Posted by Anup Patel 8 months, 3 weeks ago
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>
---
 hw/intc/riscv_aplic.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index e98e258deb..775bb96164 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);
 }
 
-- 
2.34.1


Re: [PATCH 1/2] hw/intc/riscv_aplic: Fix setipnum_le write emulation for APLIC MSI-mode
Posted by Daniel Henrique Barboza 8 months, 3 weeks ago

On 3/6/24 06:57, Anup Patel wrote:
> 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>

>   hw/intc/riscv_aplic.c | 20 ++++++++++++++++----
>   1 file changed, 16 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
> index e98e258deb..775bb96164 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);
>   }
>