On Mon, 2026-09-21 at 20:23 +0530, Mayuresh Chitale wrote:
> Commit 27f9566dcd98 dropped bits 13-15 from the LOCAL_INTERRUPTS
> macro and hence also from individual masks such as all_ints,
> sip_writable_mask etc.
> 
> As a result, even with sscofpmf and ssaia enabled, the LCOFI never
> got
> delivered to the host OS and guest OS respectively.
> 
> Add back bit 13 in all the affected masks, but gate it on Sscofpmf
> being
> implemented. For the virtual interrupt paths, i.e., mvip/mvien,
> hvip/hvien/vsip/vsie registers, bit 13 is additionally gated on Smaia
> and Ssaia respectively. Bits 14, 15 can be added when those interrupt
> sources get defined.
> 
> Fixes: 27f9566dcd98 ("target/riscv: Update the local interrupt mask")
> Reviewed-by: Daniel Henrique Barboza
> <[email protected]>
> Suggested-by: Gong Shuai <[email protected]>
> Suggested-by: TianCheng TANG <[email protected]>
> Signed-off-by: Mayuresh Chitale <[email protected]>

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  target/riscv/tcg/csr.c | 88 +++++++++++++++++++++++++++++++++++-----
> --
>  1 file changed, 73 insertions(+), 15 deletions(-)
> 
> diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c
> index 061bc9db77..a3351428cb 100644
> --- a/target/riscv/tcg/csr.c
> +++ b/target/riscv/tcg/csr.c
> @@ -1815,7 +1815,7 @@ static RISCVException
> write_stimecmph(CPURISCVState *env, int csrno,
>  #define LOCAL_INTERRUPTS   (~0xFFFFULL)
>  
>  static const uint64_t delegable_ints =
> -    S_MODE_INTERRUPTS | VS_MODE_INTERRUPTS | MIP_LCOFIP;
> +    S_MODE_INTERRUPTS | VS_MODE_INTERRUPTS;
>  static const uint64_t vs_delegable_ints =
>      (VS_MODE_INTERRUPTS | LOCAL_INTERRUPTS) & ~MIP_LCOFIP;
>  static const uint64_t all_ints = M_MODE_INTERRUPTS |
> S_MODE_INTERRUPTS |
> @@ -1877,6 +1877,42 @@ static const uint64_t hvien_writable_mask =
> LOCAL_INTERRUPTS;
>  
>  static const uint64_t vsip_writable_mask = MIP_VSSIP |
> LOCAL_INTERRUPTS;
>  
> +/*
> + * Selects the extensions that need to be checked when accessing
> various
> + * interrupt registers.
> + */
> +typedef enum {
> +    /* Accessing mideleg, mie, mip, and alias paths  */
> +    AIA_NONE,
> +    /* Accessing mvien, mvip non-alias path */
> +    AIA_SMAIA,
> +    /* Accessing hvien, hvip, vsie, vsip paths */
> +    AIA_SSAIA,
> +} AIAExt;
> +
> +/*
> + * This function can be extended later to configure mask for
> standard local
> + * interrupt bits 14 and 15, once those get defined in the Priv
> Spec.
> + */
> +static uint64_t std_impl_intr_mask(CPURISCVState *env, AIAExt ext)
> +{
> +    const RISCVCPUConfig *cfg = riscv_cpu_cfg(env);
> +
> +    if (ext == AIA_SMAIA && !cfg->ext_smaia) {
> +        return 0;
> +    }
> +
> +    if (ext == AIA_SSAIA && !cfg->ext_ssaia) {
> +        return 0;
> +    }
> +
> +    if (!cfg->ext_sscofpmf) {
> +        return 0;
> +    }
> +
> +    return MIP_LCOFIP;
> +}
> +
>  /* Machine Information Registers */
>  static RISCVException read_zero(CPURISCVState *env, int csrno,
>                                  target_ulong *val)
> @@ -2249,8 +2285,10 @@ static RISCVException
> rmw_mideleg64(CPURISCVState *env, int csrno,
>                                      uint64_t *ret_val,
>                                      uint64_t new_val, uint64_t
> wr_mask)
>  {
> +    uint64_t std_mask = std_impl_intr_mask(env, AIA_NONE);
>      uint64_t mask = wr_mask & delegable_ints;
>  
> +    mask |= wr_mask & std_mask;
>      if (ret_val) {
>          *ret_val = env->mideleg;
>      }
> @@ -2300,8 +2338,10 @@ static RISCVException rmw_mie64(CPURISCVState
> *env, int csrno,
>                                  uint64_t *ret_val,
>                                  uint64_t new_val, uint64_t wr_mask)
>  {
> +    uint64_t std_mask = std_impl_intr_mask(env, AIA_NONE);
>      uint64_t mask = wr_mask & all_ints;
>  
> +    mask |= wr_mask & std_mask;
>      if (ret_val) {
>          *ret_val = env->mie;
>      }
> @@ -2350,8 +2390,10 @@ static RISCVException
> rmw_mvien64(CPURISCVState *env, int csrno,
>                                  uint64_t *ret_val,
>                                  uint64_t new_val, uint64_t wr_mask)
>  {
> +    uint64_t std_mask = std_impl_intr_mask(env, AIA_SMAIA);
>      uint64_t mask = wr_mask & mvien_writable_mask;
>  
> +    mask |= wr_mask & std_mask;
>      if (ret_val) {
>          *ret_val = env->mvien;
>      }
> @@ -3784,9 +3826,12 @@ static RISCVException rmw_mip64(CPURISCVState
> *env, int csrno,
>                                  uint64_t *ret_val,
>                                  uint64_t new_val, uint64_t wr_mask)
>  {
> +    uint64_t std_mask = std_impl_intr_mask(env, AIA_NONE);
>      uint64_t old_mip, mask = wr_mask & delegable_ints;
>      uint32_t gin;
>  
> +    mask |= wr_mask & std_mask;
> +
>      /*
>       * When mvien[9]=1, mip.SEIP is read-only and reflects only
>       * the external interrupt signal from the interrupt controller.
> @@ -3900,9 +3945,12 @@ static RISCVException rmw_mvip64(CPURISCVState
> *env, int csrno,
>       *  alias_mask denotes the bits that come from mip nalias_mask
> denotes bits
>       *  that come from hvip.
>       */
> -    uint64_t alias_mask = ((S_MODE_INTERRUPTS | LOCAL_INTERRUPTS) &
> +    AIAExt intr_virt = ((csrno == CSR_MVIP) || (csrno == CSR_MVIPH))
> ?
> +                          AIA_SMAIA : AIA_NONE;
> +    uint64_t std_mask = std_impl_intr_mask(env, intr_virt);
> +    uint64_t alias_mask = ((S_MODE_INTERRUPTS | std_mask |
> LOCAL_INTERRUPTS) &
>          (env->mideleg | ~env->mvien)) | MIP_STIP;
> -    uint64_t nalias_mask = (S_MODE_INTERRUPTS | LOCAL_INTERRUPTS) &
> +    uint64_t nalias_mask = (S_MODE_INTERRUPTS | std_mask |
> LOCAL_INTERRUPTS) &
>          (~env->mideleg & env->mvien);
>      uint64_t wr_mask_mvip;
>      uint64_t wr_mask_mip;
> @@ -3931,8 +3979,8 @@ static RISCVException rmw_mvip64(CPURISCVState
> *env, int csrno,
>          alias_mask &= ~MIP_STIP;
>      }
>  
> -    wr_mask_mip = wr_mask & alias_mask & mvip_writable_mask;
> -    wr_mask_mvip = wr_mask & nalias_mask & mvip_writable_mask;
> +    wr_mask_mip = wr_mask & alias_mask & (mvip_writable_mask |
> std_mask);
> +    wr_mask_mvip = wr_mask & nalias_mask & (mvip_writable_mask |
> std_mask);
>  
>      /*
>       * For bits set in alias_mask, mvip needs to be alias of mip, so
> forward
> @@ -4065,9 +4113,11 @@ static RISCVException rmw_vsie64(CPURISCVState
> *env, int csrno,
>                                   uint64_t *ret_val,
>                                   uint64_t new_val, uint64_t wr_mask)
>  {
> -    uint64_t alias_mask = (LOCAL_INTERRUPTS | VS_MODE_INTERRUPTS) &
> -                            env->hideleg;
> -    uint64_t nalias_mask = LOCAL_INTERRUPTS & (~env->hideleg & env-
> >hvien);
> +    uint64_t std_mask = std_impl_intr_mask(env, AIA_SSAIA);
> +    uint64_t alias_mask = (LOCAL_INTERRUPTS | VS_MODE_INTERRUPTS |
> +                           std_mask) & env->hideleg;
> +    uint64_t nalias_mask = (LOCAL_INTERRUPTS | std_mask) &
> +                           (~env->hideleg & env->hvien);
>      uint64_t rval, rval_vs, vsbits;
>      uint64_t wr_mask_vsie;
>      uint64_t wr_mask_mie;
> @@ -4135,9 +4185,11 @@ static RISCVException rmw_sie64(CPURISCVState
> *env, int csrno,
>                                  uint64_t *ret_val,
>                                  uint64_t new_val, uint64_t wr_mask)
>  {
> -    uint64_t nalias_mask = (S_MODE_INTERRUPTS | LOCAL_INTERRUPTS) &
> +    uint64_t std_mask = std_impl_intr_mask(env, AIA_NONE);
> +    uint64_t nalias_mask = (S_MODE_INTERRUPTS | std_mask |
> LOCAL_INTERRUPTS) &
>          (~env->mideleg & env->mvien);
> -    uint64_t alias_mask = (S_MODE_INTERRUPTS | LOCAL_INTERRUPTS) &
> env->mideleg;
> +    uint64_t alias_mask = (S_MODE_INTERRUPTS | std_mask |
> LOCAL_INTERRUPTS) &
> +        env->mideleg;
>      uint64_t sie_mask = wr_mask & nalias_mask;
>      RISCVException ret;
>  
> @@ -4320,6 +4372,7 @@ static RISCVException rmw_vsip64(CPURISCVState
> *env, int csrno,
>                                   uint64_t new_val, uint64_t wr_mask)
>  {
>      RISCVException ret;
> +    uint64_t std_mask = std_impl_intr_mask(env, AIA_SSAIA);
>      uint64_t rval, mask = env->hideleg & VS_MODE_INTERRUPTS;
>      uint64_t vsbits;
>  
> @@ -4335,7 +4388,7 @@ static RISCVException rmw_vsip64(CPURISCVState
> *env, int csrno,
>      wr_mask |= vsbits << 1;
>  
>      ret = rmw_hvip64(env, csrno, &rval, new_val,
> -                     wr_mask & mask & vsip_writable_mask);
> +                     wr_mask & mask & (vsip_writable_mask |
> std_mask));
>      if (ret_val) {
>          rval &= mask;
>          vsbits = rval & VS_MODE_INTERRUPTS;
> @@ -4382,7 +4435,9 @@ static RISCVException rmw_sip64(CPURISCVState
> *env, int csrno,
>                                  uint64_t new_val, uint64_t wr_mask)
>  {
>      RISCVException ret;
> -    uint64_t mask = (env->mideleg | env->mvien) & sip_writable_mask;
> +    uint64_t std_mask = std_impl_intr_mask(env, AIA_NONE);
> +    uint64_t mask = (env->mideleg | env->mvien) &
> +                    (sip_writable_mask | std_mask);
>  
>      if (env->virt_enabled) {
>          if (env->hvictl & HVICTL_VTI) {
> @@ -4395,7 +4450,7 @@ static RISCVException rmw_sip64(CPURISCVState
> *env, int csrno,
>  
>      if (ret_val) {
>          *ret_val &= (env->mideleg | env->mvien) &
> -            (S_MODE_INTERRUPTS | LOCAL_INTERRUPTS);
> +            (S_MODE_INTERRUPTS | std_mask | LOCAL_INTERRUPTS);
>      }
>  
>      return ret;
> @@ -4737,7 +4792,9 @@ static RISCVException rmw_hvien64(CPURISCVState
> *env, int csrno,
>                                      uint64_t new_val, uint64_t
> wr_mask)
>  {
>      uint64_t mask = wr_mask & hvien_writable_mask;
> +    uint64_t std_mask = std_impl_intr_mask(env, AIA_SSAIA);
>  
> +    mask |= wr_mask & std_mask;
>      if (ret_val) {
>          *ret_val = env->hvien;
>      }
> @@ -4861,6 +4918,7 @@ static RISCVException rmw_hvip64(CPURISCVState
> *env, int csrno,
>       */
>      uint64_t alias_mask = (env->hideleg | ~env->hvien) |
> VS_MODE_INTERRUPTS;
>      uint64_t nalias_mask = (~env->hideleg & env->hvien);
> +    uint64_t std_mask = std_impl_intr_mask(env, AIA_SSAIA);
>      uint64_t wr_mask_hvip;
>      uint64_t wr_mask_mip;
>  
> @@ -4882,8 +4940,8 @@ static RISCVException rmw_hvip64(CPURISCVState
> *env, int csrno,
>          alias_mask &= (env->hideleg | env->hvien);
>      }
>  
> -    wr_mask_hvip = wr_mask & nalias_mask & hvip_writable_mask;
> -    wr_mask_mip = wr_mask & alias_mask & hvip_writable_mask;
> +    wr_mask_hvip = wr_mask & nalias_mask & (hvip_writable_mask |
> std_mask);
> +    wr_mask_mip = wr_mask & alias_mask & (hvip_writable_mask |
> std_mask);
>  
>      /* Aliased bits, bits 10, 6, 2 need to come from mip. */
>      ret = rmw_mip64(env, csrno, &ret_mip, new_val, wr_mask_mip);

Reply via email to