target/riscv: Add Hypervisor CSR access functions

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>
Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
This commit is contained in:
Alistair Francis 2020-01-31 17:02:04 -08:00 committed by Palmer Dabbelt
parent df30e652d4
commit ff2cc1294c
No known key found for this signature in database
GPG Key ID: 2E1319F35FBB1889
1 changed files with 134 additions and 2 deletions

View File

@ -98,6 +98,20 @@ static int smode(CPURISCVState *env, int csrno)
return -!riscv_has_ext(env, RVS);
}
static int hmode(CPURISCVState *env, int csrno)
{
if (riscv_has_ext(env, RVS) &&
riscv_has_ext(env, RVH)) {
/* Hypervisor extension is supported */
if ((env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
env->priv == PRV_M) {
return 0;
}
}
return -1;
}
static int pmp(CPURISCVState *env, int csrno)
{
return -!riscv_feature(env, RISCV_FEATURE_PMP);
@ -226,8 +240,9 @@ static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val)
/* Machine constants */
#define M_MODE_INTERRUPTS (MIP_MSIP | MIP_MTIP | MIP_MEIP)
#define S_MODE_INTERRUPTS (MIP_SSIP | MIP_STIP | MIP_SEIP)
#define M_MODE_INTERRUPTS (MIP_MSIP | MIP_MTIP | MIP_MEIP)
#define S_MODE_INTERRUPTS (MIP_SSIP | MIP_STIP | MIP_SEIP)
#define VS_MODE_INTERRUPTS (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)
static const target_ulong delegable_ints = S_MODE_INTERRUPTS;
static const target_ulong all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS;
@ -257,6 +272,7 @@ static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD;
static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
static const target_ulong hip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP;
#if defined(TARGET_RISCV32)
static const char valid_vm_1_09[16] = {
@ -756,6 +772,112 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
return 0;
}
/* Hypervisor Extensions */
static int read_hstatus(CPURISCVState *env, int csrno, target_ulong *val)
{
*val = env->hstatus;
return 0;
}
static int write_hstatus(CPURISCVState *env, int csrno, target_ulong val)
{
env->hstatus = val;
return 0;
}
static int read_hedeleg(CPURISCVState *env, int csrno, target_ulong *val)
{
*val = env->hedeleg;
return 0;
}
static int write_hedeleg(CPURISCVState *env, int csrno, target_ulong val)
{
env->hedeleg = val;
return 0;
}
static int read_hideleg(CPURISCVState *env, int csrno, target_ulong *val)
{
*val = env->hideleg;
return 0;
}
static int write_hideleg(CPURISCVState *env, int csrno, target_ulong val)
{
env->hideleg = val;
return 0;
}
static int rmw_hip(CPURISCVState *env, int csrno, target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask)
{
int ret = rmw_mip(env, 0, ret_value, new_value,
write_mask & hip_writable_mask);
return ret;
}
static int read_hie(CPURISCVState *env, int csrno, target_ulong *val)
{
*val = env->mie & VS_MODE_INTERRUPTS;
return 0;
}
static int write_hie(CPURISCVState *env, int csrno, target_ulong val)
{
target_ulong newval = (env->mie & ~VS_MODE_INTERRUPTS) | (val & VS_MODE_INTERRUPTS);
return write_mie(env, CSR_MIE, newval);
}
static int read_hcounteren(CPURISCVState *env, int csrno, target_ulong *val)
{
*val = env->hcounteren;
return 0;
}
static int write_hcounteren(CPURISCVState *env, int csrno, target_ulong val)
{
env->hcounteren = val;
return 0;
}
static int read_htval(CPURISCVState *env, int csrno, target_ulong *val)
{
*val = env->htval;
return 0;
}
static int write_htval(CPURISCVState *env, int csrno, target_ulong val)
{
env->htval = val;
return 0;
}
static int read_htinst(CPURISCVState *env, int csrno, target_ulong *val)
{
*val = env->htinst;
return 0;
}
static int write_htinst(CPURISCVState *env, int csrno, target_ulong val)
{
env->htinst = val;
return 0;
}
static int read_hgatp(CPURISCVState *env, int csrno, target_ulong *val)
{
*val = env->hgatp;
return 0;
}
static int write_hgatp(CPURISCVState *env, int csrno, target_ulong val)
{
env->hgatp = val;
return 0;
}
/* Physical Memory Protection */
static int read_pmpcfg(CPURISCVState *env, int csrno, target_ulong *val)
{
@ -959,6 +1081,16 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
/* Supervisor Protection and Translation */
[CSR_SATP] = { smode, read_satp, write_satp },
[CSR_HSTATUS] = { hmode, read_hstatus, write_hstatus },
[CSR_HEDELEG] = { hmode, read_hedeleg, write_hedeleg },
[CSR_HIDELEG] = { hmode, read_hideleg, write_hideleg },
[CSR_HIP] = { hmode, NULL, NULL, rmw_hip },
[CSR_HIE] = { hmode, read_hie, write_hie },
[CSR_HCOUNTEREN] = { hmode, read_hcounteren, write_hcounteren },
[CSR_HTVAL] = { hmode, read_htval, write_htval },
[CSR_HTINST] = { hmode, read_htinst, write_htinst },
[CSR_HGATP] = { hmode, read_hgatp, write_hgatp },
/* Physical Memory Protection */
[CSR_PMPCFG0 ... CSR_PMPADDR9] = { pmp, read_pmpcfg, write_pmpcfg },
[CSR_PMPADDR0 ... CSR_PMPADDR15] = { pmp, read_pmpaddr, write_pmpaddr },