target/riscv: Add *envcfg* CSRs support

The RISC-V privileged specification v1.12 defines few execution
environment configuration CSRs that can be used enable/disable
extensions per privilege levels.

Add the basic support for these CSRs.

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Atish Patra <atishp@rivosinc.com>
Message-Id: <20220303185440.512391-6-atishp@rivosinc.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Atish Patra 2022-03-03 10:54:39 -08:00 committed by Alistair Francis
parent 3e6a417c8a
commit 29a9ec9bd8
4 changed files with 174 additions and 0 deletions

View File

@ -304,6 +304,11 @@ struct CPUArchState {
target_ulong spmbase;
target_ulong upmmask;
target_ulong upmbase;
/* CSRs for execution enviornment configuration */
uint64_t menvcfg;
target_ulong senvcfg;
uint64_t henvcfg;
#endif
target_ulong cur_pmmask;
target_ulong cur_pmbase;

View File

@ -202,6 +202,9 @@
#define CSR_STVEC 0x105
#define CSR_SCOUNTEREN 0x106
/* Supervisor Configuration CSRs */
#define CSR_SENVCFG 0x10A
/* Supervisor Trap Handling */
#define CSR_SSCRATCH 0x140
#define CSR_SEPC 0x141
@ -247,6 +250,10 @@
#define CSR_HTIMEDELTA 0x605
#define CSR_HTIMEDELTAH 0x615
/* Hypervisor Configuration CSRs */
#define CSR_HENVCFG 0x60A
#define CSR_HENVCFGH 0x61A
/* Virtual CSRs */
#define CSR_VSSTATUS 0x200
#define CSR_VSIE 0x204
@ -290,6 +297,10 @@
#define CSR_VSIEH 0x214
#define CSR_VSIPH 0x254
/* Machine Configuration CSRs */
#define CSR_MENVCFG 0x30A
#define CSR_MENVCFGH 0x31A
/* Enhanced Physical Memory Protection (ePMP) */
#define CSR_MSECCFG 0x747
#define CSR_MSECCFGH 0x757
@ -663,6 +674,34 @@ typedef enum RISCVException {
#define PM_EXT_CLEAN 0x00000002ULL
#define PM_EXT_DIRTY 0x00000003ULL
/* Execution enviornment configuration bits */
#define MENVCFG_FIOM BIT(0)
#define MENVCFG_CBIE (3UL << 4)
#define MENVCFG_CBCFE BIT(6)
#define MENVCFG_CBZE BIT(7)
#define MENVCFG_PBMTE (1ULL << 62)
#define MENVCFG_STCE (1ULL << 63)
/* For RV32 */
#define MENVCFGH_PBMTE BIT(30)
#define MENVCFGH_STCE BIT(31)
#define SENVCFG_FIOM MENVCFG_FIOM
#define SENVCFG_CBIE MENVCFG_CBIE
#define SENVCFG_CBCFE MENVCFG_CBCFE
#define SENVCFG_CBZE MENVCFG_CBZE
#define HENVCFG_FIOM MENVCFG_FIOM
#define HENVCFG_CBIE MENVCFG_CBIE
#define HENVCFG_CBCFE MENVCFG_CBCFE
#define HENVCFG_CBZE MENVCFG_CBZE
#define HENVCFG_PBMTE MENVCFG_PBMTE
#define HENVCFG_STCE MENVCFG_STCE
/* For RV32 */
#define HENVCFGH_PBMTE MENVCFGH_PBMTE
#define HENVCFGH_STCE MENVCFGH_STCE
/* Offsets for every pair of control bits per each priv level */
#define XS_OFFSET 0ULL
#define U_OFFSET 2ULL

View File

@ -1398,6 +1398,101 @@ static RISCVException write_mtval(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
/* Execution environment configuration setup */
static RISCVException read_menvcfg(CPURISCVState *env, int csrno,
target_ulong *val)
{
*val = env->menvcfg;
return RISCV_EXCP_NONE;
}
static RISCVException write_menvcfg(CPURISCVState *env, int csrno,
target_ulong val)
{
uint64_t mask = MENVCFG_FIOM | MENVCFG_CBIE | MENVCFG_CBCFE | MENVCFG_CBZE;
if (riscv_cpu_mxl(env) == MXL_RV64) {
mask |= MENVCFG_PBMTE | MENVCFG_STCE;
}
env->menvcfg = (env->menvcfg & ~mask) | (val & mask);
return RISCV_EXCP_NONE;
}
static RISCVException read_menvcfgh(CPURISCVState *env, int csrno,
target_ulong *val)
{
*val = env->menvcfg >> 32;
return RISCV_EXCP_NONE;
}
static RISCVException write_menvcfgh(CPURISCVState *env, int csrno,
target_ulong val)
{
uint64_t mask = MENVCFG_PBMTE | MENVCFG_STCE;
uint64_t valh = (uint64_t)val << 32;
env->menvcfg = (env->menvcfg & ~mask) | (valh & mask);
return RISCV_EXCP_NONE;
}
static RISCVException read_senvcfg(CPURISCVState *env, int csrno,
target_ulong *val)
{
*val = env->senvcfg;
return RISCV_EXCP_NONE;
}
static RISCVException write_senvcfg(CPURISCVState *env, int csrno,
target_ulong val)
{
uint64_t mask = SENVCFG_FIOM | SENVCFG_CBIE | SENVCFG_CBCFE | SENVCFG_CBZE;
env->senvcfg = (env->senvcfg & ~mask) | (val & mask);
return RISCV_EXCP_NONE;
}
static RISCVException read_henvcfg(CPURISCVState *env, int csrno,
target_ulong *val)
{
*val = env->henvcfg;
return RISCV_EXCP_NONE;
}
static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
target_ulong val)
{
uint64_t mask = HENVCFG_FIOM | HENVCFG_CBIE | HENVCFG_CBCFE | HENVCFG_CBZE;
if (riscv_cpu_mxl(env) == MXL_RV64) {
mask |= HENVCFG_PBMTE | HENVCFG_STCE;
}
env->henvcfg = (env->henvcfg & ~mask) | (val & mask);
return RISCV_EXCP_NONE;
}
static RISCVException read_henvcfgh(CPURISCVState *env, int csrno,
target_ulong *val)
{
*val = env->henvcfg >> 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 valh = (uint64_t)val << 32;
env->henvcfg = (env->henvcfg & ~mask) | (valh & mask);
return RISCV_EXCP_NONE;
}
static RISCVException rmw_mip64(CPURISCVState *env, int csrno,
uint64_t *ret_val,
uint64_t new_val, uint64_t wr_mask)
@ -3158,6 +3253,18 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
[CSR_MVIPH] = { "mviph", aia_any32, read_zero, write_ignore },
[CSR_MIPH] = { "miph", aia_any32, NULL, NULL, rmw_miph },
/* Execution environment configuration */
[CSR_MENVCFG] = { "menvcfg", any, read_menvcfg, write_menvcfg,
.min_priv_ver = PRIV_VERSION_1_12_0 },
[CSR_MENVCFGH] = { "menvcfgh", any32, read_menvcfgh, write_menvcfgh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
[CSR_SENVCFG] = { "senvcfg", smode, read_senvcfg, write_senvcfg,
.min_priv_ver = PRIV_VERSION_1_12_0 },
[CSR_HENVCFG] = { "henvcfg", hmode, read_henvcfg, write_henvcfg,
.min_priv_ver = PRIV_VERSION_1_12_0 },
[CSR_HENVCFGH] = { "henvcfgh", hmode32, read_henvcfgh, write_henvcfgh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
/* Supervisor Trap Setup */
[CSR_SSTATUS] = { "sstatus", smode, read_sstatus, write_sstatus, NULL,
read_sstatus_i128 },

View File

@ -231,6 +231,28 @@ static int riscv_cpu_post_load(void *opaque, int version_id)
return 0;
}
static bool envcfg_needed(void *opaque)
{
RISCVCPU *cpu = opaque;
CPURISCVState *env = &cpu->env;
return (env->priv_ver >= PRIV_VERSION_1_12_0 ? 1 : 0);
}
static const VMStateDescription vmstate_envcfg = {
.name = "cpu/envcfg",
.version_id = 1,
.minimum_version_id = 1,
.needed = envcfg_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT64(env.menvcfg, RISCVCPU),
VMSTATE_UINTTL(env.senvcfg, RISCVCPU),
VMSTATE_UINT64(env.henvcfg, RISCVCPU),
VMSTATE_END_OF_LIST()
}
};
const VMStateDescription vmstate_riscv_cpu = {
.name = "cpu",
.version_id = 3,
@ -292,6 +314,7 @@ const VMStateDescription vmstate_riscv_cpu = {
&vmstate_pointermasking,
&vmstate_rv128,
&vmstate_kvmtimer,
&vmstate_envcfg,
NULL
}
};