Route MIP reads in the interrupt, CSR, ACLINT and pending-IRQ code through a single riscv_cpu_get_mip() accessor, so the implementation can change in one place.
riscv_cpu_update_mip() now reads the old value under the BQL, so the returned value matches the one written. Signed-off-by: Philippe Mathieu-Daudé <[email protected]> --- target/riscv/cpu.h | 7 +++++++ hw/intc/riscv_aclint.c | 2 +- target/riscv/cpu.c | 8 +++++++- target/riscv/tcg/cpu_helper.c | 12 +++++++----- target/riscv/tcg/csr.c | 6 ++++-- 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index e34c0c676d5..ad731bf5d34 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -684,6 +684,13 @@ bool riscv_cpu_translate_for_debug(CPUState *cs, vaddr addr, bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request); void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env); int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts); +/** + * riscv_cpu_get_mip: + * @env: CPURISCVState + * + * Returns: the current value of the Machine Interrupt Pending (MIP) register. + */ +uint64_t riscv_cpu_get_mip(const CPURISCVState *env); /** * riscv_cpu_update_mip: * @env: CPURISCVState diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c index 2d133d0dcf9..4bd359c3380 100644 --- a/hw/intc/riscv_aclint.c +++ b/hw/intc/riscv_aclint.c @@ -438,7 +438,7 @@ static uint64_t riscv_aclint_swi_read(void *opaque, hwaddr addr, qemu_log_mask(LOG_GUEST_ERROR, "aclint-swi: invalid hartid: %zu", hartid); } else if ((addr & 0x3) == 0) { - return (swi->sswi) ? 0 : ((env->mip & MIP_MSIP) > 0); + return (swi->sswi) ? 0 : ((riscv_cpu_get_mip(env) & MIP_MSIP) > 0); } } diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index da4c1a090b9..b8d6f992ba4 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -916,8 +916,9 @@ 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; uint64_t vstip = (env->vstime_irq) ? MIP_VSTIP : 0; + uint64_t mip = riscv_cpu_get_mip(env); - return (env->mip | vsgein | vstip) & env->mie; + return (mip | vsgein | vstip) & env->mie; } int riscv_cpu_mirq_pending(CPURISCVState *env) @@ -953,6 +954,11 @@ int riscv_cpu_vsirq_pending(CPURISCVState *env) (irqs | irqs_f_vs), env->hviprio); } +uint64_t riscv_cpu_get_mip(const CPURISCVState *env) +{ + return env->mip; +} + bool riscv_cpu_has_work(CPUState *cs) { RISCVCPU *cpu = RISCV_CPU(cs); diff --git a/target/riscv/tcg/cpu_helper.c b/target/riscv/tcg/cpu_helper.c index 91f5eb72930..f8f779a01d8 100644 --- a/target/riscv/tcg/cpu_helper.c +++ b/target/riscv/tcg/cpu_helper.c @@ -567,7 +567,7 @@ void riscv_cpu_interrupt(CPURISCVState *env) vstip = env->vstime_irq ? MIP_VSTIP : 0; - if (env->mip | vsgein | vstip | irqf) { + if (riscv_cpu_get_mip(env) | vsgein | vstip | irqf) { cpu_interrupt(cs, CPU_INTERRUPT_HARD); } else { cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); @@ -576,14 +576,15 @@ void riscv_cpu_interrupt(CPURISCVState *env) uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask, uint64_t value) { - uint64_t old = env->mip; + uint64_t old; /* No need to update mip for VSTIP */ mask = ((mask == MIP_VSTIP) && env->vstime_irq) ? 0 : mask; BQL_LOCK_GUARD(); - env->mip = (env->mip & ~mask) | (value & mask); + old = riscv_cpu_get_mip(env); + env->mip = (old & ~mask) | (value & mask); riscv_cpu_interrupt(env); @@ -2061,10 +2062,11 @@ void riscv_cpu_do_interrupt(CPUState *cs) bool async = !!(cs->exception_index & RISCV_EXCP_INT_FLAG); target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK; uint64_t deleg = async ? env->mideleg : env->medeleg; + uint64_t mip = riscv_cpu_get_mip(env); bool s_injected = env->mvip & (1ULL << cause) & env->mvien && - !(env->mip & (1ULL << cause)); + !(mip & (1ULL << cause)); bool vs_injected = env->hvip & (1ULL << cause) & env->hvien && - !(env->mip & (1ULL << cause)); + !(mip & (1ULL << cause)); bool smode_double_trap = false; uint64_t hdeleg = async ? env->hideleg : env->hedeleg; const bool prev_virt = env->virt_enabled; diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c index 061bc9db77b..a0e32f14276 100644 --- a/target/riscv/tcg/csr.c +++ b/target/riscv/tcg/csr.c @@ -3816,7 +3816,7 @@ static RISCVException rmw_mip64(CPURISCVState *env, int csrno, if (mask) { old_mip = riscv_cpu_update_mip(env, mask, (new_val & mask)); } else { - old_mip = env->mip; + old_mip = riscv_cpu_get_mip(env); } if (csrno != CSR_HVIP) { @@ -4549,8 +4549,10 @@ static RISCVException read_vstopi(CPURISCVState *env, int csrno, hviprio = get_field(env->hvictl, HVICTL_IPRIO); if (gein) { + uint64_t mip = riscv_cpu_get_mip(env); + vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0; - vseip = env->mie & (env->mip | vsgein) & MIP_VSEIP; + vseip = env->mie & (mip | vsgein) & MIP_VSEIP; if (gein <= env->geilen && vseip) { siid[scount] = IRQ_S_EXT; siprio[scount] = IPRIO_MMAXIPRIO + 1; -- 2.55.0
