From cf08d74c2664472cc4fc29e065a27e54a92b8e70 Mon Sep 17 00:00:00 2001 From: Rajnesh Kanwal Date: Thu, 30 Apr 2020 06:20:48 -0400 Subject: [PATCH] target/riscv: Fix VS mode interrupts forwarding. Currently riscv_cpu_local_irq_pending is used to find out pending interrupt and VS mode interrupts are being shifted to represent S mode interrupts in this function. So when the cause returned by this function is passed to riscv_cpu_do_interrupt to actually forward the interrupt, the VS mode forwarding check does not work as intended and interrupt is actually forwarded to hypervisor. This patch fixes this issue. Backports commit c5969a3a3c2cb9ea02ffb7e86acb059d3cf8c264 from qemu --- qemu/target/riscv/cpu_helper.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/qemu/target/riscv/cpu_helper.c b/qemu/target/riscv/cpu_helper.c index 176a19ae..2246b07d 100644 --- a/qemu/target/riscv/cpu_helper.c +++ b/qemu/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); @@ -900,6 +900,13 @@ void riscv_cpu_do_interrupt(CPUState *cs) if (riscv_cpu_virt_enabled(env) && ((hdeleg >> cause) & 1) && !force_hs_execp) { + /* + * See if we need to adjust cause. Yes if its VS mode interrupt + * no if hypervisor has delegated one of hs mode's interrupt + */ + if (cause == IRQ_VS_TIMER || cause == IRQ_VS_SOFT || + cause == IRQ_VS_EXT) + cause = cause - 1; /* Trap to VS mode */ } else if (riscv_cpu_virt_enabled(env)) { /* Trap into HS mode, from virt */