diff options
author | Andrew Bresticker <abrestic@rivosinc.com> | 2022-05-31 17:05:44 -0400 |
---|---|---|
committer | Alistair Francis <alistair.francis@wdc.com> | 2022-06-10 09:31:42 +1000 |
commit | 8f42415fc1d1bb462f2001bf5e2ad3b78f14b2e3 (patch) | |
tree | ce324aa7b30eb2a0d9688d07787483229c2781cc /target/riscv | |
parent | af9751316e53cdf7e98131afe6928a5f4445fe16 (diff) | |
download | qemu-8f42415fc1d1bb462f2001bf5e2ad3b78f14b2e3.zip qemu-8f42415fc1d1bb462f2001bf5e2ad3b78f14b2e3.tar.gz qemu-8f42415fc1d1bb462f2001bf5e2ad3b78f14b2e3.tar.bz2 |
target/riscv: Wake on VS-level external interrupts
Whether or not VSEIP is pending isn't reflected in env->mip and must
instead be determined from hstatus.vgein and hgeip. As a result a
CPU in WFI won't wake on a VSEIP, which violates the WFI behavior as
specified in the privileged ISA. Just use riscv_cpu_all_pending()
instead, which already accounts for VSEIP.
Signed-off-by: Andrew Bresticker <abrestic@rivosinc.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-Id: <20220531210544.181322-1-abrestic@rivosinc.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Diffstat (limited to 'target/riscv')
-rw-r--r-- | target/riscv/cpu.c | 2 | ||||
-rw-r--r-- | target/riscv/cpu.h | 1 | ||||
-rw-r--r-- | target/riscv/cpu_helper.c | 2 |
3 files changed, 3 insertions, 2 deletions
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index bcbba3f..0497af4 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -391,7 +391,7 @@ static bool riscv_cpu_has_work(CPUState *cs) * Definition of the WFI instruction requires it to ignore the privilege * mode and delegation registers, but respect individual enables */ - return (env->mip & env->mie) != 0; + return riscv_cpu_all_pending(env) != 0; #else return true; #endif diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 890d33c..194a58d 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -489,6 +489,7 @@ int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); int riscv_cpu_hviprio_index2irq(int index, int *out_irq, int *out_rdzero); uint8_t riscv_cpu_default_priority(int irq); +uint64_t riscv_cpu_all_pending(CPURISCVState *env); int riscv_cpu_mirq_pending(CPURISCVState *env); int riscv_cpu_sirq_pending(CPURISCVState *env); int riscv_cpu_vsirq_pending(CPURISCVState *env); diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index d99fac9..16c6045 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -340,7 +340,7 @@ static int riscv_cpu_pending_to_irq(CPURISCVState *env, return best_irq; } -static uint64_t riscv_cpu_all_pending(CPURISCVState *env) +uint64_t riscv_cpu_all_pending(CPURISCVState *env) { uint32_t gein = get_field(env->hstatus, HSTATUS_VGEIN); uint64_t vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0; |