On Wed, Jan 12, 2022 at 5:46 PM Frank Chang <frank.ch...@sifive.com> wrote: > > 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.
Let's keep is 5 for now. This is little high to ensure that we don't run out space in the candidate array. Regards, Anup > >> >> + >> 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>