qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 3/4] target/riscv: Implement AIA local interrupt CSRs


From: Anup Patel
Subject: Re: [PATCH 3/4] target/riscv: Implement AIA local interrupt CSRs
Date: Fri, 11 Jun 2021 10:34:44 +0530

On Fri, Jun 11, 2021 at 4:49 AM Alistair Francis <alistair23@gmail.com> wrote:
>
> On Sat, May 15, 2021 at 12:34 AM Anup Patel <anup.patel@wdc.com> wrote:
> >
> > We implement various AIA local interrupt CSRs for M-mode, HS-mode,
> > and VS-mode.
> >
> > Signed-off-by: Anup Patel <anup.patel@wdc.com>
> > ---
> >  target/riscv/cpu.c        |   27 +-
> >  target/riscv/cpu.h        |   52 +-
> >  target/riscv/cpu_helper.c |  245 ++++++++-
> >  target/riscv/csr.c        | 1059 +++++++++++++++++++++++++++++++++++--
> >  target/riscv/machine.c    |   26 +-
> >  5 files changed, 1309 insertions(+), 100 deletions(-)
>
> I feel this patch could be split up more :)

This is patch is large because I did not want to break functionality.

I try again to break this patch. At the moment, the best I can do is
to break in to two parts.
1) AIA local interrupt CSRs without IMSIC
2) Extend AIA local interrupt CSRs to support IMSIC register access

