Anup Patel <a...@brainfault.org> 於 2021年12月30日 週四 下午8:47寫道:
> From: Anup Patel <anup.pa...@wdc.com> > > The AIA specification introduces new [m|s|vs]topi CSRs for > reporting pending local IRQ number and associated IRQ priority. > > Signed-off-by: Anup Patel <anup.pa...@wdc.com> > Signed-off-by: Anup Patel <a...@brainfault.org> > --- > target/riscv/csr.c | 156 +++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 156 insertions(+) > > diff --git a/target/riscv/csr.c b/target/riscv/csr.c > index 55e747fbf7..5a27c3bfbb 100644 > --- a/target/riscv/csr.c > +++ b/target/riscv/csr.c > @@ -190,6 +190,15 @@ static int smode32(CPURISCVState *env, int csrno) > 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)) { > @@ -502,6 +511,8 @@ static RISCVException read_timeh(CPURISCVState *env, > int csrno, > #define VS_MODE_INTERRUPTS ((uint64_t)(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)) > #define HS_MODE_INTERRUPTS ((uint64_t)(MIP_SGEIP | VS_MODE_INTERRUPTS)) > > +#define VSTOPI_NUM_SRCS 5 > Nit: VSTOPI_NUM_SRCS can be reduced to 2 as AIA spec says: The list of candidate interrupts can be reduced to two finalists relatively. But it's fine to keep it to 5 if you think it has better readability. > + > static const uint64_t delegable_ints = S_MODE_INTERRUPTS | > VS_MODE_INTERRUPTS; > static const uint64_t vs_delegable_ints = VS_MODE_INTERRUPTS; > @@ -862,6 +873,28 @@ static RISCVException rmw_mieh(CPURISCVState *env, > int csrno, > return ret; > } > > +static int read_mtopi(CPURISCVState *env, int csrno, target_ulong *val) > +{ > + int irq; > + uint8_t iprio; > + > + irq = riscv_cpu_mirq_pending(env); > + if (irq <= 0 || irq > 63) { > + *val = 0; > + } else { > + iprio = env->miprio[irq]; > + if (!iprio) { > + if (riscv_cpu_default_priority(irq) > IPRIO_DEFAULT_M) { > + iprio = IPRIO_MMAXIPRIO; > + } > + } > + *val = (irq & TOPI_IID_MASK) << TOPI_IID_SHIFT; > + *val |= iprio; > + } > + > + return RISCV_EXCP_NONE; > +} > + > static RISCVException read_mtvec(CPURISCVState *env, int csrno, > target_ulong *val) > { > @@ -1391,6 +1424,120 @@ static RISCVException write_satp(CPURISCVState > *env, int csrno, > return RISCV_EXCP_NONE; > } > > +static int read_vstopi(CPURISCVState *env, int csrno, target_ulong *val) > +{ > + int irq, ret; > + target_ulong topei; > + uint64_t vseip, vsgein; > + uint32_t iid, iprio, hviid, hviprio, gein; > + uint32_t s, scount = 0, siid[VSTOPI_NUM_SRCS], > siprio[VSTOPI_NUM_SRCS]; > + > + gein = get_field(env->hstatus, HSTATUS_VGEIN); > + hviid = get_field(env->hvictl, HVICTL_IID); > + hviprio = get_field(env->hvictl, HVICTL_IPRIO); > + > + if (gein) { > + vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0; > + vseip = env->mie & (env->mip | vsgein) & MIP_VSEIP; > + if (gein <= env->geilen && vseip) { > + siid[scount] = IRQ_S_EXT; > + siprio[scount] = IPRIO_MMAXIPRIO + 1; > + if (env->aia_ireg_rmw_fn[PRV_S]) { > + /* > + * Call machine specific IMSIC register emulation for > + * reading TOPEI. > + */ > + ret = env->aia_ireg_rmw_fn[PRV_S]( > + env->aia_ireg_rmw_fn_arg[PRV_S], > + AIA_MAKE_IREG(ISELECT_IMSIC_TOPEI, PRV_S, true, > gein, > + riscv_cpu_mxl_bits(env)), > + &topei, 0, 0); > + if (!ret && topei) { > + siprio[scount] = topei & IMSIC_TOPEI_IPRIO_MASK; > + } > + } > + scount++; > + } > + } else { > + if (hviid == IRQ_S_EXT && hviprio) { > + siid[scount] = IRQ_S_EXT; > + siprio[scount] = hviprio; > + scount++; > + } > + } > + > + if (env->hvictl & HVICTL_VTI) { > + if (hviid != IRQ_S_EXT) { > + siid[scount] = hviid; > + siprio[scount] = hviprio; > + scount++; > + } > + } else { > + irq = riscv_cpu_vsirq_pending(env); > + if (irq != IRQ_S_EXT && 0 < irq && irq <= 63) { > + siid[scount] = irq; > + siprio[scount] = env->hviprio[irq]; > + scount++; > + } > + } > + > + iid = 0; > + iprio = UINT_MAX; > + for (s = 0; s < scount; s++) { > + if (siprio[s] < iprio) { > + iid = siid[s]; > + iprio = siprio[s]; > + } > + } > + > + if (iid) { > + if (env->hvictl & HVICTL_IPRIOM) { > + if (iprio > IPRIO_MMAXIPRIO) { > + iprio = IPRIO_MMAXIPRIO; > + } > + if (!iprio) { > + if (riscv_cpu_default_priority(iid) > IPRIO_DEFAULT_S) { > + iprio = IPRIO_MMAXIPRIO; > + } > + } > + } else { > + iprio = 1; > + } > + } else { > + iprio = 0; > + } > + > + *val = (iid & TOPI_IID_MASK) << TOPI_IID_SHIFT; > + *val |= iprio; > + return RISCV_EXCP_NONE; > +} > + > +static int read_stopi(CPURISCVState *env, int csrno, target_ulong *val) > +{ > + int irq; > + uint8_t iprio; > + > + 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 { > + iprio = env->siprio[irq]; > + if (!iprio) { > + if (riscv_cpu_default_priority(irq) > IPRIO_DEFAULT_S) { > + iprio = IPRIO_MMAXIPRIO; > + } > + } > + *val = (irq & TOPI_IID_MASK) << TOPI_IID_SHIFT; > + *val |= iprio; > + } > + > + return RISCV_EXCP_NONE; > +} > + > /* Hypervisor Extensions */ > static RISCVException read_hstatus(CPURISCVState *env, int csrno, > target_ulong *val) > @@ -2389,6 +2536,9 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { > [CSR_MTVAL] = { "mtval", any, read_mtval, write_mtval }, > [CSR_MIP] = { "mip", any, NULL, NULL, rmw_mip }, > > + /* Machine-Level Interrupts (AIA) */ > + [CSR_MTOPI] = { "mtopi", aia_any, read_mtopi }, > + > /* Virtual Interrupts for Supervisor Level (AIA) */ > [CSR_MVIEN] = { "mvien", aia_any, read_zero, write_ignore }, > [CSR_MVIP] = { "mvip", aia_any, read_zero, write_ignore }, > @@ -2416,6 +2566,9 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { > /* Supervisor Protection and Translation */ > [CSR_SATP] = { "satp", smode, read_satp, write_satp }, > > + /* Supervisor-Level Interrupts (AIA) */ > + [CSR_STOPI] = { "stopi", aia_smode, read_stopi }, > + > /* Supervisor-Level High-Half CSRs (AIA) */ > [CSR_SIEH] = { "sieh", aia_smode32, NULL, NULL, rmw_sieh }, > [CSR_SIPH] = { "siph", aia_smode32, NULL, NULL, rmw_siph }, > @@ -2454,6 +2607,9 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { > [CSR_HVIPRIO1] = { "hviprio1", aia_hmode, read_hviprio1, > write_hviprio1 }, > [CSR_HVIPRIO2] = { "hviprio2", aia_hmode, read_hviprio2, > write_hviprio2 }, > > + /* VS-Level Interrupts (H-extension with AIA) */ > + [CSR_VSTOPI] = { "vstopi", aia_hmode, read_vstopi }, > + > /* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */ > [CSR_HIDELEGH] = { "hidelegh", aia_hmode32, NULL, NULL, > rmw_hidelegh }, > [CSR_HVIENH] = { "hvienh", aia_hmode32, read_zero, > write_ignore }, > -- > 2.25.1 > > > Reviewed-by: Frank Chang <frank.ch...@sifive.com>