[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] riscv/target: fix vs interrupt delegation

From: Jose Martins
Subject: [PATCH] riscv/target: fix vs interrupt delegation
Date: Tue, 28 Jan 2020 17:12:35 +0000
User-agent: NeoMutt/20171215


I've been having an issue delegating external interrupts to VS mode. I've set
the VSEI bit in hideleg. Then, to trigger the interrupt I set the VSEIP bit in
hip. However, this does not forward the external interrupt to VS mode, but to
HS mode.

Looking through the code, I see the VS to S interrupt cause translation is done
in riscv_cpu_local_irq_pending by immediately shifting right the pending vs
interrupts. So, this function will return the same cause either this is a HS
interrupt or a VS interrupt. Later, in riscv_cpu_do_interrupt, this is not
taken into account when checking the pending interrupt against the hypervisor
interrupt delegation register (hideleg). There will never be a match as the 
supervisor interrupt cannot be delegated to VS mode.

I believe an easy fix is to delay the cause translation until we know this
is indeed a delegated VS mode interrupt. Here is a patch:

Signed-off-by: José Martins <address@hidden>
 target/riscv/cpu_helper.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 7166e6199e..161dc34e0d 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -46,7 +46,7 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
     target_ulong pending = env->mip & env->mie &
                                ~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
     target_ulong vspending = (env->mip & env->mie &
-                              (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)) >> 1;
+                              (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP));

     target_ulong mie    = env->priv < PRV_M ||
                           (env->priv == PRV_M && mstatus_mie);
@@ -892,6 +892,9 @@ void riscv_cpu_do_interrupt(CPUState *cs)
             if (riscv_cpu_virt_enabled(env) && ((hdeleg >> cause) & 1) &&
                 !riscv_cpu_force_hs_excep_enabled(env)) {
                 /* Trap to VS mode */
+                if(async){
+                    cause -= 1;
+                }
             } else if (riscv_cpu_virt_enabled(env)) {
                 /* Trap into HS mode, from virt */


reply via email to

[Prev in Thread] Current Thread [Next in Thread]