Message ID | 20230522131123.3498539-3-tommy.wu@sifive.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | target/riscv: Add Smrnmi support. | expand |
On 5/22/23 10:11, Tommy Wu wrote: > Signed-off-by: Frank Chang <frank.chang@sifive.com> > Signed-off-by: Tommy Wu <tommy.wu@sifive.com> > --- Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> > target/riscv/cpu.c | 5 +++ > target/riscv/cpu.h | 4 ++ > target/riscv/cpu_bits.h | 11 ++++++ > target/riscv/csr.c | 82 +++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 102 insertions(+) > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > index 39b74569b1..1b645c5485 100644 > --- a/target/riscv/cpu.c > +++ b/target/riscv/cpu.c > @@ -810,6 +810,11 @@ static void riscv_cpu_reset_hold(Object *obj) > riscv_trigger_init(env); > } > > + if (cpu->cfg.ext_smrnmi) { > + env->rnmip = 0; > + env->mnstatus = set_field(env->mnstatus, MNSTATUS_NMIE, false); > + } > + > if (kvm_enabled()) { > kvm_riscv_reset_vcpu(cpu); > } > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h > index 6c14b93cb5..f44fd95f16 100644 > --- a/target/riscv/cpu.h > +++ b/target/riscv/cpu.h > @@ -368,6 +368,10 @@ struct CPUArchState { > uint64_t kvm_timer_frequency; > > /* RNMI */ > + target_ulong mnscratch; > + target_ulong mnepc; > + target_ulong mncause; /* mncause without bit XLEN-1 set to 1 */ > + target_ulong mnstatus; > target_ulong rnmip; > uint64_t rnmi_irqvec; > uint64_t rnmi_excpvec; > diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h > index 7cb43b88f3..d7bd4538ab 100644 > --- a/target/riscv/cpu_bits.h > +++ b/target/riscv/cpu_bits.h > @@ -355,6 +355,12 @@ > #define CSR_PMPADDR14 0x3be > #define CSR_PMPADDR15 0x3bf > > +/* RNMI */ > +#define CSR_MNSCRATCH 0x740 > +#define CSR_MNEPC 0x741 > +#define CSR_MNCAUSE 0x742 > +#define CSR_MNSTATUS 0x744 > + > /* Debug/Trace Registers (shared with Debug Mode) */ > #define CSR_TSELECT 0x7a0 > #define CSR_TDATA1 0x7a1 > @@ -624,6 +630,11 @@ typedef enum { > #define SATP64_ASID 0x0FFFF00000000000ULL > #define SATP64_PPN 0x00000FFFFFFFFFFFULL > > +/* RNMI mnstatus CSR mask */ > +#define MNSTATUS_NMIE 0x00000008 > +#define MNSTATUS_MNPV 0x00000080 > +#define MNSTATUS_MNPP 0x00001800 > + > /* VM modes (satp.mode) privileged ISA 1.10 */ > #define VM_1_10_MBARE 0 > #define VM_1_10_SV32 1 > diff --git a/target/riscv/csr.c b/target/riscv/csr.c > index 4451bd1263..a1d39fc116 100644 > --- a/target/riscv/csr.c > +++ b/target/riscv/csr.c > @@ -536,6 +536,18 @@ static RISCVException debug(CPURISCVState *env, int csrno) > > return RISCV_EXCP_ILLEGAL_INST; > } > + > +static RISCVException rnmi(CPURISCVState *env, int csrno) > +{ > + RISCVCPU *cpu = env_archcpu(env); > + > + if (cpu->cfg.ext_smrnmi) { > + return RISCV_EXCP_NONE; > + } > + > + return RISCV_EXCP_ILLEGAL_INST; > +} > + > #endif > > static RISCVException seed(CPURISCVState *env, int csrno) > @@ -2336,6 +2348,66 @@ static RISCVException rmw_miph(CPURISCVState *env, int csrno, > return ret; > } > > +static int read_mnscratch(CPURISCVState *env, int csrno, target_ulong *val) > +{ > + *val = env->mnscratch; > + return RISCV_EXCP_NONE; > +} > + > +static int write_mnscratch(CPURISCVState *env, int csrno, target_ulong val) > +{ > + env->mnscratch = val; > + return RISCV_EXCP_NONE; > +} > + > +static int read_mnepc(CPURISCVState *env, int csrno, target_ulong *val) > +{ > + *val = env->mnepc; > + return RISCV_EXCP_NONE; > +} > + > +static int write_mnepc(CPURISCVState *env, int csrno, target_ulong val) > +{ > + env->mnepc = val; > + return RISCV_EXCP_NONE; > +} > + > +static int read_mncause(CPURISCVState *env, int csrno, target_ulong *val) > +{ > + *val = env->mncause; > + return RISCV_EXCP_NONE; > +} > + > +static int write_mncause(CPURISCVState *env, int csrno, target_ulong val) > +{ > + env->mncause = val; > + return RISCV_EXCP_NONE; > +} > + > +static int read_mnstatus(CPURISCVState *env, int csrno, target_ulong *val) > +{ > + *val = env->mnstatus; > + return RISCV_EXCP_NONE; > +} > + > +static int write_mnstatus(CPURISCVState *env, int csrno, target_ulong val) > +{ > + target_ulong mask = (MNSTATUS_NMIE | MNSTATUS_MNPP); > + > + if (riscv_has_ext(env, RVH)) { > + /* Flush tlb on mnstatus fields that affect VM. */ > + if ((val ^ env->mnstatus) & MNSTATUS_MNPV) { > + tlb_flush(env_cpu(env)); > + } > + > + mask |= MNSTATUS_MNPV; > + } > + > + /* mnstatus.mnie can only be cleared by hardware. */ > + env->mnstatus = (env->mnstatus & MNSTATUS_NMIE) | (val & mask); > + return RISCV_EXCP_NONE; > +} > + > /* Supervisor Trap Setup */ > static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno, > Int128 *val) > @@ -4204,6 +4276,16 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { > write_sstateen_1_3, > .min_priv_ver = PRIV_VERSION_1_12_0 }, > > + /* RNMI */ > + [CSR_MNSCRATCH] = { "mnscratch", rnmi, read_mnscratch, write_mnscratch, > + .min_priv_ver = PRIV_VERSION_1_12_0 }, > + [CSR_MNEPC] = { "mnepc", rnmi, read_mnepc, write_mnepc, > + .min_priv_ver = PRIV_VERSION_1_12_0 }, > + [CSR_MNCAUSE] = { "mncause", rnmi, read_mncause, write_mncause, > + .min_priv_ver = PRIV_VERSION_1_12_0 }, > + [CSR_MNSTATUS] = { "mnstatus", rnmi, read_mnstatus, write_mnstatus, > + .min_priv_ver = PRIV_VERSION_1_12_0 }, > + > /* Supervisor Trap Setup */ > [CSR_SSTATUS] = { "sstatus", smode, read_sstatus, write_sstatus, > NULL, read_sstatus_i128 },
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 39b74569b1..1b645c5485 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -810,6 +810,11 @@ static void riscv_cpu_reset_hold(Object *obj) riscv_trigger_init(env); } + if (cpu->cfg.ext_smrnmi) { + env->rnmip = 0; + env->mnstatus = set_field(env->mnstatus, MNSTATUS_NMIE, false); + } + if (kvm_enabled()) { kvm_riscv_reset_vcpu(cpu); } diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 6c14b93cb5..f44fd95f16 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -368,6 +368,10 @@ struct CPUArchState { uint64_t kvm_timer_frequency; /* RNMI */ + target_ulong mnscratch; + target_ulong mnepc; + target_ulong mncause; /* mncause without bit XLEN-1 set to 1 */ + target_ulong mnstatus; target_ulong rnmip; uint64_t rnmi_irqvec; uint64_t rnmi_excpvec; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 7cb43b88f3..d7bd4538ab 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -355,6 +355,12 @@ #define CSR_PMPADDR14 0x3be #define CSR_PMPADDR15 0x3bf +/* RNMI */ +#define CSR_MNSCRATCH 0x740 +#define CSR_MNEPC 0x741 +#define CSR_MNCAUSE 0x742 +#define CSR_MNSTATUS 0x744 + /* Debug/Trace Registers (shared with Debug Mode) */ #define CSR_TSELECT 0x7a0 #define CSR_TDATA1 0x7a1 @@ -624,6 +630,11 @@ typedef enum { #define SATP64_ASID 0x0FFFF00000000000ULL #define SATP64_PPN 0x00000FFFFFFFFFFFULL +/* RNMI mnstatus CSR mask */ +#define MNSTATUS_NMIE 0x00000008 +#define MNSTATUS_MNPV 0x00000080 +#define MNSTATUS_MNPP 0x00001800 + /* VM modes (satp.mode) privileged ISA 1.10 */ #define VM_1_10_MBARE 0 #define VM_1_10_SV32 1 diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 4451bd1263..a1d39fc116 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -536,6 +536,18 @@ static RISCVException debug(CPURISCVState *env, int csrno) return RISCV_EXCP_ILLEGAL_INST; } + +static RISCVException rnmi(CPURISCVState *env, int csrno) +{ + RISCVCPU *cpu = env_archcpu(env); + + if (cpu->cfg.ext_smrnmi) { + return RISCV_EXCP_NONE; + } + + return RISCV_EXCP_ILLEGAL_INST; +} + #endif static RISCVException seed(CPURISCVState *env, int csrno) @@ -2336,6 +2348,66 @@ static RISCVException rmw_miph(CPURISCVState *env, int csrno, return ret; } +static int read_mnscratch(CPURISCVState *env, int csrno, target_ulong *val) +{ + *val = env->mnscratch; + return RISCV_EXCP_NONE; +} + +static int write_mnscratch(CPURISCVState *env, int csrno, target_ulong val) +{ + env->mnscratch = val; + return RISCV_EXCP_NONE; +} + +static int read_mnepc(CPURISCVState *env, int csrno, target_ulong *val) +{ + *val = env->mnepc; + return RISCV_EXCP_NONE; +} + +static int write_mnepc(CPURISCVState *env, int csrno, target_ulong val) +{ + env->mnepc = val; + return RISCV_EXCP_NONE; +} + +static int read_mncause(CPURISCVState *env, int csrno, target_ulong *val) +{ + *val = env->mncause; + return RISCV_EXCP_NONE; +} + +static int write_mncause(CPURISCVState *env, int csrno, target_ulong val) +{ + env->mncause = val; + return RISCV_EXCP_NONE; +} + +static int read_mnstatus(CPURISCVState *env, int csrno, target_ulong *val) +{ + *val = env->mnstatus; + return RISCV_EXCP_NONE; +} + +static int write_mnstatus(CPURISCVState *env, int csrno, target_ulong val) +{ + target_ulong mask = (MNSTATUS_NMIE | MNSTATUS_MNPP); + + if (riscv_has_ext(env, RVH)) { + /* Flush tlb on mnstatus fields that affect VM. */ + if ((val ^ env->mnstatus) & MNSTATUS_MNPV) { + tlb_flush(env_cpu(env)); + } + + mask |= MNSTATUS_MNPV; + } + + /* mnstatus.mnie can only be cleared by hardware. */ + env->mnstatus = (env->mnstatus & MNSTATUS_NMIE) | (val & mask); + return RISCV_EXCP_NONE; +} + /* Supervisor Trap Setup */ static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno, Int128 *val) @@ -4204,6 +4276,16 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { write_sstateen_1_3, .min_priv_ver = PRIV_VERSION_1_12_0 }, + /* RNMI */ + [CSR_MNSCRATCH] = { "mnscratch", rnmi, read_mnscratch, write_mnscratch, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_MNEPC] = { "mnepc", rnmi, read_mnepc, write_mnepc, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_MNCAUSE] = { "mncause", rnmi, read_mncause, write_mncause, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_MNSTATUS] = { "mnstatus", rnmi, read_mnstatus, write_mnstatus, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + /* Supervisor Trap Setup */ [CSR_SSTATUS] = { "sstatus", smode, read_sstatus, write_sstatus, NULL, read_sstatus_i128 },