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;

Reply via email to