diff options
author | Tommy Wu <tommy.wu@sifive.com> | 2025-01-06 13:43:32 +0800 |
---|---|---|
committer | Alistair Francis <alistair.francis@wdc.com> | 2025-01-19 09:44:34 +1000 |
commit | 5db557f82bff480437275d4cc9e0b5463bc04484 (patch) | |
tree | 9354a3dd1e1a11caa88a305e874620fed219c144 | |
parent | 36de64b74cc56e95b082e2e26522a22ec75a7c8d (diff) | |
download | qemu-5db557f82bff480437275d4cc9e0b5463bc04484.zip qemu-5db557f82bff480437275d4cc9e0b5463bc04484.tar.gz qemu-5db557f82bff480437275d4cc9e0b5463bc04484.tar.bz2 |
target/riscv: Add Smrnmi CSRs
The Smrnmi extension adds the 'mnscratch', 'mnepc', 'mncause',
'mnstatus' CSRs.
Signed-off-by: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20250106054336.1878291-3-frank.chang@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
-rw-r--r-- | target/riscv/cpu.c | 5 | ||||
-rw-r--r-- | target/riscv/cpu.h | 7 | ||||
-rw-r--r-- | target/riscv/cpu_bits.h | 11 | ||||
-rw-r--r-- | target/riscv/csr.c | 82 |
4 files changed, 105 insertions, 0 deletions
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index d9eb2c0..66193cd 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1127,6 +1127,11 @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type) riscv_trigger_reset_hold(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 5e71522..5eaf9da 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -480,6 +480,13 @@ struct CPUArchState { uint64_t kvm_timer_state; uint64_t kvm_timer_frequency; #endif /* CONFIG_KVM */ + + /* RNMI */ + target_ulong mnscratch; + target_ulong mnepc; + target_ulong mncause; /* mncause without bit XLEN-1 set to 1 */ + target_ulong mnstatus; + target_ulong rnmip; }; /* diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 797dd69..ba6fc54 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -353,6 +353,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 @@ -604,6 +610,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 6b8cef5..af97667 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -590,6 +590,17 @@ 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) @@ -4376,6 +4387,67 @@ static RISCVException write_mcontext(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +static RISCVException 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; +} + #endif /* Crypto Extension */ @@ -4883,6 +4955,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 }, |