On Wed, 2026-09-30 at 19:45 +0200, Philippe Mathieu-Daudé wrote: > 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]>
Reviewed-by: Alistair Francis <[email protected]> Alistair > --- > 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;
