Merge patch series "target/riscv: Add support for Svadu extension"
Weiwei Li <liweiwei@iscas.ac.cn> says: This patchset adds support svadu extension. It also fixes some relationship between *envcfg fields and Svpbmt/Sstc extensions. Specification for Svadu extension can be found in: https://github.com/riscv/riscv-svadu * b4-shazam-merge: target/riscv: Export Svadu property target/riscv: Add *envcfg.HADE related check in address translation target/riscv: Add *envcfg.PBMTE related check in address translation target/riscv: Add csr support for svadu target/riscv: Fix the relationship of PBMTE/STCE fields between menvcfg and henvcfg target/riscv: Fix the relationship between menvcfg.PBMTE/STCE and Svpbmt/Sstc extensions Message-ID: <20230224040852.37109-1-liweiwei@iscas.ac.cn> Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
commit
8e5aded3de
@ -111,6 +111,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
|
||||
ISA_EXT_DATA_ENTRY(ssaia, true, PRIV_VERSION_1_12_0, ext_ssaia),
|
||||
ISA_EXT_DATA_ENTRY(sscofpmf, true, PRIV_VERSION_1_12_0, ext_sscofpmf),
|
||||
ISA_EXT_DATA_ENTRY(sstc, true, PRIV_VERSION_1_12_0, ext_sstc),
|
||||
ISA_EXT_DATA_ENTRY(svadu, true, PRIV_VERSION_1_12_0, ext_svadu),
|
||||
ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval),
|
||||
ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot),
|
||||
ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt),
|
||||
@ -617,6 +618,11 @@ static void riscv_cpu_reset_hold(Object *obj)
|
||||
env->bins = 0;
|
||||
env->two_stage_lookup = false;
|
||||
|
||||
env->menvcfg = (cpu->cfg.ext_svpbmt ? MENVCFG_PBMTE : 0) |
|
||||
(cpu->cfg.ext_svadu ? MENVCFG_HADE : 0);
|
||||
env->henvcfg = (cpu->cfg.ext_svpbmt ? HENVCFG_PBMTE : 0) |
|
||||
(cpu->cfg.ext_svadu ? HENVCFG_HADE : 0);
|
||||
|
||||
/* Initialized default priorities of local interrupts. */
|
||||
for (i = 0; i < ARRAY_SIZE(env->miprio); i++) {
|
||||
iprio = riscv_cpu_default_priority(i);
|
||||
@ -1129,6 +1135,8 @@ static Property riscv_cpu_extensions[] = {
|
||||
DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
|
||||
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
|
||||
|
||||
DEFINE_PROP_BOOL("svadu", RISCVCPU, cfg.ext_svadu, true),
|
||||
|
||||
DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
|
||||
DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
|
||||
DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
|
||||
|
@ -438,6 +438,7 @@ struct RISCVCPUConfig {
|
||||
bool ext_zihintpause;
|
||||
bool ext_smstateen;
|
||||
bool ext_sstc;
|
||||
bool ext_svadu;
|
||||
bool ext_svinval;
|
||||
bool ext_svnapot;
|
||||
bool ext_svpbmt;
|
||||
|
@ -747,10 +747,12 @@ typedef enum RISCVException {
|
||||
#define MENVCFG_CBIE (3UL << 4)
|
||||
#define MENVCFG_CBCFE BIT(6)
|
||||
#define MENVCFG_CBZE BIT(7)
|
||||
#define MENVCFG_HADE (1ULL << 61)
|
||||
#define MENVCFG_PBMTE (1ULL << 62)
|
||||
#define MENVCFG_STCE (1ULL << 63)
|
||||
|
||||
/* For RV32 */
|
||||
#define MENVCFGH_HADE BIT(29)
|
||||
#define MENVCFGH_PBMTE BIT(30)
|
||||
#define MENVCFGH_STCE BIT(31)
|
||||
|
||||
@ -763,10 +765,12 @@ typedef enum RISCVException {
|
||||
#define HENVCFG_CBIE MENVCFG_CBIE
|
||||
#define HENVCFG_CBCFE MENVCFG_CBCFE
|
||||
#define HENVCFG_CBZE MENVCFG_CBZE
|
||||
#define HENVCFG_HADE MENVCFG_HADE
|
||||
#define HENVCFG_PBMTE MENVCFG_PBMTE
|
||||
#define HENVCFG_STCE MENVCFG_STCE
|
||||
|
||||
/* For RV32 */
|
||||
#define HENVCFGH_HADE MENVCFGH_HADE
|
||||
#define HENVCFGH_PBMTE MENVCFGH_PBMTE
|
||||
#define HENVCFGH_STCE MENVCFGH_STCE
|
||||
|
||||
|
@ -936,9 +936,17 @@ restart:
|
||||
return TRANSLATE_FAIL;
|
||||
}
|
||||
|
||||
bool pbmte = env->menvcfg & MENVCFG_PBMTE;
|
||||
bool hade = env->menvcfg & MENVCFG_HADE;
|
||||
|
||||
if (first_stage && two_stage && riscv_cpu_virt_enabled(env)) {
|
||||
pbmte = pbmte && (env->henvcfg & HENVCFG_PBMTE);
|
||||
hade = hade && (env->henvcfg & HENVCFG_HADE);
|
||||
}
|
||||
|
||||
if (riscv_cpu_sxl(env) == MXL_RV32) {
|
||||
ppn = pte >> PTE_PPN_SHIFT;
|
||||
} else if (cpu->cfg.ext_svpbmt || cpu->cfg.ext_svnapot) {
|
||||
} else if (pbmte || cpu->cfg.ext_svnapot) {
|
||||
ppn = (pte & (target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT;
|
||||
} else {
|
||||
ppn = pte >> PTE_PPN_SHIFT;
|
||||
@ -950,7 +958,7 @@ restart:
|
||||
if (!(pte & PTE_V)) {
|
||||
/* Invalid PTE */
|
||||
return TRANSLATE_FAIL;
|
||||
} else if (!cpu->cfg.ext_svpbmt && (pte & PTE_PBMT)) {
|
||||
} else if (!pbmte && (pte & PTE_PBMT)) {
|
||||
return TRANSLATE_FAIL;
|
||||
} else if (!(pte & (PTE_R | PTE_W | PTE_X))) {
|
||||
/* Inner PTE, continue walking */
|
||||
@ -992,6 +1000,10 @@ restart:
|
||||
|
||||
/* Page table updates need to be atomic with MTTCG enabled */
|
||||
if (updated_pte != pte) {
|
||||
if (!hade) {
|
||||
return TRANSLATE_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* - if accessed or dirty bits need updating, and the PTE is
|
||||
* in RAM, then we do so atomically with a compare and swap.
|
||||
|
@ -1879,10 +1879,13 @@ static RISCVException read_menvcfg(CPURISCVState *env, int csrno,
|
||||
static RISCVException write_menvcfg(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
{
|
||||
RISCVCPUConfig *cfg = &env_archcpu(env)->cfg;
|
||||
uint64_t mask = MENVCFG_FIOM | MENVCFG_CBIE | MENVCFG_CBCFE | MENVCFG_CBZE;
|
||||
|
||||
if (riscv_cpu_mxl(env) == MXL_RV64) {
|
||||
mask |= MENVCFG_PBMTE | MENVCFG_STCE;
|
||||
mask |= (cfg->ext_svpbmt ? MENVCFG_PBMTE : 0) |
|
||||
(cfg->ext_sstc ? MENVCFG_STCE : 0) |
|
||||
(cfg->ext_svadu ? MENVCFG_HADE : 0);
|
||||
}
|
||||
env->menvcfg = (env->menvcfg & ~mask) | (val & mask);
|
||||
|
||||
@ -1899,7 +1902,10 @@ static RISCVException read_menvcfgh(CPURISCVState *env, int csrno,
|
||||
static RISCVException write_menvcfgh(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
{
|
||||
uint64_t mask = MENVCFG_PBMTE | MENVCFG_STCE;
|
||||
RISCVCPUConfig *cfg = &env_archcpu(env)->cfg;
|
||||
uint64_t mask = (cfg->ext_svpbmt ? MENVCFG_PBMTE : 0) |
|
||||
(cfg->ext_sstc ? MENVCFG_STCE : 0) |
|
||||
(cfg->ext_svadu ? MENVCFG_HADE : 0);
|
||||
uint64_t valh = (uint64_t)val << 32;
|
||||
|
||||
env->menvcfg = (env->menvcfg & ~mask) | (valh & mask);
|
||||
@ -1979,7 +1985,13 @@ static RISCVException read_henvcfg(CPURISCVState *env, int csrno,
|
||||
return ret;
|
||||
}
|
||||
|
||||
*val = env->henvcfg;
|
||||
/*
|
||||
* henvcfg.pbmte is read_only 0 when menvcfg.pbmte = 0
|
||||
* henvcfg.stce is read_only 0 when menvcfg.stce = 0
|
||||
* henvcfg.hade is read_only 0 when menvcfg.hade = 0
|
||||
*/
|
||||
*val = env->henvcfg & (~(HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_HADE) |
|
||||
env->menvcfg);
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
@ -1995,7 +2007,7 @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
if (riscv_cpu_mxl(env) == MXL_RV64) {
|
||||
mask |= HENVCFG_PBMTE | HENVCFG_STCE;
|
||||
mask |= env->menvcfg & (HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_HADE);
|
||||
}
|
||||
|
||||
env->henvcfg = (env->henvcfg & ~mask) | (val & mask);
|
||||
@ -2013,14 +2025,16 @@ static RISCVException read_henvcfgh(CPURISCVState *env, int csrno,
|
||||
return ret;
|
||||
}
|
||||
|
||||
*val = env->henvcfg >> 32;
|
||||
*val = (env->henvcfg & (~(HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_HADE) |
|
||||
env->menvcfg)) >> 32;
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException write_henvcfgh(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
{
|
||||
uint64_t mask = HENVCFG_PBMTE | HENVCFG_STCE;
|
||||
uint64_t mask = env->menvcfg & (HENVCFG_PBMTE | HENVCFG_STCE |
|
||||
HENVCFG_HADE);
|
||||
uint64_t valh = (uint64_t)val << 32;
|
||||
RISCVException ret;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user