Anup Patel <a...@brainfault.org> 於 2021年12月30日 週四 下午8:53寫道:
> From: Anup Patel <anup.pa...@wdc.com> > > The AIA specification defines IMSIC interface CSRs for easy access > to the per-HART IMSIC registers without using indirect xiselect and > xireg CSRs. This patch implements the AIA IMSIC interface CSRs. > > Signed-off-by: Anup Patel <anup.pa...@wdc.com> > Signed-off-by: Anup Patel <a...@brainfault.org> > --- > target/riscv/csr.c | 202 +++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 202 insertions(+) > > diff --git a/target/riscv/csr.c b/target/riscv/csr.c > index 488877e89c..89e74f848d 100644 > --- a/target/riscv/csr.c > +++ b/target/riscv/csr.c > @@ -906,6 +906,16 @@ static int aia_xlate_vs_csrno(CPURISCVState *env, int > csrno) > return CSR_VSISELECT; > case CSR_SIREG: > return CSR_VSIREG; > + case CSR_SSETEIPNUM: > + return CSR_VSSETEIPNUM; > + case CSR_SCLREIPNUM: > + return CSR_VSCLREIPNUM; > + case CSR_SSETEIENUM: > + return CSR_VSSETEIENUM; > + case CSR_SCLREIENUM: > + return CSR_VSCLREIENUM; > + case CSR_STOPEI: > + return CSR_VSTOPEI; > default: > return csrno; > }; > @@ -1058,6 +1068,177 @@ done: > return RISCV_EXCP_NONE; > } > > +static int rmw_xsetclreinum(CPURISCVState *env, int csrno, target_ulong > *val, > + target_ulong new_val, target_ulong wr_mask) > +{ > + int ret = -EINVAL; > + bool set, pend, virt; > + target_ulong priv, isel, vgein, xlen, nval, wmask; > + > + /* 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; > Missing: *pend = true;* here? Frank Chang > + 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->aia_ireg_rmw_fn[priv]) { > + goto done; > + } > + > + /* Find the selected guest interrupt file */ > + vgein = (virt) ? get_field(env->hstatus, HSTATUS_VGEIN) : 0; > + > + /* Selected guest interrupt file should be valid */ > + if (virt && (!vgein || env->geilen < vgein)) { > + goto done; > + } > + > + /* Set/Clear CSRs always read zero */ > + if (val) { > + *val = 0; > + } > + > + if (wr_mask) { > + /* Get interrupt number */ > + new_val &= wr_mask; > + > + /* Find target interrupt pending/enable register */ > + xlen = riscv_cpu_mxl_bits(env); > + isel = (new_val / xlen); > + isel *= (xlen / IMSIC_EIPx_BITS); > + isel += (pend) ? ISELECT_IMSIC_EIP0 : ISELECT_IMSIC_EIE0; > + > + /* Find the interrupt bit to be set/clear */ > + wmask = ((target_ulong)1) << (new_val % xlen); > + nval = (set) ? wmask : 0; > + > + /* Call machine specific IMSIC register emulation */ > + ret = env->aia_ireg_rmw_fn[priv](env->aia_ireg_rmw_fn_arg[priv], > + AIA_MAKE_IREG(isel, priv, virt, > + vgein, xlen), > + NULL, nval, wmask); > + } else { > + ret = 0; > + } > + > +done: > + if (ret) { > + return (riscv_cpu_virt_enabled(env) && virt) ? > + RISCV_EXCP_VIRT_INSTRUCTION_FAULT : > RISCV_EXCP_ILLEGAL_INST; > + } > + return RISCV_EXCP_NONE; > +} > + > +static int rmw_xtopei(CPURISCVState *env, int csrno, target_ulong *val, > + target_ulong new_val, target_ulong wr_mask) > +{ > + bool virt; > + int ret = -EINVAL; > + target_ulong priv, 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_MTOPEI: > + priv = PRV_M; > + break; > + case CSR_STOPEI: > + priv = PRV_S; > + break; > + case CSR_VSTOPEI: > + priv = PRV_S; > + virt = true; > + break; > + default: > + goto done; > + }; > + > + /* IMSIC CSRs only available when machine implements IMSIC. */ > + if (!env->aia_ireg_rmw_fn[priv]) { > + goto done; > + } > + > + /* Find the selected guest interrupt file */ > + vgein = (virt) ? get_field(env->hstatus, HSTATUS_VGEIN) : 0; > + > + /* Selected guest interrupt file should be valid */ > + if (virt && (!vgein || env->geilen < vgein)) { > + goto done; > + } > + > + /* Call machine specific IMSIC register emulation for TOPEI */ > + ret = env->aia_ireg_rmw_fn[priv](env->aia_ireg_rmw_fn_arg[priv], > + AIA_MAKE_IREG(ISELECT_IMSIC_TOPEI, priv, virt, vgein, > + riscv_cpu_mxl_bits(env)), > + val, new_val, wr_mask); > + > +done: > + if (ret) { > + return (riscv_cpu_virt_enabled(env) && virt) ? > + RISCV_EXCP_VIRT_INSTRUCTION_FAULT : > RISCV_EXCP_ILLEGAL_INST; > + } > + return RISCV_EXCP_NONE; > +} > + > static RISCVException read_mtvec(CPURISCVState *env, int csrno, > target_ulong *val) > { > @@ -2706,6 +2887,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { > /* Machine-Level Interrupts (AIA) */ > [CSR_MTOPI] = { "mtopi", aia_any, read_mtopi }, > > + /* Machine-Level IMSIC Interface (AIA) */ > + [CSR_MSETEIPNUM] = { "mseteipnum", aia_any, NULL, NULL, > rmw_xsetclreinum }, > + [CSR_MCLREIPNUM] = { "mclreipnum", aia_any, NULL, NULL, > rmw_xsetclreinum }, > + [CSR_MSETEIENUM] = { "mseteienum", aia_any, NULL, NULL, > rmw_xsetclreinum }, > + [CSR_MCLREIENUM] = { "mclreienum", aia_any, NULL, NULL, > rmw_xsetclreinum }, > + [CSR_MTOPEI] = { "mtopei", aia_any, NULL, NULL, rmw_xtopei }, > + > /* Virtual Interrupts for Supervisor Level (AIA) */ > [CSR_MVIEN] = { "mvien", aia_any, read_zero, write_ignore }, > [CSR_MVIP] = { "mvip", aia_any, read_zero, write_ignore }, > @@ -2740,6 +2928,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { > /* Supervisor-Level Interrupts (AIA) */ > [CSR_STOPI] = { "stopi", aia_smode, read_stopi }, > > + /* Supervisor-Level IMSIC Interface (AIA) */ > + [CSR_SSETEIPNUM] = { "sseteipnum", aia_smode, NULL, NULL, > rmw_xsetclreinum }, > + [CSR_SCLREIPNUM] = { "sclreipnum", aia_smode, NULL, NULL, > rmw_xsetclreinum }, > + [CSR_SSETEIENUM] = { "sseteienum", aia_smode, NULL, NULL, > rmw_xsetclreinum }, > + [CSR_SCLREIENUM] = { "sclreienum", aia_smode, NULL, NULL, > rmw_xsetclreinum }, > + [CSR_STOPEI] = { "stopei", aia_smode, NULL, NULL, rmw_xtopei > }, > + > /* Supervisor-Level High-Half CSRs (AIA) */ > [CSR_SIEH] = { "sieh", aia_smode32, NULL, NULL, rmw_sieh }, > [CSR_SIPH] = { "siph", aia_smode32, NULL, NULL, rmw_siph }, > @@ -2785,6 +2980,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { > /* 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, NULL, NULL, > rmw_xsetclreinum }, > + [CSR_VSCLREIPNUM] = { "vsclreipnum", aia_hmode, NULL, NULL, > rmw_xsetclreinum }, > + [CSR_VSSETEIENUM] = { "vsseteienum", aia_hmode, NULL, NULL, > rmw_xsetclreinum }, > + [CSR_VSCLREIENUM] = { "vsclreienum", aia_hmode, NULL, NULL, > rmw_xsetclreinum }, > + [CSR_VSTOPEI] = { "vstopei", aia_hmode, NULL, NULL, > rmw_xtopei }, > + > /* 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 > > >