[PATCH 2/2] hw/intc/riscv_aplic: Fix in_clrip[x] read emulation

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 2/2] hw/intc/riscv_aplic: Fix in_clrip[x] read emulation
Posted by Anup Patel 8 months, 3 weeks ago
The reads to in_clrip[x] registers return rectified input values of the
interrupt sources.

A rectified input value of an interrupt source is defined by the section
"4.5.2 Source configurations (sourcecfg[1]–sourcecfg[1023])" of the RISC-V
AIA specification as:
"rectified input value = (incoming wire value) XOR (source is inverted)"

Update the riscv_aplic_read_input_word() implementation to match the above.

Fixes: e8f79343cfc8 ("hw/intc: Add RISC-V AIA APLIC device emulation")
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 hw/intc/riscv_aplic.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index 775bb96164..6a7fbfa861 100644
--- a/hw/intc/riscv_aplic.c
+++ b/hw/intc/riscv_aplic.c
@@ -162,7 +162,7 @@ static bool is_kvm_aia(bool msimode)
 static uint32_t riscv_aplic_read_input_word(RISCVAPLICState *aplic,
                                             uint32_t word)
 {
-    uint32_t i, irq, ret = 0;
+    uint32_t i, irq, sourcecfg, sm, raw_input, irq_inverted, ret = 0;
 
     for (i = 0; i < 32; i++) {
         irq = word * 32 + i;
@@ -170,7 +170,20 @@ static uint32_t riscv_aplic_read_input_word(RISCVAPLICState *aplic,
             continue;
         }
 
-        ret |= ((aplic->state[irq] & APLIC_ISTATE_INPUT) ? 1 : 0) << i;
+        sourcecfg = aplic->sourcecfg[irq];
+        if (sourcecfg & APLIC_SOURCECFG_D) {
+            continue;
+        }
+
+        sm = sourcecfg & APLIC_SOURCECFG_SM_MASK;
+        if (sm == APLIC_SOURCECFG_SM_INACTIVE) {
+            continue;
+        }
+
+        raw_input = (aplic->state[irq] & APLIC_ISTATE_INPUT) ? 1 : 0;
+        irq_inverted = (sm == APLIC_SOURCECFG_SM_LEVEL_LOW ||
+                        sm == APLIC_SOURCECFG_SM_EDGE_FALL) ? 1 : 0;
+        ret |= (raw_input ^ irq_inverted) << i;
     }
 
     return ret;
-- 
2.34.1


Re: [PATCH 2/2] hw/intc/riscv_aplic: Fix in_clrip[x] read emulation
Posted by Daniel Henrique Barboza 8 months, 3 weeks ago

On 3/6/24 06:57, Anup Patel wrote:
> The reads to in_clrip[x] registers return rectified input values of the
> interrupt sources.
> 
> A rectified input value of an interrupt source is defined by the section
> "4.5.2 Source configurations (sourcecfg[1]–sourcecfg[1023])" of the RISC-V
> AIA specification as:
> "rectified input value = (incoming wire value) XOR (source is inverted)"
> 
> Update the riscv_aplic_read_input_word() implementation to match the above.
> 
> 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 | 17 +++++++++++++++--
>   1 file changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
> index 775bb96164..6a7fbfa861 100644
> --- a/hw/intc/riscv_aplic.c
> +++ b/hw/intc/riscv_aplic.c
> @@ -162,7 +162,7 @@ static bool is_kvm_aia(bool msimode)
>   static uint32_t riscv_aplic_read_input_word(RISCVAPLICState *aplic,
>                                               uint32_t word)
>   {
> -    uint32_t i, irq, ret = 0;
> +    uint32_t i, irq, sourcecfg, sm, raw_input, irq_inverted, ret = 0;
>   
>       for (i = 0; i < 32; i++) {
>           irq = word * 32 + i;
> @@ -170,7 +170,20 @@ static uint32_t riscv_aplic_read_input_word(RISCVAPLICState *aplic,
>               continue;
>           }
>   
> -        ret |= ((aplic->state[irq] & APLIC_ISTATE_INPUT) ? 1 : 0) << i;
> +        sourcecfg = aplic->sourcecfg[irq];
> +        if (sourcecfg & APLIC_SOURCECFG_D) {
> +            continue;
> +        }
> +
> +        sm = sourcecfg & APLIC_SOURCECFG_SM_MASK;
> +        if (sm == APLIC_SOURCECFG_SM_INACTIVE) {
> +            continue;
> +        }
> +
> +        raw_input = (aplic->state[irq] & APLIC_ISTATE_INPUT) ? 1 : 0;
> +        irq_inverted = (sm == APLIC_SOURCECFG_SM_LEVEL_LOW ||
> +                        sm == APLIC_SOURCECFG_SM_EDGE_FALL) ? 1 : 0;
> +        ret |= (raw_input ^ irq_inverted) << i;
>       }
>   
>       return ret;