>
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index f3702111ae..795162834b 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -256,11 +256,11 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE 
> > *f, int flags)
> >          qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ",
> >                       (target_ulong)env->vsstatus);
> >      }
> > -    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip     ", env->mip);
> > -    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie     ", env->mie);
> > -    qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg);
> > +    qemu_fprintf(f, " %s %016" PRIx64 "\n", "mip     ", env->mip);
> > +    qemu_fprintf(f, " %s %016" PRIx64 "\n", "mie     ", env->mie);
> > +    qemu_fprintf(f, " %s %016" PRIx64 "\n", "mideleg ", env->mideleg);
> >      if (riscv_has_ext(env, RVH)) {
> > -        qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hideleg ", 
> > env->hideleg);
> > +        qemu_fprintf(f, " %s %016" PRIx64 "\n", "hideleg ", env->hideleg);
> >      }
> >      qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg);
> >      if (riscv_has_ext(env, RVH)) {
> > @@ -345,6 +345,8 @@ void restore_state_to_opc(CPURISCVState *env, 
> > TranslationBlock *tb,
> >
> >  static void riscv_cpu_reset(DeviceState *dev)
> >  {
> > +    uint8_t iprio;
> > +    int i, irq, rdzero;
> >      CPUState *cs = CPU(dev);
> >      RISCVCPU *cpu = RISCV_CPU(cs);
> >      RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
> > @@ -357,6 +359,23 @@ static void riscv_cpu_reset(DeviceState *dev)
> >      env->mcause = 0;
> >      env->pc = env->resetvec;
> >      env->two_stage_lookup = false;
> > +
> > +    /* Initialized default priorities of local interrupts. */
> > +    for (i = 0; i < ARRAY_SIZE(env->miprio); i++) {
> > +        iprio = riscv_cpu_default_priority(i);
> > +        env->miprio[i] = iprio;
> > +        env->siprio[i] = iprio;
> > +        env->hviprio[i] = IPRIO_DEFAULT_MMAXIPRIO;
> > +    }
> > +    i = 0;
> > +    while (!riscv_cpu_hviprio_index2irq(i, &irq, &rdzero)) {
> > +        if (rdzero) {
> > +            env->hviprio[irq] = 0;
> > +        } else {
> > +            env->hviprio[irq] = env->miprio[irq];
> > +        }
> > +        i++;
> > +    }
> >  #endif
> >      cs->exception_index = EXCP_NONE;
> >      env->load_res = -1;
> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> > index f00c60c840..780d3f9058 100644
> > --- a/target/riscv/cpu.h
> > +++ b/target/riscv/cpu.h
> > @@ -157,12 +157,12 @@ struct CPURISCVState {
> >       */
> >      uint64_t mstatus;
> >
> > -    target_ulong mip;
> > +    uint64_t mip;
>
> This isn't right. MIP is a MXLEN-1 CSR. I didn't check but I assume
> all the other existing target_ulong CSRs are the same.

When AIA is available the number of local interrupts are 64 for
both RV32 and RV64.

The width of CSRs remain same as target_ulong but we have
new CSRs for RV32 (such as mipH) for the high-half.

Also, this patch changes does not break the case when AIA
is not available (or disabled).

Regards,
Anup

>
> Alistair
>
> >
> > -    uint32_t miclaim;
> > +    uint64_t miclaim;
> >
> > -    target_ulong mie;
> > -    target_ulong mideleg;
> > +    uint64_t mie;
> > +    uint64_t mideleg;
> >
> >      target_ulong sptbr;  /* until: priv-1.9.1 */
> >      target_ulong satp;   /* since: priv-1.10.0 */
> > @@ -179,16 +179,27 @@ struct CPURISCVState {
> >      target_ulong mcause;
> >      target_ulong mtval;  /* since: priv-1.10.0 */
> >
> > +    /* AIA CSRs */
> > +    target_ulong miselect;
> > +    target_ulong siselect;
> > +
> > +    uint8_t miprio[64];
> > +    uint8_t siprio[64];
> > +
> >      /* Hypervisor CSRs */
> >      target_ulong hstatus;
> >      target_ulong hedeleg;
> > -    target_ulong hideleg;
> > +    uint64_t hideleg;
> >      target_ulong hcounteren;
> >      target_ulong htval;
> >      target_ulong htinst;
> >      target_ulong hgatp;
> >      uint64_t htimedelta;
> >
> > +    /* AIA HS-mode CSRs */
> > +    uint8_t hviprio[64];
> > +    target_ulong hvicontrol;
> > +
> >      /* Virtual CSRs */
> >      /*
> >       * For RV32 this is 32-bit vsstatus and 32-bit vsstatush.
> > @@ -202,6 +213,9 @@ struct CPURISCVState {
> >      target_ulong vstval;
> >      target_ulong vsatp;
> >
> > +    /* AIA VS-mode CSRs */
> > +    target_ulong vsiselect;
> > +
> >      target_ulong mtval2;
> >      target_ulong mtinst;
> >
> > @@ -236,6 +250,18 @@ struct CPURISCVState {
> >      uint64_t (*rdtime_fn)(uint32_t);
> >      uint32_t rdtime_fn_arg;
> >
> > +    /* machine specific AIA IMSIC read-modify-write callback */
> > +#define IMSIC_MAKE_REG(__isel, __priv, __virt, __vgein) \
> > +    ((((__vgein) & 0x3f) << 24) | (((__virt) & 0x1) << 20) | \
> > +     (((__priv) & 0x3) << 16) | (__isel & 0xffff))
> > +#define IMSIC_REG_ISEL(__reg)                  ((__reg) & 0xffff)
> > +#define IMSIC_REG_PRIV(__reg)                  (((__reg) >> 16) & 0x3)
> > +#define IMSIC_REG_VIRT(__reg)                  (((__reg) >> 20) & 0x1)
> > +#define IMSIC_REG_VGEIN(__reg)                 (((__reg) >> 24) & 0x3f)
> > +    int (*imsic_rmw_fn)(void *arg, target_ulong reg, target_ulong *val,
> > +                        target_ulong new_val, target_ulong write_mask);
> > +    void *imsic_rmw_fn_arg;
> > +
> >      /* True if in debugger mode.  */
> >      bool debugger;
> >  #endif
> > @@ -335,6 +361,11 @@ int riscv_cpu_write_elf32_note(WriteCoreDumpFunction 
> > f, CPUState *cs,
> >                                 int cpuid, void *opaque);
> >  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);
> > +int riscv_cpu_mirq_pending(CPURISCVState *env);
> > +int riscv_cpu_sirq_pending(CPURISCVState *env);
> > +int riscv_cpu_vsirq_pending(CPURISCVState *env);
> >  bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request);
> >  bool riscv_cpu_fp_enabled(CPURISCVState *env);
> >  bool riscv_cpu_virt_enabled(CPURISCVState *env);
> > @@ -364,9 +395,16 @@ void riscv_cpu_list(void);
> >
> >  #ifndef CONFIG_USER_ONLY
> >  void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env);
> > -int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts);
> > -uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t 
> > value);
> > +int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts);
> > +uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t 
> > value);
> >  #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value 
> > */
> > +void riscv_cpu_set_imsic_rmw_fn(CPURISCVState *env,
> > +                                int (*rmw_fn)(void *arg,
> > +                                              target_ulong reg,
> > +                                              target_ulong *val,
> > +                                              target_ulong new_val,
> > +                                              target_ulong write_mask),
> > +                                void *rmw_fn_arg);
> >  void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t),
> >                               uint32_t arg);
> >  #endif
> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> > index 21c54ef561..5b06b4f995 100644
> > --- a/target/riscv/cpu_helper.c
> > +++ b/target/riscv/cpu_helper.c
> > @@ -36,44 +36,219 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool 
> > ifetch)
> >  }
> >
> >  #ifndef CONFIG_USER_ONLY
> > -static int riscv_cpu_local_irq_pending(CPURISCVState *env)
> > +
> > +/*
> > + * The HS-mode is allowed to configure priority only for the
> > + * following VS-mode local interrupts:
> > + *
> > + * 0  (Reserved interrupt, reads as zero)
> > + * 1  Supervisor software interrupt
> > + * 4  (Reserved interrupt, reads as zero)
> > + * 5  Supervisor timer interrupt
> > + * 8  (Reserved interrupt, reads as zero)
> > + * 13 (Reserved interrupt)
> > + * 14 "
> > + * 15 "
> > + * 16 "
> > + * 18 Debug/trace interrupt
> > + * 20 (Reserved interrupt)
> > + * 22 ”
> > + * 24 ”
> > + * 26 ”
> > + * 28 "
> > + * 30 (Reserved for standard reporting of bus or system errors)
> > + */
> > +
> > +static int hviprio_index2irq[] =
> > +    { 0, 1, 4, 5, 8, 13, 14, 15, 16, 18, 20, 22, 24, 26, 28, 30 };
> > +static int hviprio_index2rdzero[] =
> > +    { 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
> > +
> > +int riscv_cpu_hviprio_index2irq(int index, int *out_irq, int *out_rdzero)
> >  {
> > -    target_ulong irqs;
> > +    if (index < 0 || ARRAY_SIZE(hviprio_index2irq) <= index) {
> > +        return -EINVAL;
> > +    }
> >
> > -    target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
> > -    target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
> > -    target_ulong hs_mstatus_sie = get_field(env->mstatus_hs, MSTATUS_SIE);
> > +    if (out_irq) {
> > +        *out_irq = hviprio_index2irq[index];
> > +    }
> > +
> > +    if (out_rdzero) {
> > +        *out_rdzero = hviprio_index2rdzero[index];
> > +    }
> >
> > -    target_ulong pending = env->mip & env->mie &
> > -                               ~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
> > -    target_ulong vspending = (env->mip & env->mie &
> > -                              (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP));
> > +    return 0;
> > +}
> >
> > -    target_ulong mie    = env->priv < PRV_M ||
> > -                          (env->priv == PRV_M && mstatus_mie);
> > -    target_ulong sie    = env->priv < PRV_S ||
> > -                          (env->priv == PRV_S && mstatus_sie);
> > -    target_ulong hs_sie = env->priv < PRV_S ||
> > -                          (env->priv == PRV_S && hs_mstatus_sie);
> > +uint8_t riscv_cpu_default_priority(int irq)
> > +{
> > +    int u, l;
> > +    uint8_t iprio = IPRIO_MMAXIPRIO;
> >
> > -    if (riscv_cpu_virt_enabled(env)) {
> > -        target_ulong pending_hs_irq = pending & -hs_sie;
> > +    if (irq < 0 || irq > 63) {
> > +        return iprio;
> > +    }
> >
> > -        if (pending_hs_irq) {
> > -            riscv_cpu_set_force_hs_excep(env, FORCE_HS_EXCEP);
> > -            return ctz64(pending_hs_irq);
> > +    /*
> > +     * Default priorities of local interrupts are defined in the
> > +     * RISC-V Advanced Interrupt Architecture specification.
> > +     *
> > +     * ----------------------------------------------------------------
> > +     *  Default  |
> > +     *  Priority | Major Interrupt Numbers
> > +     * ----------------------------------------------------------------
> > +     *  Highest  | 63 (3f), 62 (3e), 31 (1f), 30 (1e), 61 (3d), 60 (3c),
> > +     *           | 59 (3b), 58 (3a), 29 (1d), 28 (1c), 57 (39), 56 (38),
> > +     *           | 55 (37), 54 (36), 27 (1b), 26 (1a), 53 (35), 52 (34),
> > +     *           | 51 (33), 50 (32), 25 (19), 24 (18), 49 (31), 48 (30)
> > +     *           |
> > +     *           | 11 (0b),  3 (03),  7 (07)
> > +     *           |  9 (09),  1 (01),  5 (05)
> > +     *           | 12 (0c)
> > +     *           | 10 (0a),  2 (02),  6 (06)
> > +     *           |
> > +     *           | 47 (2f), 46 (2e), 23 (17), 22 (16), 45 (2d), 44 (2c),
> > +     *           | 43 (2b), 42 (2a), 21 (15), 20 (14), 41 (29), 40 (28),
> > +     *           | 39 (27), 38 (26), 19 (13), 18 (12), 37 (25), 36 (24),
> > +     *  Lowest   | 35 (23), 34 (22), 17 (11), 16 (10), 33 (21), 32 (20)
> > +     * ----------------------------------------------------------------
> > +     */
> > +
> > +    u = IPRIO_DEFAULT_U(irq);
> > +    l = IPRIO_DEFAULT_L(irq);
> > +    if (u == 0) {
> > +        if (irq == IRQ_VS_EXT || irq == IRQ_VS_TIMER ||
> > +            irq == IRQ_VS_SOFT) {
> > +            iprio = IPRIO_DEFAULT_VS;
> > +        } else if (irq == IRQ_S_GEXT) {
> > +            iprio = IPRIO_DEFAULT_SGEXT;
> > +        } else if (irq == IRQ_S_EXT || irq == IRQ_S_TIMER ||
> > +                   irq == IRQ_S_SOFT) {
> > +            iprio = IPRIO_DEFAULT_S;
> > +        } else if (irq == IRQ_M_EXT || irq == IRQ_M_TIMER ||
> > +                   irq == IRQ_M_SOFT) {
> > +            iprio = IPRIO_DEFAULT_M;
> > +        } else {
> > +            iprio = IPRIO_DEFAULT_VS;
> >          }
> > +    } else if (u == 1) {
> > +        if (l < 8) {
> > +            iprio = IPRIO_DEFAULT_16_23(irq);
> > +        } else {
> > +            iprio = IPRIO_DEFAULT_24_31(irq);
> > +        }
> > +    } else if (u == 2) {
> > +        iprio = IPRIO_DEFAULT_32_47(irq);
> > +    } else if (u == 3) {
> > +        iprio = IPRIO_DEFAULT_48_63(irq);
> > +    }
> > +
> > +    return iprio;
> > +}
> > +
> > +static int riscv_cpu_pending_to_irq(CPURISCVState *env,
> > +                                    uint64_t pending, uint8_t *iprio)
> > +{
> > +    int irq, best_irq = EXCP_NONE;
> > +    unsigned int prio, best_prio = UINT_MAX;
> >
> > -        pending = vspending;
> > +    if (!pending) {
> > +        return EXCP_NONE;
> >      }
> >
> > -    irqs = (pending & ~env->mideleg & -mie) | (pending &  env->mideleg & 
> > -sie);
> > +    irq = ctz64(pending);
> > +    if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
> > +        return irq;
> > +    }
> >
> > -    if (irqs) {
> > -        return ctz64(irqs); /* since non-zero */
> > +    pending = pending >> irq;
> > +    while (pending) {
> > +        prio = iprio[irq];
> > +        if (!prio) {
> > +            prio = (riscv_cpu_default_priority(irq) < IPRIO_DEFAULT_M) ?
> > +                   1 : IPRIO_MMAXIPRIO;
> > +        }
> > +        if ((pending & 0x1) && (prio < best_prio)) {
> > +            best_irq = irq;
> > +            best_prio = prio;
> > +        }
> > +        irq++;
> > +        pending = pending >> 1;
> > +    }
> > +
> > +    return best_irq;
> > +}
> > +
> > +int riscv_cpu_mirq_pending(CPURISCVState *env)
> > +{
> > +    uint64_t irqs = env->mip & env->mie & ~env->mideleg &
> > +                    ~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
> > +
> > +    return riscv_cpu_pending_to_irq(env, irqs, env->miprio);
> > +}
> > +
> > +int riscv_cpu_sirq_pending(CPURISCVState *env)
> > +{
> > +    uint64_t irqs = env->mip & env->mie & env->mideleg &
> > +                    ~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
> > +
> > +    return riscv_cpu_pending_to_irq(env, irqs, env->siprio);
> > +}
> > +
> > +int riscv_cpu_vsirq_pending(CPURISCVState *env)
> > +{
> > +    uint64_t irqs = env->mip & env->mie & env->mideleg &
> > +                    (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
> > +
> > +    return riscv_cpu_pending_to_irq(env, irqs >> 1, env->hviprio);
> > +}
> > +
> > +static int riscv_cpu_local_irq_pending(CPURISCVState *env)
> > +{
> > +    int virq;
> > +    uint64_t irqs, mie, sie, vsie;
> > +    uint64_t pending, vspending;
> > +
> > +    /* Determine interrupt enable state of all privilege modes */
> > +    if (riscv_cpu_virt_enabled(env)) {
> > +        mie = 1;
> > +        sie = 1;
> > +        vsie = (env->priv < PRV_S) ||
> > +               (env->priv == PRV_S && get_field(env->mstatus, 
> > MSTATUS_SIE));
> >      } else {
> > -        return EXCP_NONE; /* indicates no pending interrupt */
> > +        mie = (env->priv < PRV_M) ||
> > +              (env->priv == PRV_M && get_field(env->mstatus, MSTATUS_MIE));
> > +        sie = (env->priv < PRV_S) ||
> > +              (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_SIE));
> > +        vsie = 0;
> > +    }
> > +
> > +    /* Check M-mode interrupts */
> > +    pending = env->mip & env->mie &
> > +              ~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
> > +    irqs = pending & ~env->mideleg & -mie;
> > +    if (irqs) {
> > +        return riscv_cpu_pending_to_irq(env, irqs, env->miprio);
> > +    }
> > +
> > +    /* Check HS-mode interrupts */
> > +    irqs = pending & env->mideleg & -sie;
> > +    if (irqs) {
> > +        return riscv_cpu_pending_to_irq(env, irqs, env->siprio);
> > +    }
> > +
> > +    /* Check VS-mode interrupts */
> > +    vspending = env->mip & env->mie &
> > +                (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
> > +    irqs = vspending & env->hideleg & -vsie;
> > +    if (irqs) {
> > +        virq = riscv_cpu_pending_to_irq(env, irqs >> 1, env->hviprio);
> > +        return (virq <= 0) ? virq : virq + 1;
> >      }
> > +
> > +    /* Indicates no pending interrupt */
> > +    return EXCP_NONE;
> >  }
> >  #endif
> >
> > @@ -213,7 +388,7 @@ bool riscv_cpu_two_stage_lookup(int mmu_idx)
> >      return mmu_idx & TB_FLAGS_PRIV_HYP_ACCESS_MASK;
> >  }
> >
> > -int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts)
> > +int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
> >  {
> >      CPURISCVState *env = &cpu->env;
> >      if (env->miclaim & interrupts) {
> > @@ -224,11 +399,11 @@ int riscv_cpu_claim_interrupts(RISCVCPU *cpu, 
> > uint32_t interrupts)
> >      }
> >  }
> >
> > -uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
> > +uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t value)
> >  {
> >      CPURISCVState *env = &cpu->env;
> >      CPUState *cs = CPU(cpu);
> > -    uint32_t old = env->mip;
> > +    uint64_t old = env->mip;
> >      bool locked = false;
> >
> >      if (!qemu_mutex_iothread_locked()) {
> > @@ -251,6 +426,18 @@ uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t 
> > mask, uint32_t value)
> >      return old;
> >  }
> >
> > +void riscv_cpu_set_imsic_rmw_fn(CPURISCVState *env,
> > +                                int (*rmw_fn)(void *arg,
> > +                                              target_ulong reg,
> > +                                              target_ulong *val,
> > +                                              target_ulong new_val,
> > +                                              target_ulong write_mask),
> > +                                void *rmw_fn_arg)
> > +{
> > +    env->imsic_rmw_fn = rmw_fn;
> > +    env->imsic_rmw_fn_arg = rmw_fn_arg;
> > +}
> > +
> >  void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t),
> >                               uint32_t arg)
> >  {
> > @@ -904,7 +1091,7 @@ 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;
> > -    target_ulong deleg = async ? env->mideleg : env->medeleg;
> > +    uint64_t deleg = async ? env->mideleg : env->medeleg;
> >      bool write_tval = false;
> >      target_ulong tval = 0;
> >      target_ulong htval = 0;
> > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> > index d2585395bf..3c016d7452 100644
> > --- a/target/riscv/csr.c
> > +++ b/target/riscv/csr.c
> > @@ -153,11 +153,56 @@ static int any32(CPURISCVState *env, int csrno)
> >
> >  }
> >
> > +static int aia_any(CPURISCVState *env, int csrno)
> > +{
> > +    if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
> > +        return -RISCV_EXCP_ILLEGAL_INST;
> > +    }
> > +
> > +    return any(env, csrno);
> > +}
> > +
> > +static int aia_any32(CPURISCVState *env, int csrno)
> > +{
> > +    if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
> > +        return -RISCV_EXCP_ILLEGAL_INST;
> > +    }
> > +
> > +    return any32(env, csrno);
> > +}
> > +
> >  static int smode(CPURISCVState *env, int csrno)
> >  {
> >      return -!riscv_has_ext(env, RVS);
> >  }
> >
> > +static int smode32(CPURISCVState *env, int csrno)
> > +{
> > +    if (!riscv_cpu_is_32bit(env)) {
> > +        return -RISCV_EXCP_ILLEGAL_INST;
> > +    }
> > +
> > +    return smode(env, csrno);
> > +}
> > +
> > +static int aia_smode(CPURISCVState *env, int csrno)
> > +{
> > +    if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
> > +        return -RISCV_EXCP_ILLEGAL_INST;
> > +    }
> > +
> > +    return smode(env, csrno);
> > +}
> > +
> > +static int aia_smode32(CPURISCVState *env, int csrno)
> > +{
> > +    if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
> > +        return -RISCV_EXCP_ILLEGAL_INST;
> > +    }
> > +
> > +    return smode32(env, csrno);
> > +}
> > +
> >  static int hmode(CPURISCVState *env, int csrno)
> >  {
> >      if (riscv_has_ext(env, RVS) &&
> > @@ -177,11 +222,28 @@ static int hmode(CPURISCVState *env, int csrno)
> >  static int hmode32(CPURISCVState *env, int csrno)
> >  {
> >      if (!riscv_cpu_is_32bit(env)) {
> > -        return 0;
> > +        return -RISCV_EXCP_ILLEGAL_INST;
> > +    }
> > +
> > +    return hmode(env, csrno);
> > +}
> > +
> > +static int aia_hmode(CPURISCVState *env, int csrno)
> > +{
> > +    if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
> > +        return -RISCV_EXCP_ILLEGAL_INST;
> >      }
> >
> >      return hmode(env, csrno);
> > +}
> >
> > +static int aia_hmode32(CPURISCVState *env, int csrno)
> > +{
> > +    if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
> > +        return -RISCV_EXCP_ILLEGAL_INST;
> > +    }
> > +
> > +    return hmode32(env, csrno);
> >  }
> >
> >  static int pmp(CPURISCVState *env, int csrno)
> > @@ -388,14 +450,16 @@ static int read_timeh(CPURISCVState *env, int csrno, 
> > target_ulong *val)
> >
> >  /* Machine constants */
> >
> > -#define M_MODE_INTERRUPTS  (MIP_MSIP | MIP_MTIP | MIP_MEIP)
> > -#define S_MODE_INTERRUPTS  (MIP_SSIP | MIP_STIP | MIP_SEIP)
> > -#define VS_MODE_INTERRUPTS (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)
> > +#define M_MODE_INTERRUPTS  ((uint64_t)(MIP_MSIP | MIP_MTIP | MIP_MEIP))
> > +#define S_MODE_INTERRUPTS  ((uint64_t)(MIP_SSIP | MIP_STIP | MIP_SEIP))
> > +#define VS_MODE_INTERRUPTS ((uint64_t)(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP))
> > +
> > +#define TLOWBITS64         ((uint64_t)((target_ulong)-1))
> >
> > -static const target_ulong delegable_ints = S_MODE_INTERRUPTS |
> > -                                           VS_MODE_INTERRUPTS;
> > -static const target_ulong all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS 
> > |
> > -                                     VS_MODE_INTERRUPTS;
> > +static const uint64_t delegable_ints = S_MODE_INTERRUPTS |
> > +                                       VS_MODE_INTERRUPTS;
> > +static const uint64_t all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS |
> > +                                 VS_MODE_INTERRUPTS;
> >  static const target_ulong delegable_excps =
> >      (1ULL << (RISCV_EXCP_INST_ADDR_MIS)) |
> >      (1ULL << (RISCV_EXCP_INST_ACCESS_FAULT)) |
> > @@ -419,10 +483,10 @@ static const target_ulong delegable_excps =
> >  static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
> >      SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
> >      SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD;
> > -static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | 
> > MIP_UEIP;
> > -static const target_ulong hip_writable_mask = MIP_VSSIP;
> > -static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | 
> > MIP_VSEIP;
> > -static const target_ulong vsip_writable_mask = MIP_VSSIP;
> > +static const uint64_t sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
> > +static const uint64_t hip_writable_mask = MIP_VSSIP;
> > +static const uint64_t hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | 
> > MIP_VSEIP;
> > +static const uint64_t vsip_writable_mask = MIP_VSSIP;
> >
> >  static const char valid_vm_1_10_32[16] = {
> >      [VM_1_10_MBARE] = 1,
> > @@ -596,7 +660,437 @@ static int read_mideleg(CPURISCVState *env, int 
> > csrno, target_ulong *val)
> >
> >  static int write_mideleg(CPURISCVState *env, int csrno, target_ulong val)
> >  {
> > -    env->mideleg = (env->mideleg & ~delegable_ints) | (val & 
> > delegable_ints);
> > +    uint64_t mask = delegable_ints & TLOWBITS64;
> > +
> > +    env->mideleg = (env->mideleg & ~mask) | (val & mask);
> > +    if (riscv_has_ext(env, RVH)) {
> > +        env->mideleg |= VS_MODE_INTERRUPTS;
> > +    }
> > +    return 0;
> > +}
> > +
> > +static int aia_xlate_vs_csrno(CPURISCVState *env, int csrno)
> > +{
> > +    if (!riscv_cpu_virt_enabled(env)) {
> > +        return csrno;
> > +    }
> > +
> > +    switch (csrno) {
> > +    case CSR_SISELECT:
> > +        return CSR_VSISELECT;
> > +    case CSR_SIREG:
> > +        return CSR_VSIREG;
> > +    case CSR_STOPI:
> > +        return CSR_VSTOPI;
> > +    case CSR_SSETEIPNUM:
> > +        return CSR_VSSETEIPNUM;
> > +    case CSR_SCLREIPNUM:
> > +        return CSR_VSCLREIPNUM;
> > +    case CSR_SSETEIENUM:
> > +        return CSR_VSSETEIENUM;
> > +    case CSR_SCLREIENUM:
> > +        return CSR_VSCLREIENUM;
> > +    default:
> > +        return csrno;
> > +    };
> > +}
> > +
> > +static int rmw_xiselect(CPURISCVState *env, int csrno, target_ulong *val,
> > +                        target_ulong new_val, target_ulong write_mask)
> > +{
> > +    target_ulong *iselect;
> > +
> > +    switch (csrno) {
> > +    case CSR_MISELECT:
> > +        iselect = &env->miselect;
> > +        break;
> > +    case CSR_SISELECT:
> > +        iselect = riscv_cpu_virt_enabled(env) ?
> > +                  &env->vsiselect : &env->siselect;
> > +        break;
> > +    case CSR_VSISELECT:
> > +        iselect = &env->vsiselect;
> > +        break;
> > +    default:
> > +         return -RISCV_EXCP_ILLEGAL_INST;
> > +    };
> > +
> > +    if (val) {
> > +        *val = *iselect;
> > +    }
> > +
> > +    if (write_mask) {
> > +        *iselect = (*iselect & ~write_mask) | (new_val & write_mask);
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +static int rmw_iprio(target_ulong iselect, uint8_t *iprio,
> > +                     target_ulong *val, target_ulong new_val,
> > +                     target_ulong write_mask)
> > +{
> > +    int i, firq, nirqs;
> > +    target_ulong old_val;
> > +
> > +    if (iselect < ISELECT_IPRIO0 || ISELECT_IPRIO15 < iselect) {
> > +        return -EINVAL;
> > +    }
> > +#if TARGET_LONG_BITS == 64
> > +    if (iselect & 0x1) {
> > +        return -EINVAL;
> > +    }
> > +#endif
> > +
> > +    nirqs = 4 * (TARGET_LONG_BITS / 32);
> > +    firq = ((iselect - ISELECT_IPRIO0) / (TARGET_LONG_BITS / 32)) * 
> > (nirqs);
> > +
> > +    old_val = 0;
> > +    for (i = 0; i < nirqs; i++) {
> > +        old_val |= ((target_ulong)iprio[firq + i]) << (IPRIO_IRQ_BITS * i);
> > +    }
> > +
> > +    if (val) {
> > +        *val = old_val;
> > +    }
> > +
> > +    if (write_mask) {
> > +        new_val = (old_val & ~write_mask) | (new_val & write_mask);
> > +        for (i = 0; i < nirqs; i++) {
> > +            iprio[firq + i] = (new_val >> (IPRIO_IRQ_BITS * i)) & 0xff;
> > +        }
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +static int rmw_xireg(CPURISCVState *env, int csrno, target_ulong *val,
> > +                     target_ulong new_val, target_ulong write_mask)
> > +{
> > +    bool virt;
> > +    uint8_t *iprio;
> > +    int ret = -EINVAL;
> > +    target_ulong priv, isel, vgein;
> > +
> > +    /* Translate CSR number for VS-mode */
> > +    csrno = aia_xlate_vs_csrno(env, csrno);
> > +
> > +    /* Decode register details from CSR number */
> > +    virt = false;
> > +    switch (csrno) {
> > +    case CSR_MIREG:
> > +        iprio = env->miprio;
> > +        isel = env->miselect;
> > +        priv = PRV_M;
> > +        break;
> > +    case CSR_SIREG:
> > +        iprio = env->siprio;
> > +        isel = env->siselect;
> > +        priv = PRV_S;
> > +        break;
> > +    case CSR_VSIREG:
> > +        iprio = env->hviprio;
> > +        isel = env->vsiselect;
> > +        priv = PRV_S;
> > +        virt = true;
> > +        break;
> > +    default:
> > +         goto done;
> > +    };
> > +
> > +    /* Find the selected guest interrupt file */
> > +    vgein = (virt) ? (env->hstatus & HSTATUS_VGEIN) >> HSTATUS_VGEIN_SHIFT 
> > : 0;
> > +
> > +    if (ISELECT_IPRIO0 <= isel && isel <= ISELECT_IPRIO15) {
> > +        /* Local interrupt priority registers not available for VS-mode */
> > +        if (!virt) {
> > +            ret = rmw_iprio(isel, iprio, val, new_val, write_mask);
> > +        }
> > +    } else if (ISELECT_IMSIC_FIRST <= isel && isel <= ISELECT_IMSIC_LAST) {
> > +        /* IMSIC registers only available when machine implements it. */
> > +        if (env->imsic_rmw_fn) {
> > +            /* Selected guest interrupt file should not be zero */
> > +            if (virt && !vgein) {
> > +                goto done;
> > +            }
> > +            /* Call machine specific IMSIC register emulation */
> > +            ret = env->imsic_rmw_fn(env->imsic_rmw_fn_arg,
> > +                                    IMSIC_MAKE_REG(isel, priv, virt, 
> > vgein),
> > +                                    val, new_val, write_mask);
> > +        }
> > +    }
> > +
> > +done:
> > +    if (ret) {
> > +        return (riscv_cpu_virt_enabled(env) && virt) ?
> > +               -RISCV_EXCP_VIRT_INSTRUCTION_FAULT : 
> > -RISCV_EXCP_ILLEGAL_INST;
> > +    }
> > +    return 0;
> > +}
> > +
> > +static int read_mtopi(CPURISCVState *env, int csrno, target_ulong *val)
> > +{
> > +    int irq;
> > +
> > +    irq = riscv_cpu_mirq_pending(env);
> > +    if (irq <= 0 || irq > 63) {
> > +       *val = 0;
> > +    } else {
> > +       *val = (irq & TOPI_IID_MASK) << TOPI_IID_SHIFT;
> > +       *val |= env->miprio[irq];
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +static int read_xsetclreinum(CPURISCVState *env, int csrno, target_ulong 
> > *val)
> > +{
> > +    bool virt;
> > +    int ret = -EINVAL;
> > +    target_ulong vgein;
> > +
> > +    /* Translate CSR number for VS-mode */
> > +    csrno = aia_xlate_vs_csrno(env, csrno);
> > +
> > +    /* Decode register details from CSR number */
> > +    virt = false;
> > +    switch (csrno) {
> > +    case CSR_MSETEIPNUM:
> > +    case CSR_MCLREIPNUM:
> > +    case CSR_MSETEIENUM:
> > +    case CSR_MCLREIENUM:
> > +    case CSR_SSETEIPNUM:
> > +    case CSR_SCLREIPNUM:
> > +    case CSR_SSETEIENUM:
> > +    case CSR_SCLREIENUM:
> > +        break;
> > +    case CSR_VSSETEIPNUM:
> > +    case CSR_VSCLREIPNUM:
> > +    case CSR_VSSETEIENUM:
> > +    case CSR_VSCLREIENUM:
> > +        virt = true;
> > +        break;
> > +    default:
> > +         goto done;
> > +    };
> > +
> > +    /* IMSIC CSRs only available when machine implements IMSIC. */
> > +    if (!env->imsic_rmw_fn) {
> > +        goto done;
> > +    }
> > +
> > +    /* Find the selected guest interrupt file */
> > +    vgein = (virt) ? (env->hstatus & HSTATUS_VGEIN) >> HSTATUS_VGEIN_SHIFT 
> > : 0;
> > +
> > +    /* Selected guest interrupt file should not be zero */
> > +    if (virt && !vgein) {
> > +        goto done;
> > +    }
> > +
> > +    /* Set/Clear CSRs always read zero */
> > +    ret = 0;
> > +    if (val) {
> > +        *val = 0;
> > +    }
> > +
> > +done:
> > +    if (ret) {
> > +        return (riscv_cpu_virt_enabled(env) && virt) ?
> > +               -RISCV_EXCP_VIRT_INSTRUCTION_FAULT : 
> > -RISCV_EXCP_ILLEGAL_INST;
> > +    }
> > +    return 0;
> > +}
> > +
> > +static int write_xsetclreinum(CPURISCVState *env, int csrno, target_ulong 
> > val)
> > +{
> > +    int ret = -EINVAL;
> > +    bool set, pend, virt;
> > +    target_ulong priv, isel, vgein;
> > +    target_ulong new_val, write_mask;
> > +
> > +    /* Translate CSR number for VS-mode */
> > +    csrno = aia_xlate_vs_csrno(env, csrno);
> > +
> > +    /* Decode register details from CSR number */
> > +    virt = set = pend = false;
> > +    switch (csrno) {
> > +    case CSR_MSETEIPNUM:
> > +        priv = PRV_M;
> > +        set = true;
> > +        break;
> > +    case CSR_MCLREIPNUM:
> > +        priv = PRV_M;
> > +        pend = true;
> > +        break;
> > +    case CSR_MSETEIENUM:
> > +        priv = PRV_M;
> > +        set = true;
> > +        break;
> > +    case CSR_MCLREIENUM:
> > +        priv = PRV_M;
> > +        break;
> > +    case CSR_SSETEIPNUM:
> > +        priv = PRV_S;
> > +        set = true;
> > +        pend = true;
> > +        break;
> > +    case CSR_SCLREIPNUM:
> > +        priv = PRV_S;
> > +        pend = true;
> > +        break;
> > +    case CSR_SSETEIENUM:
> > +        priv = PRV_S;
> > +        set = true;
> > +        break;
> > +    case CSR_SCLREIENUM:
> > +        priv = PRV_S;
> > +        break;
> > +    case CSR_VSSETEIPNUM:
> > +        priv = PRV_S;
> > +        virt = true;
> > +        set = true;
> > +        pend = true;
> > +        break;
> > +    case CSR_VSCLREIPNUM:
> > +        priv = PRV_S;
> > +        virt = true;
> > +        pend = true;
> > +        break;
> > +    case CSR_VSSETEIENUM:
> > +        priv = PRV_S;
> > +        virt = true;
> > +        set = true;
> > +        break;
> > +    case CSR_VSCLREIENUM:
> > +        priv = PRV_S;
> > +        virt = true;
> > +        break;
> > +    default:
> > +         goto done;
> > +    };
> > +
> > +    /* IMSIC CSRs only available when machine implements IMSIC. */
> > +    if (!env->imsic_rmw_fn) {
> > +        goto done;
> > +    }
> > +
> > +    /* Find target interrupt pending/enable register */
> > +    if (pend) {
> > +        isel = ISELECT_IMSIC_EIP0;
> > +    } else {
> > +        isel = ISELECT_IMSIC_EIE0;
> > +    }
> > +    isel += val / IMSIC_EIPx_BITS;
> > +
> > +    /* Find the interrupt bit to be set/clear */
> > +    write_mask = 1 << (val % IMSIC_EIPx_BITS);
> > +    new_val = (set) ? write_mask : 0;
> > +
> > +    /* Find the selected guest interrupt file */
> > +    vgein = (virt) ? (env->hstatus & HSTATUS_VGEIN) >> HSTATUS_VGEIN_SHIFT 
> > : 0;
> > +
> > +    /* Selected guest interrupt file should not be zero */
> > +    if (virt && !vgein) {
> > +        goto done;
> > +    }
> > +
> > +    /* Call machine specific IMSIC register emulation */
> > +    ret = env->imsic_rmw_fn(env->imsic_rmw_fn_arg,
> > +                            IMSIC_MAKE_REG(isel, priv, virt, vgein),
> > +                            NULL, new_val, write_mask);
> > +
> > +done:
> > +    if (ret) {
> > +        return (riscv_cpu_virt_enabled(env) && virt) ?
> > +               -RISCV_EXCP_VIRT_INSTRUCTION_FAULT : 
> > -RISCV_EXCP_ILLEGAL_INST;
> > +    }
> > +    return 0;
> > +}
> > +
> > +static int read_xclaimei(CPURISCVState *env, int csrno, target_ulong *val)
> > +{
> > +    bool virt;
> > +    int ret = -EINVAL;
> > +    target_ulong priv, isel, vgein;
> > +    target_ulong topei, write_mask;
> > +
> > +    /* Decode register details from CSR number */
> > +    virt = false;
> > +    switch (csrno) {
> > +    case CSR_MCLAIMEI:
> > +        priv = PRV_M;
> > +        break;
> > +    case CSR_SCLAIMEI:
> > +        priv = PRV_S;
> > +        virt = riscv_cpu_virt_enabled(env);
> > +        break;
> > +    default:
> > +        goto done;
> > +    };
> > +
> > +    /* IMSIC CSRs only available when machine implements IMSIC. */
> > +    if (!env->imsic_rmw_fn) {
> > +        goto done;
> > +    }
> > +
> > +    /* Find the selected guest interrupt file */
> > +    vgein = (virt) ? (env->hstatus & HSTATUS_VGEIN) >> HSTATUS_VGEIN_SHIFT 
> > : 0;
> > +
> > +    /* Selected guest interrupt file should not be zero */
> > +    if (virt && !vgein) {
> > +        goto done;
> > +    }
> > +
> > +    /* Call machine specific IMSIC register emulation for reading TOPEI */
> > +    ret = env->imsic_rmw_fn(env->imsic_rmw_fn_arg,
> > +                            IMSIC_MAKE_REG(ISELECT_IMSIC_TOPEI, priv, 
> > virt, vgein),
> > +                            &topei, -1, 0);
> > +    if (ret) {
> > +        goto done;
> > +    }
> > +
> > +    /* If no interrupt pending then we are done */
> > +    if (!topei) {
> > +        goto done;
> > +    }
> > +
> > +    /* Find target interrupt pending register */
> > +    isel = ISELECT_IMSIC_EIP0;
> > +    isel += ((topei >> TOPI_IID_SHIFT) / IMSIC_EIPx_BITS);
> > +
> > +    /* Find the interrupt bit to be cleared */
> > +    write_mask = 1 << ((topei >> TOPI_IID_SHIFT) % IMSIC_EIPx_BITS);
> > +
> > +    /* Call machine specific IMSIC register emulation to clear pending bit 
> > */
> > +    ret = env->imsic_rmw_fn(env->imsic_rmw_fn_arg,
> > +                            IMSIC_MAKE_REG(isel, priv, virt, vgein),
> > +                            NULL, 0, write_mask);
> > +
> > +    /* Update return value */
> > +    if (val) {
> > +        *val = topei;
> > +    }
> > +
> > +done:
> > +    if (ret) {
> > +        return (riscv_cpu_virt_enabled(env) && virt) ?
> > +               -RISCV_EXCP_VIRT_INSTRUCTION_FAULT : 
> > -RISCV_EXCP_ILLEGAL_INST;
> > +    }
> > +    return 0;
> > +}
> > +
> > +static int read_midelegh(CPURISCVState *env, int csrno, target_ulong *val)
> > +{
> > +    *val = (env->mideleg >> 32);
> > +    return 0;
> > +}
> > +
> > +static int write_midelegh(CPURISCVState *env, int csrno, target_ulong val)
> > +{
> > +    uint64_t mask = delegable_ints & ~TLOWBITS64;
> > +    uint64_t newval = ((uint64_t)val) << 32;
> > +
> > +    env->mideleg = (env->mideleg & ~mask) | (newval & mask);
> >      if (riscv_has_ext(env, RVH)) {
> >          env->mideleg |= VS_MODE_INTERRUPTS;
> >      }
> > @@ -611,7 +1105,24 @@ static int read_mie(CPURISCVState *env, int csrno, 
> > target_ulong *val)
> >
> >  static int write_mie(CPURISCVState *env, int csrno, target_ulong val)
> >  {
> > -    env->mie = (env->mie & ~all_ints) | (val & all_ints);
> > +    uint64_t mask = all_ints & TLOWBITS64;
> > +
> > +    env->mie = (env->mie & ~mask) | (val & mask);
> > +    return 0;
> > +}
> > +
> > +static int read_mieh(CPURISCVState *env, int csrno, target_ulong *val)
> > +{
> > +    *val = (env->mie >> 32);
> > +    return 0;
> > +}
> > +
> > +static int write_mieh(CPURISCVState *env, int csrno, target_ulong val)
> > +{
> > +    uint64_t mask = all_ints & ~TLOWBITS64;
> > +    uint64_t newval = ((uint64_t)val) << 32;
> > +
> > +    env->mie = (env->mie & ~mask) | (newval & mask);
> >      return 0;
> >  }
> >
> > @@ -718,8 +1229,9 @@ static int rmw_mip(CPURISCVState *env, int csrno, 
> > target_ulong *ret_value,
> >  {
> >      RISCVCPU *cpu = env_archcpu(env);
> >      /* Allow software control of delegable interrupts not claimed by 
> > hardware */
> > -    target_ulong mask = write_mask & delegable_ints & ~env->miclaim;
> > -    uint32_t old_mip;
> > +    uint64_t mask = ((uint64_t)write_mask) & delegable_ints &
> > +                    ~env->miclaim & TLOWBITS64;
> > +    uint64_t old_mip;
> >
> >      if (mask) {
> >          old_mip = riscv_cpu_update_mip(cpu, mask, (new_value & mask));
> > @@ -734,6 +1246,29 @@ static int rmw_mip(CPURISCVState *env, int csrno, 
> > target_ulong *ret_value,
> >      return 0;
> >  }
> >
> > +static int rmw_miph(CPURISCVState *env, int csrno, target_ulong *ret_value,
> > +                    target_ulong new_value, target_ulong write_mask)
> > +{
> > +    RISCVCPU *cpu = env_archcpu(env);
> > +    /* Allow software control of delegable interrupts not claimed by 
> > hardware */
> > +    uint64_t mask = ((uint64_t)write_mask << 32) & delegable_ints &
> > +                    ~env->miclaim & ~TLOWBITS64;
> > +    uint64_t new_value64 = (uint64_t)new_value << 32;
> > +    uint64_t old_mip;
> > +
> > +    if (mask) {
> > +        old_mip = riscv_cpu_update_mip(cpu, mask, (new_value64 & mask));
> > +    } else {
> > +        old_mip = env->mip;
> > +    }
> > +
> > +    if (ret_value) {
> > +        *ret_value = old_mip >> 32;
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> >  /* Supervisor Trap Setup */
> >  static int read_sstatus(CPURISCVState *env, int csrno, target_ulong *val)
> >  {
> > @@ -751,39 +1286,103 @@ static int write_sstatus(CPURISCVState *env, int 
> > csrno, target_ulong val)
> >
> >  static int read_vsie(CPURISCVState *env, int csrno, target_ulong *val)
> >  {
> > +    uint64_t mask = VS_MODE_INTERRUPTS & env->hideleg & TLOWBITS64;
> > +
> >      /* Shift the VS bits to their S bit location in vsie */
> > -    *val = (env->mie & env->hideleg & VS_MODE_INTERRUPTS) >> 1;
> > +    *val = (env->mie & mask) >> 1;
> > +    return 0;
> > +}
> > +
> > +static int read_vsieh(CPURISCVState *env, int csrno, target_ulong *val)
> > +{
> > +    uint64_t mask = VS_MODE_INTERRUPTS & env->hideleg & ~TLOWBITS64;
> > +
> > +    /* Shift the VS bits to their S bit location in vsieh */
> > +    *val = (env->mie & mask) >> (32 + 1);
> >      return 0;
> >  }
> >
> >  static int read_sie(CPURISCVState *env, int csrno, target_ulong *val)
> >  {
> >      if (riscv_cpu_virt_enabled(env)) {
> > -        read_vsie(env, CSR_VSIE, val);
> > -    } else {
> > -        *val = env->mie & env->mideleg;
> > +        if (env->hvicontrol & HVICONTROL_VTI) {
> > +            return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
> > +        }
> > +        return read_vsie(env, CSR_VSIE, val);
> >      }
> > +
> > +    *val = env->mie & env->mideleg;
> >      return 0;
> >  }
> >
> >  static int write_vsie(CPURISCVState *env, int csrno, target_ulong val)
> >  {
> > +    uint64_t mask = VS_MODE_INTERRUPTS & env->hideleg &
> > +                    all_ints & TLOWBITS64;
> > +
> >      /* Shift the S bits to their VS bit location in mie */
> > -    target_ulong newval = (env->mie & ~VS_MODE_INTERRUPTS) |
> > -                          ((val << 1) & env->hideleg & VS_MODE_INTERRUPTS);
> > -    return write_mie(env, CSR_MIE, newval);
> > +    env->mie = (env->mie & ~mask) | ((val << 1) & mask);
> > +
> > +    return 0;
> > +}
> > +
> > +static int write_vsieh(CPURISCVState *env, int csrno, target_ulong val)
> > +{
> > +    uint64_t mask = VS_MODE_INTERRUPTS & env->hideleg &
> > +                    all_ints & ~TLOWBITS64;
> > +    uint64_t newval = (uint64_t)val << 32;
> > +
> > +    /* Shift the S bits to their VS bit location in mie */
> > +    env->mie = (env->mie & ~mask) | ((newval << 1) & mask);
> > +
> > +    return 0;
> >  }
> >
> >  static int write_sie(CPURISCVState *env, int csrno, target_ulong val)
> >  {
> > +    uint64_t mask;
> > +
> >      if (riscv_cpu_virt_enabled(env)) {
> > -        write_vsie(env, CSR_VSIE, val);
> > -    } else {
> > -        target_ulong newval = (env->mie & ~S_MODE_INTERRUPTS) |
> > -                              (val & S_MODE_INTERRUPTS);
> > -        write_mie(env, CSR_MIE, newval);
> > +        if (env->hvicontrol & HVICONTROL_VTI) {
> > +            return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
> > +        }
> > +        return write_vsie(env, CSR_VSIE, val);
> > +    }
> > +
> > +    mask = S_MODE_INTERRUPTS & env->mideleg & all_ints & TLOWBITS64;
> > +    env->mie = (env->mie & ~mask) | ((uint64_t)val & mask);
> > +
> > +    return 0;
> > +}
> > +
> > +static int read_sieh(CPURISCVState *env, int csrno, target_ulong *val)
> > +{
> > +    if (riscv_cpu_virt_enabled(env)) {
> > +        if (env->hvicontrol & HVICONTROL_VTI) {
> > +            return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
> > +        }
> > +        return read_vsieh(env, CSR_VSIEH, val);
> > +    }
> > +
> > +    *val = ((env->mie & env->mideleg) >> 32);
> > +    return 0;
> > +}
> > +
> > +static int write_sieh(CPURISCVState *env, int csrno, target_ulong val)
> > +{
> > +    uint64_t mask, newval;
> > +
> > +    if (riscv_cpu_virt_enabled(env)) {
> > +        if (env->hvicontrol & HVICONTROL_VTI) {
> > +            return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
> > +        }
> > +        return write_vsieh(env, CSR_VSIEH, val);
> >      }
> >
> > +    mask = S_MODE_INTERRUPTS & env->mideleg & all_ints & ~TLOWBITS64;
> > +    newval = (uint64_t)val << 32;
> > +
> > +    env->mie = (env->mie & ~mask) | (newval & mask);
> >      return 0;
> >  }
> >
> > @@ -868,29 +1467,110 @@ static int write_sbadaddr(CPURISCVState *env, int 
> > csrno, target_ulong val)
> >  static int rmw_vsip(CPURISCVState *env, int csrno, target_ulong *ret_value,
> >                      target_ulong new_value, target_ulong write_mask)
> >  {
> > -    /* Shift the S bits to their VS bit location in mip */
> > -    int ret = rmw_mip(env, 0, ret_value, new_value << 1,
> > -                      (write_mask << 1) & vsip_writable_mask & 
> > env->hideleg);
> > -    *ret_value &= VS_MODE_INTERRUPTS;
> > -    /* Shift the VS bits to their S bit location in vsip */
> > -    *ret_value >>= 1;
> > -    return ret;
> > +    RISCVCPU *cpu = env_archcpu(env);
> > +    /* Allow software control of delegable interrupts not claimed by 
> > hardware */
> > +    uint64_t mask = ((uint64_t)write_mask << 1) & delegable_ints &
> > +                    vsip_writable_mask & env->hideleg &
> > +                    ~env->miclaim & TLOWBITS64;
> > +    uint64_t old_mip;
> > +
> > +    if (mask) {
> > +        old_mip = riscv_cpu_update_mip(cpu, mask, (new_value & mask));
> > +    } else {
> > +        old_mip = env->mip;
> > +    }
> > +
> > +    if (ret_value) {
> > +        *ret_value = old_mip & VS_MODE_INTERRUPTS;
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +static int rmw_vsiph(CPURISCVState *env, int csrno, target_ulong 
> > *ret_value,
> > +                     target_ulong new_value, target_ulong write_mask)
> > +{
> > +    RISCVCPU *cpu = env_archcpu(env);
> > +    /* Allow software control of delegable interrupts not claimed by 
> > hardware */
> > +    uint64_t mask = ((uint64_t)write_mask << (32 + 1)) & delegable_ints &
> > +                    vsip_writable_mask & env->hideleg &
> > +                    ~env->miclaim & ~TLOWBITS64;
> > +    uint64_t new_value64 = (uint64_t)new_value << 32;
> > +    uint64_t old_mip;
> > +
> > +    if (mask) {
> > +        old_mip = riscv_cpu_update_mip(cpu, mask, (new_value64 & mask));
> > +    } else {
> > +        old_mip = env->mip;
> > +    }
> > +
> > +    if (ret_value) {
> > +        *ret_value = (old_mip & VS_MODE_INTERRUPTS) >> 32;
> > +    }
> > +
> > +    return 0;
> >  }
> >
> >  static int rmw_sip(CPURISCVState *env, int csrno, target_ulong *ret_value,
> >                     target_ulong new_value, target_ulong write_mask)
> >  {
> > -    int ret;
> > +    RISCVCPU *cpu = env_archcpu(env);
> > +    uint64_t mask, old_mip;
> >
> >      if (riscv_cpu_virt_enabled(env)) {
> > -        ret = rmw_vsip(env, CSR_VSIP, ret_value, new_value, write_mask);
> > +        if (env->hvicontrol & HVICONTROL_VTI) {
> > +            return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
> > +        }
> > +        return rmw_vsip(env, CSR_VSIP, ret_value, new_value, write_mask);
> > +    }
> > +
> > +    /* Allow software control of delegable interrupts not claimed by 
> > hardware */
> > +    mask = ((uint64_t)write_mask) & delegable_ints &
> > +           env->mideleg & sip_writable_mask &
> > +           ~env->miclaim & TLOWBITS64;
> > +    if (mask) {
> > +        old_mip = riscv_cpu_update_mip(cpu, mask, (new_value & mask));
> >      } else {
> > -        ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value,
> > -                      write_mask & env->mideleg & sip_writable_mask);
> > +        old_mip = env->mip;
> >      }
> >
> > -    *ret_value &= env->mideleg;
> > -    return ret;
> > +    if (ret_value) {
> > +        *ret_value = old_mip;
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +static int rmw_siph(CPURISCVState *env, int csrno, target_ulong *ret_value,
> > +                    target_ulong new_value, target_ulong write_mask)
> > +{
> > +    RISCVCPU *cpu = env_archcpu(env);
> > +    uint64_t mask, new_value64;
> > +    uint64_t old_mip;
> > +
> > +    if (riscv_cpu_virt_enabled(env)) {
> > +        if (env->hvicontrol & HVICONTROL_VTI) {
> > +            return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
> > +        }
> > +        return rmw_vsiph(env, CSR_VSIPH, ret_value, new_value, write_mask);
> > +    }
> > +
> > +    /* Allow software control of delegable interrupts not claimed by 
> > hardware */
> > +    mask = ((uint64_t)write_mask << 32) & delegable_ints &
> > +           env->mideleg & sip_writable_mask &
> > +           ~env->miclaim & ~TLOWBITS64;
> > +    new_value64 = (uint64_t)new_value << 32;
> > +    if (mask) {
> > +        old_mip = riscv_cpu_update_mip(cpu, mask, (new_value64 & mask));
> > +    } else {
> > +        old_mip = env->mip;
> > +    }
> > +
> > +    if (ret_value) {
> > +        *ret_value = (old_mip & env->mideleg) >> 32;
> > +    }
> > +
> > +    return 0;
> >  }
> >
> >  /* Supervisor Protection and Translation */
> > @@ -930,6 +1610,51 @@ static int write_satp(CPURISCVState *env, int csrno, 
> > target_ulong val)
> >      return 0;
> >  }
> >
> > +static int read_vstopi(CPURISCVState *env, int csrno, target_ulong *val)
> > +{
> > +    int irq, hiid;
> > +    uint8_t hiprio, iprio;
> > +
> > +    irq = riscv_cpu_vsirq_pending(env);
> > +    if (irq <= 0 || irq > 63) {
> > +       *val = 0;
> > +    } else {
> > +       *val = (irq & TOPI_IID_MASK) << TOPI_IID_SHIFT;
> > +       iprio = env->hviprio[irq];
> > +       /* TODO: This needs to improve in specification */
> > +       if (!(env->hstatus & HSTATUS_VGEIN)) {
> > +           hiid = (env->hvicontrol & HVICONTROL_IID_MASK) >>
> > +                 HVICONTROL_IID_SHIFT;
> > +           hiprio = env->hvicontrol & HVICONTROL_IPRIO_MASK;
> > +           if (irq == hiid && hiprio) {
> > +               iprio = hiprio;
> > +           }
> > +       }
> > +       *val |= iprio;
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +static int read_stopi(CPURISCVState *env, int csrno, target_ulong *val)
> > +{
> > +    int irq;
> > +
> > +    if (riscv_cpu_virt_enabled(env)) {
> > +        return read_vstopi(env, CSR_VSTOPI, val);
> > +    }
> > +
> > +    irq = riscv_cpu_sirq_pending(env);
> > +    if (irq <= 0 || irq > 63) {
> > +       *val = 0;
> > +    } else {
> > +       *val = (irq & TOPI_IID_MASK) << TOPI_IID_SHIFT;
> > +       *val |= env->siprio[irq];
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> >  /* Hypervisor Extensions */
> >  static int read_hstatus(CPURISCVState *env, int csrno, target_ulong *val)
> >  {
> > @@ -979,26 +1704,90 @@ static int write_hideleg(CPURISCVState *env, int 
> > csrno, target_ulong val)
> >      return 0;
> >  }
> >
> > +static int read_hidelegh(CPURISCVState *env, int csrno, target_ulong *val)
> > +{
> > +    *val = env->hideleg >> 32;
> > +    return 0;
> > +}
> > +
> > +static int write_hidelegh(CPURISCVState *env, int csrno, target_ulong val)
> > +{
> > +    uint64_t mask = ~TLOWBITS64;
> > +    uint64_t newval = ((uint64_t)val) << 32;
> > +
> > +    env->hideleg = (env->hideleg & ~mask) | (newval & mask);
> > +
> > +    return 0;
> > +}
> > +
> >  static int rmw_hvip(CPURISCVState *env, int csrno, target_ulong *ret_value,
> >                     target_ulong new_value, target_ulong write_mask)
> >  {
> > -    int ret = rmw_mip(env, 0, ret_value, new_value,
> > -                      write_mask & hvip_writable_mask);
> > +    RISCVCPU *cpu = env_archcpu(env);
> > +    /* Allow software control of delegable interrupts not claimed by 
> > hardware */
> > +    uint64_t mask = ((uint64_t)write_mask) & delegable_ints &
> > +                    hvip_writable_mask &
> > +                    ~env->miclaim & TLOWBITS64;
> > +    uint64_t old_mip;
> > +
> > +    if (mask) {
> > +        old_mip = riscv_cpu_update_mip(cpu, mask, (new_value & mask));
> > +    } else {
> > +        old_mip = env->mip;
> > +    }
> >
> > -    *ret_value &= hvip_writable_mask;
> > +    if (ret_value) {
> > +        *ret_value = old_mip & hvip_writable_mask;
> > +    }
> >
> > -    return ret;
> > +    return 0;
> > +}
> > +
> > +static int rmw_hviph(CPURISCVState *env, int csrno, target_ulong 
> > *ret_value,
> > +                    target_ulong new_value, target_ulong write_mask)
> > +{
> > +    RISCVCPU *cpu = env_archcpu(env);
> > +    /* Allow software control of delegable interrupts not claimed by 
> > hardware */
> > +    uint64_t mask = ((uint64_t)write_mask << 32) & delegable_ints &
> > +                    hvip_writable_mask &
> > +                    ~env->miclaim & ~TLOWBITS64;
> > +    uint64_t new_value64 = (uint64_t)new_value << 32;
> > +    uint64_t old_mip;
> > +
> > +    if (mask) {
> > +        old_mip = riscv_cpu_update_mip(cpu, mask, (new_value64 & mask));
> > +    } else {
> > +        old_mip = env->mip;
> > +    }
> > +
> > +    if (ret_value) {
> > +        *ret_value = (old_mip & hvip_writable_mask) >> 32;
> > +    }
> > +
> > +    return 0;
> >  }
> >
> >  static int rmw_hip(CPURISCVState *env, int csrno, target_ulong *ret_value,
> >                     target_ulong new_value, target_ulong write_mask)
> >  {
> > -    int ret = rmw_mip(env, 0, ret_value, new_value,
> > -                      write_mask & hip_writable_mask);
> > +    RISCVCPU *cpu = env_archcpu(env);
> > +    /* Allow software control of delegable interrupts not claimed by 
> > hardware */
> > +    uint64_t mask = ((uint64_t)write_mask) & delegable_ints &
> > +                    hip_writable_mask &
> > +                    ~env->miclaim & TLOWBITS64;
> > +    uint64_t old_mip;
> >
> > -    *ret_value &= hip_writable_mask;
> > +    if (mask) {
> > +        old_mip = riscv_cpu_update_mip(cpu, mask, (new_value & mask));
> > +    } else {
> > +        old_mip = env->mip;
> > +    }
> >
> > -    return ret;
> > +    if (ret_value) {
> > +        *ret_value = old_mip & hip_writable_mask;
> > +    }
> > +
> > +    return 0;
> >  }
> >
> >  static int read_hie(CPURISCVState *env, int csrno, target_ulong *val)
> > @@ -1009,8 +1798,9 @@ static int read_hie(CPURISCVState *env, int csrno, 
> > target_ulong *val)
> >
> >  static int write_hie(CPURISCVState *env, int csrno, target_ulong val)
> >  {
> > -    target_ulong newval = (env->mie & ~VS_MODE_INTERRUPTS) | (val & 
> > VS_MODE_INTERRUPTS);
> > -    return write_mie(env, CSR_MIE, newval);
> > +    uint64_t mask = VS_MODE_INTERRUPTS & all_ints & TLOWBITS64;
> > +    env->mie = (env->mie & ~mask) | ((uint64_t)val & mask);
> > +    return 0;
> >  }
> >
> >  static int read_hcounteren(CPURISCVState *env, int csrno, target_ulong 
> > *val)
> > @@ -1128,6 +1918,110 @@ static int write_htimedeltah(CPURISCVState *env, 
> > int csrno, target_ulong val)
> >      return 0;
> >  }
> >
> > +static int read_hvicontrol(CPURISCVState *env, int csrno, target_ulong 
> > *val)
> > +{
> > +    *val = env->hvicontrol;
> > +    return 0;
> > +}
> > +
> > +static int write_hvicontrol(CPURISCVState *env, int csrno, target_ulong 
> > val)
> > +{
> > +    env->hvicontrol = val & HVICONTROL_VALID_MASK;
> > +    return 0;
> > +}
> > +
> > +static int read_hvipriox(CPURISCVState *env, int first_index,
> > +                         uint8_t *iprio, target_ulong *val)
> > +{
> > +    int i, irq, rdzero, num_irqs = 4 * (TARGET_LONG_BITS / 32);
> > +
> > +    /* First index has to be multiple of numbe of irqs per register */
> > +    if (first_index % num_irqs) {
> > +        return (riscv_cpu_virt_enabled(env)) ?
> > +               -RISCV_EXCP_VIRT_INSTRUCTION_FAULT : 
> > -RISCV_EXCP_ILLEGAL_INST;
> > +    }
> > +
> > +    /* Fill-up return value */
> > +    *val = 0;
> > +    for (i = 0; i < num_irqs; i++) {
> > +        if (riscv_cpu_hviprio_index2irq(first_index + i, &irq, &rdzero)) {
> > +            continue;
> > +        }
> > +        if (rdzero) {
> > +            continue;
> > +        }
> > +        *val |= ((target_ulong)iprio[irq]) << (i * 8);
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +static int write_hvipriox(CPURISCVState *env, int first_index,
> > +                          uint8_t *iprio, target_ulong val)
> > +{
> > +    int i, irq, rdzero, num_irqs = 4 * (TARGET_LONG_BITS / 32);
> > +
> > +    /* First index has to be multiple of numbe of irqs per register */
> > +    if (first_index % num_irqs) {
> > +        return (riscv_cpu_virt_enabled(env)) ?
> > +               -RISCV_EXCP_VIRT_INSTRUCTION_FAULT : 
> > -RISCV_EXCP_ILLEGAL_INST;
> > +    }
> > +
> > +    /* Fill-up priority arrary */
> > +    for (i = 0; i < num_irqs; i++) {
> > +        if (riscv_cpu_hviprio_index2irq(first_index + i, &irq, &rdzero)) {
> > +            continue;
> > +        }
> > +        if (rdzero) {
> > +            iprio[irq] = 0;
> > +        } else {
> > +            iprio[irq] = (val >> (i * 8)) & 0xff;
> > +        }
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +static int read_hviprio1(CPURISCVState *env, int csrno, target_ulong *val)
> > +{
> > +    return read_hvipriox(env, 0, env->hviprio, val);
> > +}
> > +
> > +static int write_hviprio1(CPURISCVState *env, int csrno, target_ulong val)
> > +{
> > +    return write_hvipriox(env, 0, env->hviprio, val);
> > +}
> > +
> > +static int read_hviprio1h(CPURISCVState *env, int csrno, target_ulong *val)
> > +{
> > +    return read_hvipriox(env, 4, env->hviprio, val);
> > +}
> > +
> > +static int write_hviprio1h(CPURISCVState *env, int csrno, target_ulong val)
> > +{
> > +    return write_hvipriox(env, 4, env->hviprio, val);
> > +}
> > +
> > +static int read_hviprio2(CPURISCVState *env, int csrno, target_ulong *val)
> > +{
> > +    return read_hvipriox(env, 8, env->hviprio, val);
> > +}
> > +
> > +static int write_hviprio2(CPURISCVState *env, int csrno, target_ulong val)
> > +{
> > +    return write_hvipriox(env, 8, env->hviprio, val);
> > +}
> > +
> > +static int read_hviprio2h(CPURISCVState *env, int csrno, target_ulong *val)
> > +{
> > +    return read_hvipriox(env, 12, env->hviprio, val);
> > +}
> > +
> > +static int write_hviprio2h(CPURISCVState *env, int csrno, target_ulong val)
> > +{
> > +    return write_hvipriox(env, 12, env->hviprio, val);
> > +}
> > +
> >  /* Virtual CSR Registers */
> >  static int read_vsstatus(CPURISCVState *env, int csrno, target_ulong *val)
> >  {
> > @@ -1428,6 +2322,25 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
> >      [CSR_MBADADDR] = { "mbadaddr", any,  read_mbadaddr, write_mbadaddr },
> >      [CSR_MIP]      = { "mip",      any,  NULL,    NULL, rmw_mip        },
> >
> > +    /* Machine-Level Window to Indirectly Accessed Registers (AIA) */
> > +    [CSR_MISELECT] = { "miselect", aia_any,   NULL, NULL,    rmw_xiselect 
> > },
> > +    [CSR_MIREG]    = { "mireg",    aia_any,   NULL, NULL,    rmw_xireg },
> > +
> > +    /* Machine-Level Interrupts (AIA) */
> > +    [CSR_MTOPI]    = { "mtopi",    aia_any,   read_mtopi },
> > +
> > +    /* Machine-Level IMSIC Interface (AIA) */
> > +    [CSR_MSETEIPNUM] = { "mseteipnum", aia_any, read_xsetclreinum, 
> > write_xsetclreinum },
> > +    [CSR_MCLREIPNUM] = { "mclreipnum", aia_any, read_xsetclreinum, 
> > write_xsetclreinum },
> > +    [CSR_MSETEIENUM] = { "mseteienum", aia_any, read_xsetclreinum, 
> > write_xsetclreinum },
> > +    [CSR_MCLREIENUM] = { "mclreienum", aia_any, read_xsetclreinum, 
> > write_xsetclreinum },
> > +    [CSR_MCLAIMEI]   = { "mclaimei",   aia_any, read_xclaimei },
> > +
> > +    /* Machine-Level High-Half CSRs (AIA) */
> > +    [CSR_MIDELEGH] = { "midelegh", aia_any32, read_midelegh, 
> > write_midelegh },
> > +    [CSR_MIEH]     = { "mieh",     aia_any32, read_mieh,     write_mieh    
> >  },
> > +    [CSR_MIPH]     = { "miph",     aia_any32, NULL,    NULL, rmw_miph      
> >  },
> > +
> >      /* Supervisor Trap Setup */
> >      [CSR_SSTATUS]    = { "sstatus",    smode, read_sstatus,    
> > write_sstatus    },
> >      [CSR_SIE]        = { "sie",        smode, read_sie,        write_sie   
> >      },
> > @@ -1444,6 +2357,24 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
> >      /* Supervisor Protection and Translation */
> >      [CSR_SATP]     = { "satp",     smode, read_satp,    write_satp      },
> >
> > +    /* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */
> > +    [CSR_SISELECT]   = { "siselect",   aia_smode, NULL, NULL, rmw_xiselect 
> > },
> > +    [CSR_SIREG]      = { "sireg",      aia_smode, NULL, NULL, rmw_xireg },
> > +
> > +    /* Supervisor-Level Interrupts (AIA) */
> > +    [CSR_STOPI]      = { "stopi",      aia_smode, read_stopi },
> > +
> > +    /* Supervisor-Level IMSIC Interface (AIA) */
> > +    [CSR_SSETEIPNUM] = { "sseteipnum", aia_smode, read_xsetclreinum, 
> > write_xsetclreinum },
> > +    [CSR_SCLREIPNUM] = { "sclreipnum", aia_smode, read_xsetclreinum, 
> > write_xsetclreinum },
> > +    [CSR_SSETEIENUM] = { "sseteienum", aia_smode, read_xsetclreinum, 
> > write_xsetclreinum },
> > +    [CSR_SCLREIENUM] = { "sclreienum", aia_smode, read_xsetclreinum, 
> > write_xsetclreinum },
> > +    [CSR_SCLAIMEI]   = { "sclaimei",   aia_smode, read_xclaimei },
> > +
> > +    /* Supervisor-Level High-Half CSRs (AIA) */
> > +    [CSR_SIEH]       = { "sieh",       aia_smode32, read_sieh,  write_sieh 
> > },
> > +    [CSR_SIPH]       = { "siph",       aia_smode32, NULL, NULL, rmw_siph   
> > },
> > +
> >      [CSR_HSTATUS]     = { "hstatus",     hmode,   read_hstatus,     
> > write_hstatus     },
> >      [CSR_HEDELEG]     = { "hedeleg",     hmode,   read_hedeleg,     
> > write_hedeleg     },
> >      [CSR_HIDELEG]     = { "hideleg",     hmode,   read_hideleg,     
> > write_hideleg     },
> > @@ -1472,6 +2403,32 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
> >      [CSR_MTVAL2]      = { "mtval2",      hmode,   read_mtval2,      
> > write_mtval2      },
> >      [CSR_MTINST]      = { "mtinst",      hmode,   read_mtinst,      
> > write_mtinst      },
> >
> > +    /* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) 
> > */
> > +    [CSR_HVICONTROL]  = { "hvicontrol",  aia_hmode, read_hvicontrol, 
> > write_hvicontrol },
> > +    [CSR_HVIPRIO1]    = { "hviprio1",    aia_hmode, read_hviprio1,   
> > write_hviprio1 },
> > +    [CSR_HVIPRIO2]    = { "hviprio2",    aia_hmode, read_hviprio2,   
> > write_hviprio2 },
> > +
> > +    /* VS-Level Window to Indirectly Accessed Registers (H-extension with 
> > AIA) */
> > +    [CSR_VSISELECT]   = { "vsiselect",   aia_hmode, NULL, NULL,      
> > rmw_xiselect },
> > +    [CSR_VSIREG]      = { "vsireg",      aia_hmode, NULL, NULL,      
> > rmw_xireg },
> > +
> > +    /* VS-Level Interrupts (H-extension with AIA) */
> > +    [CSR_VSTOPI]      = { "vstopi",      aia_hmode, read_vstopi },
> > +
> > +    /* VS-Level IMSIC Interface (H-extension with AIA) */
> > +    [CSR_VSSETEIPNUM] = { "vsseteipnum", aia_hmode, read_xsetclreinum, 
> > write_xsetclreinum },
> > +    [CSR_VSCLREIPNUM] = { "vsclreipnum", aia_hmode, read_xsetclreinum, 
> > write_xsetclreinum },
> > +    [CSR_VSSETEIENUM] = { "vsseteienum", aia_hmode, read_xsetclreinum, 
> > write_xsetclreinum },
> > +    [CSR_VSCLREIENUM] = { "vsclreienum", aia_hmode, read_xsetclreinum, 
> > write_xsetclreinum },
> > +
> > +    /* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */
> > +    [CSR_HIDELEGH]    = { "hidelegh",    aia_hmode32, read_hidelegh,  
> > write_hidelegh },
> > +    [CSR_HVIPH]       = { "hviph",       aia_hmode32, NULL, NULL,     
> > rmw_hviph },
> > +    [CSR_HVIPRIO1H]   = { "hviprio1h",   aia_hmode32, read_hviprio1h, 
> > write_hviprio1h },
> > +    [CSR_HVIPRIO2H]   = { "hviprio2h",   aia_hmode32, read_hviprio2h, 
> > write_hviprio2h },
> > +    [CSR_VSIEH]       = { "vsieh",       aia_hmode32, read_vsieh,     
> > write_vsieh },
> > +    [CSR_VSIPH]       = { "vsiep",       aia_hmode32, NULL, NULL,     
> > rmw_vsiph },
> > +
> >      /* Physical Memory Protection */
> >      [CSR_PMPCFG0]    = { "pmpcfg0",   pmp, read_pmpcfg,  write_pmpcfg  },
> >      [CSR_PMPCFG1]    = { "pmpcfg1",   pmp, read_pmpcfg,  write_pmpcfg  },
> > diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> > index 44d4015bd6..f7fa48c240 100644
> > --- a/target/riscv/machine.c
> > +++ b/target/riscv/machine.c
> > @@ -102,19 +102,22 @@ static const VMStateDescription vmstate_vector = {
> >
> >  static const VMStateDescription vmstate_hyper = {
> >      .name = "cpu/hyper",
> > -    .version_id = 1,
> > -    .minimum_version_id = 1,
> > +    .version_id = 2,
> > +    .minimum_version_id = 2,
> >      .needed = hyper_needed,
> >      .fields = (VMStateField[]) {
> >          VMSTATE_UINTTL(env.hstatus, RISCVCPU),
> >          VMSTATE_UINTTL(env.hedeleg, RISCVCPU),
> > -        VMSTATE_UINTTL(env.hideleg, RISCVCPU),
> > +        VMSTATE_UINT64(env.hideleg, RISCVCPU),
> >          VMSTATE_UINTTL(env.hcounteren, RISCVCPU),
> >          VMSTATE_UINTTL(env.htval, RISCVCPU),
> >          VMSTATE_UINTTL(env.htinst, RISCVCPU),
> >          VMSTATE_UINTTL(env.hgatp, RISCVCPU),
> >          VMSTATE_UINT64(env.htimedelta, RISCVCPU),
> >
> > +        VMSTATE_UINT8_ARRAY(env.hviprio, RISCVCPU, 64),
> > +        VMSTATE_UINTTL(env.hvicontrol, RISCVCPU),
> > +
> >          VMSTATE_UINT64(env.vsstatus, RISCVCPU),
> >          VMSTATE_UINTTL(env.vstvec, RISCVCPU),
> >          VMSTATE_UINTTL(env.vsscratch, RISCVCPU),
> > @@ -122,6 +125,7 @@ static const VMStateDescription vmstate_hyper = {
> >          VMSTATE_UINTTL(env.vscause, RISCVCPU),
> >          VMSTATE_UINTTL(env.vstval, RISCVCPU),
> >          VMSTATE_UINTTL(env.vsatp, RISCVCPU),
> > +        VMSTATE_UINTTL(env.vsiselect, RISCVCPU),
> >
> >          VMSTATE_UINTTL(env.mtval2, RISCVCPU),
> >          VMSTATE_UINTTL(env.mtinst, RISCVCPU),
> > @@ -140,11 +144,13 @@ static const VMStateDescription vmstate_hyper = {
> >
> >  const VMStateDescription vmstate_riscv_cpu = {
> >      .name = "cpu",
> > -    .version_id = 1,
> > -    .minimum_version_id = 1,
> > +    .version_id = 2,
> > +    .minimum_version_id = 2,
> >      .fields = (VMStateField[]) {
> >          VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32),
> >          VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32),
> > +        VMSTATE_UINT8_ARRAY(env.miprio, RISCVCPU, 64),
> > +        VMSTATE_UINT8_ARRAY(env.siprio, RISCVCPU, 64),
> >          VMSTATE_UINTTL(env.pc, RISCVCPU),
> >          VMSTATE_UINTTL(env.load_res, RISCVCPU),
> >          VMSTATE_UINTTL(env.load_val, RISCVCPU),
> > @@ -161,10 +167,10 @@ const VMStateDescription vmstate_riscv_cpu = {
> >          VMSTATE_UINTTL(env.resetvec, RISCVCPU),
> >          VMSTATE_UINTTL(env.mhartid, RISCVCPU),
> >          VMSTATE_UINT64(env.mstatus, RISCVCPU),
> > -        VMSTATE_UINTTL(env.mip, RISCVCPU),
> > -        VMSTATE_UINT32(env.miclaim, RISCVCPU),
> > -        VMSTATE_UINTTL(env.mie, RISCVCPU),
> > -        VMSTATE_UINTTL(env.mideleg, RISCVCPU),
> > +        VMSTATE_UINT64(env.mip, RISCVCPU),
> > +        VMSTATE_UINT64(env.miclaim, RISCVCPU),
> > +        VMSTATE_UINT64(env.mie, RISCVCPU),
> > +        VMSTATE_UINT64(env.mideleg, RISCVCPU),
> >          VMSTATE_UINTTL(env.sptbr, RISCVCPU),
> >          VMSTATE_UINTTL(env.satp, RISCVCPU),
> >          VMSTATE_UINTTL(env.sbadaddr, RISCVCPU),
> > @@ -177,6 +183,8 @@ const VMStateDescription vmstate_riscv_cpu = {
> >          VMSTATE_UINTTL(env.mepc, RISCVCPU),
> >          VMSTATE_UINTTL(env.mcause, RISCVCPU),
> >          VMSTATE_UINTTL(env.mtval, RISCVCPU),
> > +        VMSTATE_UINTTL(env.miselect, RISCVCPU),
> > +        VMSTATE_UINTTL(env.siselect, RISCVCPU),
> >          VMSTATE_UINTTL(env.scounteren, RISCVCPU),
> >          VMSTATE_UINTTL(env.mcounteren, RISCVCPU),
> >          VMSTATE_UINTTL(env.sscratch, RISCVCPU),
> > --
> > 2.25.1
> >
> >



reply via email to

[Prev in Thread] Current Thread [Next in Thread]