target/riscv: Add Ssdbltrp CSRs handling

Add ext_ssdbltrp in RISCVCPUConfig and implement MSTATUS.SDT,
{H|M}ENVCFG.DTE and modify the availability of MTVAL2 based on the
presence of the Ssdbltrp ISA extension.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20250110125441.3208676-3-cleger@rivosinc.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Clément Léger 2025-01-10 13:54:33 +01:00 committed by Alistair Francis
parent 507957eb2a
commit 0aadf8162a
5 changed files with 84 additions and 12 deletions

View file

@ -564,6 +564,7 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
int riscv_env_mmu_index(CPURISCVState *env, bool ifetch); int riscv_env_mmu_index(CPURISCVState *env, bool ifetch);
bool cpu_get_fcfien(CPURISCVState *env); bool cpu_get_fcfien(CPURISCVState *env);
bool cpu_get_bcfien(CPURISCVState *env); bool cpu_get_bcfien(CPURISCVState *env);
bool riscv_env_smode_dbltrp_enabled(CPURISCVState *env, bool virt);
G_NORETURN void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, G_NORETURN void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
MMUAccessType access_type, MMUAccessType access_type,
int mmu_idx, uintptr_t retaddr); int mmu_idx, uintptr_t retaddr);

View file

@ -555,6 +555,7 @@
#define MSTATUS_TW 0x00200000 /* since: priv-1.10 */ #define MSTATUS_TW 0x00200000 /* since: priv-1.10 */
#define MSTATUS_TSR 0x00400000 /* since: priv-1.10 */ #define MSTATUS_TSR 0x00400000 /* since: priv-1.10 */
#define MSTATUS_SPELP 0x00800000 /* zicfilp */ #define MSTATUS_SPELP 0x00800000 /* zicfilp */
#define MSTATUS_SDT 0x01000000
#define MSTATUS_MPELP 0x020000000000 /* zicfilp */ #define MSTATUS_MPELP 0x020000000000 /* zicfilp */
#define MSTATUS_GVA 0x4000000000ULL #define MSTATUS_GVA 0x4000000000ULL
#define MSTATUS_MPV 0x8000000000ULL #define MSTATUS_MPV 0x8000000000ULL
@ -587,6 +588,7 @@ typedef enum {
#define SSTATUS_SUM 0x00040000 /* since: priv-1.10 */ #define SSTATUS_SUM 0x00040000 /* since: priv-1.10 */
#define SSTATUS_MXR 0x00080000 #define SSTATUS_MXR 0x00080000
#define SSTATUS_SPELP MSTATUS_SPELP /* zicfilp */ #define SSTATUS_SPELP MSTATUS_SPELP /* zicfilp */
#define SSTATUS_SDT MSTATUS_SDT
#define SSTATUS64_UXL 0x0000000300000000ULL #define SSTATUS64_UXL 0x0000000300000000ULL
@ -782,12 +784,14 @@ typedef enum RISCVException {
#define MENVCFG_CBCFE BIT(6) #define MENVCFG_CBCFE BIT(6)
#define MENVCFG_CBZE BIT(7) #define MENVCFG_CBZE BIT(7)
#define MENVCFG_PMM (3ULL << 32) #define MENVCFG_PMM (3ULL << 32)
#define MENVCFG_DTE (1ULL << 59)
#define MENVCFG_CDE (1ULL << 60) #define MENVCFG_CDE (1ULL << 60)
#define MENVCFG_ADUE (1ULL << 61) #define MENVCFG_ADUE (1ULL << 61)
#define MENVCFG_PBMTE (1ULL << 62) #define MENVCFG_PBMTE (1ULL << 62)
#define MENVCFG_STCE (1ULL << 63) #define MENVCFG_STCE (1ULL << 63)
/* For RV32 */ /* For RV32 */
#define MENVCFGH_DTE BIT(27)
#define MENVCFGH_ADUE BIT(29) #define MENVCFGH_ADUE BIT(29)
#define MENVCFGH_PBMTE BIT(30) #define MENVCFGH_PBMTE BIT(30)
#define MENVCFGH_STCE BIT(31) #define MENVCFGH_STCE BIT(31)
@ -808,11 +812,13 @@ typedef enum RISCVException {
#define HENVCFG_CBCFE MENVCFG_CBCFE #define HENVCFG_CBCFE MENVCFG_CBCFE
#define HENVCFG_CBZE MENVCFG_CBZE #define HENVCFG_CBZE MENVCFG_CBZE
#define HENVCFG_PMM MENVCFG_PMM #define HENVCFG_PMM MENVCFG_PMM
#define HENVCFG_DTE MENVCFG_DTE
#define HENVCFG_ADUE MENVCFG_ADUE #define HENVCFG_ADUE MENVCFG_ADUE
#define HENVCFG_PBMTE MENVCFG_PBMTE #define HENVCFG_PBMTE MENVCFG_PBMTE
#define HENVCFG_STCE MENVCFG_STCE #define HENVCFG_STCE MENVCFG_STCE
/* For RV32 */ /* For RV32 */
#define HENVCFGH_DTE MENVCFGH_DTE
#define HENVCFGH_ADUE MENVCFGH_ADUE #define HENVCFGH_ADUE MENVCFGH_ADUE
#define HENVCFGH_PBMTE MENVCFGH_PBMTE #define HENVCFGH_PBMTE MENVCFGH_PBMTE
#define HENVCFGH_STCE MENVCFGH_STCE #define HENVCFGH_STCE MENVCFGH_STCE

View file

@ -83,6 +83,7 @@ struct RISCVCPUConfig {
bool ext_smcntrpmf; bool ext_smcntrpmf;
bool ext_smcsrind; bool ext_smcsrind;
bool ext_sscsrind; bool ext_sscsrind;
bool ext_ssdbltrp;
bool ext_svadu; bool ext_svadu;
bool ext_svinval; bool ext_svinval;
bool ext_svnapot; bool ext_svnapot;

View file

@ -120,6 +120,19 @@ bool cpu_get_bcfien(CPURISCVState *env)
} }
} }
bool riscv_env_smode_dbltrp_enabled(CPURISCVState *env, bool virt)
{
#ifdef CONFIG_USER_ONLY
return false;
#else
if (virt) {
return (env->henvcfg & HENVCFG_DTE) != 0;
} else {
return (env->menvcfg & MENVCFG_DTE) != 0;
}
#endif
}
void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc, void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
uint64_t *cs_base, uint32_t *pflags) uint64_t *cs_base, uint32_t *pflags)
{ {
@ -691,6 +704,10 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
g_assert(riscv_has_ext(env, RVH)); g_assert(riscv_has_ext(env, RVH));
if (riscv_env_smode_dbltrp_enabled(env, current_virt)) {
mstatus_mask |= MSTATUS_SDT;
}
if (current_virt) { if (current_virt) {
/* Current V=1 and we are about to change to V=0 */ /* Current V=1 and we are about to change to V=0 */
env->vsstatus = env->mstatus & mstatus_mask; env->vsstatus = env->mstatus & mstatus_mask;

View file

@ -680,6 +680,15 @@ static RISCVException aia_hmode32(CPURISCVState *env, int csrno)
return hmode32(env, csrno); return hmode32(env, csrno);
} }
static RISCVException dbltrp_hmode(CPURISCVState *env, int csrno)
{
if (riscv_cpu_cfg(env)->ext_ssdbltrp) {
return RISCV_EXCP_NONE;
}
return hmode(env, csrno);
}
static RISCVException pmp(CPURISCVState *env, int csrno) static RISCVException pmp(CPURISCVState *env, int csrno)
{ {
if (riscv_cpu_cfg(env)->pmp) { if (riscv_cpu_cfg(env)->pmp) {
@ -1938,6 +1947,13 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno,
mask |= MSTATUS_VS; mask |= MSTATUS_VS;
} }
if (riscv_env_smode_dbltrp_enabled(env, env->virt_enabled)) {
mask |= MSTATUS_SDT;
if ((val & MSTATUS_SDT) != 0) {
val &= ~MSTATUS_SIE;
}
}
if (xl != MXL_RV32 || env->debugger) { if (xl != MXL_RV32 || env->debugger) {
if (riscv_has_ext(env, RVH)) { if (riscv_has_ext(env, RVH)) {
mask |= MSTATUS_MPV | MSTATUS_GVA; mask |= MSTATUS_MPV | MSTATUS_GVA;
@ -2959,7 +2975,8 @@ static RISCVException write_menvcfg(CPURISCVState *env, int csrno,
mask |= (cfg->ext_svpbmt ? MENVCFG_PBMTE : 0) | mask |= (cfg->ext_svpbmt ? MENVCFG_PBMTE : 0) |
(cfg->ext_sstc ? MENVCFG_STCE : 0) | (cfg->ext_sstc ? MENVCFG_STCE : 0) |
(cfg->ext_smcdeleg ? MENVCFG_CDE : 0) | (cfg->ext_smcdeleg ? MENVCFG_CDE : 0) |
(cfg->ext_svadu ? MENVCFG_ADUE : 0); (cfg->ext_svadu ? MENVCFG_ADUE : 0) |
(cfg->ext_ssdbltrp ? MENVCFG_DTE : 0);
if (env_archcpu(env)->cfg.ext_zicfilp) { if (env_archcpu(env)->cfg.ext_zicfilp) {
mask |= MENVCFG_LPE; mask |= MENVCFG_LPE;
@ -2974,6 +2991,10 @@ static RISCVException write_menvcfg(CPURISCVState *env, int csrno,
get_field(val, MENVCFG_PMM) != PMM_FIELD_RESERVED) { get_field(val, MENVCFG_PMM) != PMM_FIELD_RESERVED) {
mask |= MENVCFG_PMM; mask |= MENVCFG_PMM;
} }
if ((val & MENVCFG_DTE) == 0) {
env->mstatus &= ~MSTATUS_SDT;
}
} }
env->menvcfg = (env->menvcfg & ~mask) | (val & mask); env->menvcfg = (env->menvcfg & ~mask) | (val & mask);
write_henvcfg(env, CSR_HENVCFG, env->henvcfg); write_henvcfg(env, CSR_HENVCFG, env->henvcfg);
@ -2997,9 +3018,14 @@ static RISCVException write_menvcfgh(CPURISCVState *env, int csrno,
uint64_t mask = (cfg->ext_svpbmt ? MENVCFG_PBMTE : 0) | uint64_t mask = (cfg->ext_svpbmt ? MENVCFG_PBMTE : 0) |
(cfg->ext_sstc ? MENVCFG_STCE : 0) | (cfg->ext_sstc ? MENVCFG_STCE : 0) |
(cfg->ext_svadu ? MENVCFG_ADUE : 0) | (cfg->ext_svadu ? MENVCFG_ADUE : 0) |
(cfg->ext_smcdeleg ? MENVCFG_CDE : 0); (cfg->ext_smcdeleg ? MENVCFG_CDE : 0) |
(cfg->ext_ssdbltrp ? MENVCFG_DTE : 0);
uint64_t valh = (uint64_t)val << 32; uint64_t valh = (uint64_t)val << 32;
if ((valh & MENVCFG_DTE) == 0) {
env->mstatus &= ~MSTATUS_SDT;
}
env->menvcfg = (env->menvcfg & ~mask) | (valh & mask); env->menvcfg = (env->menvcfg & ~mask) | (valh & mask);
write_henvcfgh(env, CSR_HENVCFGH, env->henvcfg >> 32); write_henvcfgh(env, CSR_HENVCFGH, env->henvcfg >> 32);
@ -3070,9 +3096,10 @@ static RISCVException read_henvcfg(CPURISCVState *env, int csrno,
* henvcfg.pbmte is read_only 0 when menvcfg.pbmte = 0 * henvcfg.pbmte is read_only 0 when menvcfg.pbmte = 0
* henvcfg.stce is read_only 0 when menvcfg.stce = 0 * henvcfg.stce is read_only 0 when menvcfg.stce = 0
* henvcfg.adue is read_only 0 when menvcfg.adue = 0 * henvcfg.adue is read_only 0 when menvcfg.adue = 0
* henvcfg.dte is read_only 0 when menvcfg.dte = 0
*/ */
*val = env->henvcfg & (~(HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_ADUE) | *val = env->henvcfg & (~(HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_ADUE |
env->menvcfg); HENVCFG_DTE) | env->menvcfg);
return RISCV_EXCP_NONE; return RISCV_EXCP_NONE;
} }
@ -3088,7 +3115,8 @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
} }
if (riscv_cpu_mxl(env) == MXL_RV64) { if (riscv_cpu_mxl(env) == MXL_RV64) {
mask |= env->menvcfg & (HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_ADUE); mask |= env->menvcfg & (HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_ADUE |
HENVCFG_DTE);
if (env_archcpu(env)->cfg.ext_zicfilp) { if (env_archcpu(env)->cfg.ext_zicfilp) {
mask |= HENVCFG_LPE; mask |= HENVCFG_LPE;
@ -3108,6 +3136,9 @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
} }
env->henvcfg = val & mask; env->henvcfg = val & mask;
if ((env->henvcfg & HENVCFG_DTE) == 0) {
env->vsstatus &= ~MSTATUS_SDT;
}
return RISCV_EXCP_NONE; return RISCV_EXCP_NONE;
} }
@ -3122,8 +3153,8 @@ static RISCVException read_henvcfgh(CPURISCVState *env, int csrno,
return ret; return ret;
} }
*val = (env->henvcfg & (~(HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_ADUE) | *val = (env->henvcfg & (~(HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_ADUE |
env->menvcfg)) >> 32; HENVCFG_DTE) | env->menvcfg)) >> 32;
return RISCV_EXCP_NONE; return RISCV_EXCP_NONE;
} }
@ -3131,7 +3162,7 @@ static RISCVException write_henvcfgh(CPURISCVState *env, int csrno,
target_ulong val) target_ulong val)
{ {
uint64_t mask = env->menvcfg & (HENVCFG_PBMTE | HENVCFG_STCE | uint64_t mask = env->menvcfg & (HENVCFG_PBMTE | HENVCFG_STCE |
HENVCFG_ADUE); HENVCFG_ADUE | HENVCFG_DTE);
uint64_t valh = (uint64_t)val << 32; uint64_t valh = (uint64_t)val << 32;
RISCVException ret; RISCVException ret;
@ -3139,8 +3170,10 @@ static RISCVException write_henvcfgh(CPURISCVState *env, int csrno,
if (ret != RISCV_EXCP_NONE) { if (ret != RISCV_EXCP_NONE) {
return ret; return ret;
} }
env->henvcfg = (env->henvcfg & 0xFFFFFFFF) | (valh & mask); env->henvcfg = (env->henvcfg & 0xFFFFFFFF) | (valh & mask);
if ((env->henvcfg & HENVCFG_DTE) == 0) {
env->vsstatus &= ~MSTATUS_SDT;
}
return RISCV_EXCP_NONE; return RISCV_EXCP_NONE;
} }
@ -3594,6 +3627,9 @@ static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno,
if (env->xl != MXL_RV32 || env->debugger) { if (env->xl != MXL_RV32 || env->debugger) {
mask |= SSTATUS64_UXL; mask |= SSTATUS64_UXL;
} }
if (riscv_cpu_cfg(env)->ext_ssdbltrp) {
mask |= SSTATUS_SDT;
}
if (env_archcpu(env)->cfg.ext_zicfilp) { if (env_archcpu(env)->cfg.ext_zicfilp) {
mask |= SSTATUS_SPELP; mask |= SSTATUS_SPELP;
@ -3614,7 +3650,9 @@ static RISCVException read_sstatus(CPURISCVState *env, int csrno,
if (env_archcpu(env)->cfg.ext_zicfilp) { if (env_archcpu(env)->cfg.ext_zicfilp) {
mask |= SSTATUS_SPELP; mask |= SSTATUS_SPELP;
} }
if (riscv_cpu_cfg(env)->ext_ssdbltrp) {
mask |= SSTATUS_SDT;
}
/* TODO: Use SXL not MXL. */ /* TODO: Use SXL not MXL. */
*val = add_status_sd(riscv_cpu_mxl(env), env->mstatus & mask); *val = add_status_sd(riscv_cpu_mxl(env), env->mstatus & mask);
return RISCV_EXCP_NONE; return RISCV_EXCP_NONE;
@ -3634,7 +3672,9 @@ static RISCVException write_sstatus(CPURISCVState *env, int csrno,
if (env_archcpu(env)->cfg.ext_zicfilp) { if (env_archcpu(env)->cfg.ext_zicfilp) {
mask |= SSTATUS_SPELP; mask |= SSTATUS_SPELP;
} }
if (riscv_cpu_cfg(env)->ext_ssdbltrp) {
mask |= SSTATUS_SDT;
}
target_ulong newval = (env->mstatus & ~mask) | (val & mask); target_ulong newval = (env->mstatus & ~mask) | (val & mask);
return write_mstatus(env, CSR_MSTATUS, newval); return write_mstatus(env, CSR_MSTATUS, newval);
} }
@ -4751,6 +4791,13 @@ static RISCVException write_vsstatus(CPURISCVState *env, int csrno,
if ((val & VSSTATUS64_UXL) == 0) { if ((val & VSSTATUS64_UXL) == 0) {
mask &= ~VSSTATUS64_UXL; mask &= ~VSSTATUS64_UXL;
} }
if ((env->henvcfg & HENVCFG_DTE)) {
if ((val & SSTATUS_SDT) != 0) {
val &= ~SSTATUS_SIE;
}
} else {
val &= ~SSTATUS_SDT;
}
env->vsstatus = (env->vsstatus & ~mask) | (uint64_t)val; env->vsstatus = (env->vsstatus & ~mask) | (uint64_t)val;
return RISCV_EXCP_NONE; return RISCV_EXCP_NONE;
} }
@ -5698,7 +5745,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
[CSR_VSATP] = { "vsatp", hmode, read_vsatp, write_vsatp, [CSR_VSATP] = { "vsatp", hmode, read_vsatp, write_vsatp,
.min_priv_ver = PRIV_VERSION_1_12_0 }, .min_priv_ver = PRIV_VERSION_1_12_0 },
[CSR_MTVAL2] = { "mtval2", hmode, read_mtval2, write_mtval2, [CSR_MTVAL2] = { "mtval2", dbltrp_hmode, read_mtval2, write_mtval2,
.min_priv_ver = PRIV_VERSION_1_12_0 }, .min_priv_ver = PRIV_VERSION_1_12_0 },
[CSR_MTINST] = { "mtinst", hmode, read_mtinst, write_mtinst, [CSR_MTINST] = { "mtinst", hmode, read_mtinst, write_mtinst,
.min_priv_ver = PRIV_VERSION_1_12_0 }, .min_priv_ver = PRIV_VERSION_1_12_0 },