target/riscv: Drop support for ISA spec version 1.09.1
The RISC-V ISA spec version 1.09.1 has been deprecated in QEMU since 4.1. It's not commonly used so let's remove support for it. Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Bin Meng <bin.meng@windriver.com>
This commit is contained in:
parent
65a117da6e
commit
1a9540d1f1
@ -301,16 +301,6 @@ The ``acl_show``, ``acl_reset``, ``acl_policy``, ``acl_add``, and
|
|||||||
``acl_remove`` commands are deprecated with no replacement. Authorization
|
``acl_remove`` commands are deprecated with no replacement. Authorization
|
||||||
for VNC should be performed using the pluggable QAuthZ objects.
|
for VNC should be performed using the pluggable QAuthZ objects.
|
||||||
|
|
||||||
Guest Emulator ISAs
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
RISC-V ISA privledge specification version 1.09.1 (since 4.1)
|
|
||||||
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
|
||||||
|
|
||||||
The RISC-V ISA privledge specification version 1.09.1 has been deprecated.
|
|
||||||
QEMU supports both the newer version 1.10.0 and the ratified version 1.11.0, these
|
|
||||||
should be used instead of the 1.09.1 version.
|
|
||||||
|
|
||||||
System emulator CPUS
|
System emulator CPUS
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
@ -471,6 +461,16 @@ The ``hub_id`` parameter of ``hostfwd_add`` / ``hostfwd_remove`` (removed in 5.0
|
|||||||
The ``[hub_id name]`` parameter tuple of the 'hostfwd_add' and
|
The ``[hub_id name]`` parameter tuple of the 'hostfwd_add' and
|
||||||
'hostfwd_remove' HMP commands has been replaced by ``netdev_id``.
|
'hostfwd_remove' HMP commands has been replaced by ``netdev_id``.
|
||||||
|
|
||||||
|
Guest Emulator ISAs
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
RISC-V ISA privledge specification version 1.09.1 (removed in 5.1)
|
||||||
|
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||||
|
|
||||||
|
The RISC-V ISA privledge specification version 1.09.1 has been removed.
|
||||||
|
QEMU supports both the newer version 1.10.0 and the ratified version 1.11.0, these
|
||||||
|
should be used instead of the 1.09.1 version.
|
||||||
|
|
||||||
System emulator CPUS
|
System emulator CPUS
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
@ -368,8 +368,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
|
|||||||
priv_version = PRIV_VERSION_1_11_0;
|
priv_version = PRIV_VERSION_1_11_0;
|
||||||
} else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) {
|
} else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) {
|
||||||
priv_version = PRIV_VERSION_1_10_0;
|
priv_version = PRIV_VERSION_1_10_0;
|
||||||
} else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.9.1")) {
|
|
||||||
priv_version = PRIV_VERSION_1_09_1;
|
|
||||||
} else {
|
} else {
|
||||||
error_setg(errp,
|
error_setg(errp,
|
||||||
"Unsupported privilege spec version '%s'",
|
"Unsupported privilege spec version '%s'",
|
||||||
|
@ -73,7 +73,6 @@ enum {
|
|||||||
RISCV_FEATURE_MISA
|
RISCV_FEATURE_MISA
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PRIV_VERSION_1_09_1 0x00010901
|
|
||||||
#define PRIV_VERSION_1_10_0 0x00011000
|
#define PRIV_VERSION_1_10_0 0x00011000
|
||||||
#define PRIV_VERSION_1_11_0 0x00011100
|
#define PRIV_VERSION_1_11_0 0x00011100
|
||||||
|
|
||||||
|
@ -364,57 +364,36 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
|
|||||||
mxr = get_field(env->vsstatus, MSTATUS_MXR);
|
mxr = get_field(env->vsstatus, MSTATUS_MXR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env->priv_ver >= PRIV_VERSION_1_10_0) {
|
if (first_stage == true) {
|
||||||
if (first_stage == true) {
|
if (use_background) {
|
||||||
if (use_background) {
|
base = (hwaddr)get_field(env->vsatp, SATP_PPN) << PGSHIFT;
|
||||||
base = (hwaddr)get_field(env->vsatp, SATP_PPN) << PGSHIFT;
|
vm = get_field(env->vsatp, SATP_MODE);
|
||||||
vm = get_field(env->vsatp, SATP_MODE);
|
|
||||||
} else {
|
|
||||||
base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
|
|
||||||
vm = get_field(env->satp, SATP_MODE);
|
|
||||||
}
|
|
||||||
widened = 0;
|
|
||||||
} else {
|
} else {
|
||||||
base = (hwaddr)get_field(env->hgatp, HGATP_PPN) << PGSHIFT;
|
base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
|
||||||
vm = get_field(env->hgatp, HGATP_MODE);
|
vm = get_field(env->satp, SATP_MODE);
|
||||||
widened = 2;
|
|
||||||
}
|
}
|
||||||
sum = get_field(env->mstatus, MSTATUS_SUM);
|
|
||||||
switch (vm) {
|
|
||||||
case VM_1_10_SV32:
|
|
||||||
levels = 2; ptidxbits = 10; ptesize = 4; break;
|
|
||||||
case VM_1_10_SV39:
|
|
||||||
levels = 3; ptidxbits = 9; ptesize = 8; break;
|
|
||||||
case VM_1_10_SV48:
|
|
||||||
levels = 4; ptidxbits = 9; ptesize = 8; break;
|
|
||||||
case VM_1_10_SV57:
|
|
||||||
levels = 5; ptidxbits = 9; ptesize = 8; break;
|
|
||||||
case VM_1_10_MBARE:
|
|
||||||
*physical = addr;
|
|
||||||
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
|
||||||
return TRANSLATE_SUCCESS;
|
|
||||||
default:
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
widened = 0;
|
widened = 0;
|
||||||
base = (hwaddr)(env->sptbr) << PGSHIFT;
|
} else {
|
||||||
sum = !get_field(env->mstatus, MSTATUS_PUM);
|
base = (hwaddr)get_field(env->hgatp, HGATP_PPN) << PGSHIFT;
|
||||||
vm = get_field(env->mstatus, MSTATUS_VM);
|
vm = get_field(env->hgatp, HGATP_MODE);
|
||||||
switch (vm) {
|
widened = 2;
|
||||||
case VM_1_09_SV32:
|
}
|
||||||
levels = 2; ptidxbits = 10; ptesize = 4; break;
|
sum = get_field(env->mstatus, MSTATUS_SUM);
|
||||||
case VM_1_09_SV39:
|
switch (vm) {
|
||||||
levels = 3; ptidxbits = 9; ptesize = 8; break;
|
case VM_1_10_SV32:
|
||||||
case VM_1_09_SV48:
|
levels = 2; ptidxbits = 10; ptesize = 4; break;
|
||||||
levels = 4; ptidxbits = 9; ptesize = 8; break;
|
case VM_1_10_SV39:
|
||||||
case VM_1_09_MBARE:
|
levels = 3; ptidxbits = 9; ptesize = 8; break;
|
||||||
*physical = addr;
|
case VM_1_10_SV48:
|
||||||
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
levels = 4; ptidxbits = 9; ptesize = 8; break;
|
||||||
return TRANSLATE_SUCCESS;
|
case VM_1_10_SV57:
|
||||||
default:
|
levels = 5; ptidxbits = 9; ptesize = 8; break;
|
||||||
g_assert_not_reached();
|
case VM_1_10_MBARE:
|
||||||
}
|
*physical = addr;
|
||||||
|
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||||
|
return TRANSLATE_SUCCESS;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
CPUState *cs = env_cpu(env);
|
CPUState *cs = env_cpu(env);
|
||||||
@ -588,7 +567,6 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
|
|||||||
int page_fault_exceptions;
|
int page_fault_exceptions;
|
||||||
if (first_stage) {
|
if (first_stage) {
|
||||||
page_fault_exceptions =
|
page_fault_exceptions =
|
||||||
(env->priv_ver >= PRIV_VERSION_1_10_0) &&
|
|
||||||
get_field(env->satp, SATP_MODE) != VM_1_10_MBARE &&
|
get_field(env->satp, SATP_MODE) != VM_1_10_MBARE &&
|
||||||
!pmp_violation;
|
!pmp_violation;
|
||||||
} else {
|
} else {
|
||||||
@ -941,8 +919,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
s = env->mstatus;
|
s = env->mstatus;
|
||||||
s = set_field(s, MSTATUS_SPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
|
s = set_field(s, MSTATUS_SPIE, get_field(s, MSTATUS_SIE));
|
||||||
get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE << env->priv));
|
|
||||||
s = set_field(s, MSTATUS_SPP, env->priv);
|
s = set_field(s, MSTATUS_SPP, env->priv);
|
||||||
s = set_field(s, MSTATUS_SIE, 0);
|
s = set_field(s, MSTATUS_SIE, 0);
|
||||||
env->mstatus = s;
|
env->mstatus = s;
|
||||||
@ -979,8 +956,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
s = env->mstatus;
|
s = env->mstatus;
|
||||||
s = set_field(s, MSTATUS_MPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
|
s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_MIE));
|
||||||
get_field(s, MSTATUS_MIE) : get_field(s, MSTATUS_UIE << env->priv));
|
|
||||||
s = set_field(s, MSTATUS_MPP, env->priv);
|
s = set_field(s, MSTATUS_MPP, env->priv);
|
||||||
s = set_field(s, MSTATUS_MIE, 0);
|
s = set_field(s, MSTATUS_MIE, 0);
|
||||||
env->mstatus = s;
|
env->mstatus = s;
|
||||||
|
@ -58,31 +58,11 @@ static int ctr(CPURISCVState *env, int csrno)
|
|||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
CPUState *cs = env_cpu(env);
|
CPUState *cs = env_cpu(env);
|
||||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||||
uint32_t ctr_en = ~0u;
|
|
||||||
|
|
||||||
if (!cpu->cfg.ext_counters) {
|
if (!cpu->cfg.ext_counters) {
|
||||||
/* The Counters extensions is not enabled */
|
/* The Counters extensions is not enabled */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* The counters are always enabled at run time on newer priv specs, as the
|
|
||||||
* CSR has changed from controlling that the counters can be read to
|
|
||||||
* controlling that the counters increment.
|
|
||||||
*/
|
|
||||||
if (env->priv_ver > PRIV_VERSION_1_09_1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (env->priv < PRV_M) {
|
|
||||||
ctr_en &= env->mcounteren;
|
|
||||||
}
|
|
||||||
if (env->priv < PRV_S) {
|
|
||||||
ctr_en &= env->scounteren;
|
|
||||||
}
|
|
||||||
if (!(ctr_en & (1u << (csrno & 31)))) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -293,9 +273,6 @@ static const target_ulong delegable_excps =
|
|||||||
(1ULL << (RISCV_EXCP_INST_GUEST_PAGE_FAULT)) |
|
(1ULL << (RISCV_EXCP_INST_GUEST_PAGE_FAULT)) |
|
||||||
(1ULL << (RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT)) |
|
(1ULL << (RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT)) |
|
||||||
(1ULL << (RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT));
|
(1ULL << (RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT));
|
||||||
static const target_ulong sstatus_v1_9_mask = SSTATUS_SIE | SSTATUS_SPIE |
|
|
||||||
SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
|
|
||||||
SSTATUS_SUM | SSTATUS_SD;
|
|
||||||
static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
|
static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
|
||||||
SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
|
SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
|
||||||
SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD;
|
SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD;
|
||||||
@ -304,20 +281,11 @@ static const target_ulong hip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP;
|
|||||||
static const target_ulong vsip_writable_mask = MIP_VSSIP;
|
static const target_ulong vsip_writable_mask = MIP_VSSIP;
|
||||||
|
|
||||||
#if defined(TARGET_RISCV32)
|
#if defined(TARGET_RISCV32)
|
||||||
static const char valid_vm_1_09[16] = {
|
|
||||||
[VM_1_09_MBARE] = 1,
|
|
||||||
[VM_1_09_SV32] = 1,
|
|
||||||
};
|
|
||||||
static const char valid_vm_1_10[16] = {
|
static const char valid_vm_1_10[16] = {
|
||||||
[VM_1_10_MBARE] = 1,
|
[VM_1_10_MBARE] = 1,
|
||||||
[VM_1_10_SV32] = 1
|
[VM_1_10_SV32] = 1
|
||||||
};
|
};
|
||||||
#elif defined(TARGET_RISCV64)
|
#elif defined(TARGET_RISCV64)
|
||||||
static const char valid_vm_1_09[16] = {
|
|
||||||
[VM_1_09_MBARE] = 1,
|
|
||||||
[VM_1_09_SV39] = 1,
|
|
||||||
[VM_1_09_SV48] = 1,
|
|
||||||
};
|
|
||||||
static const char valid_vm_1_10[16] = {
|
static const char valid_vm_1_10[16] = {
|
||||||
[VM_1_10_MBARE] = 1,
|
[VM_1_10_MBARE] = 1,
|
||||||
[VM_1_10_SV39] = 1,
|
[VM_1_10_SV39] = 1,
|
||||||
@ -347,8 +315,7 @@ static int read_mstatus(CPURISCVState *env, int csrno, target_ulong *val)
|
|||||||
|
|
||||||
static int validate_vm(CPURISCVState *env, target_ulong vm)
|
static int validate_vm(CPURISCVState *env, target_ulong vm)
|
||||||
{
|
{
|
||||||
return (env->priv_ver >= PRIV_VERSION_1_10_0) ?
|
return valid_vm_1_10[vm & 0xf];
|
||||||
valid_vm_1_10[vm & 0xf] : valid_vm_1_09[vm & 0xf];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
|
static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
|
||||||
@ -358,34 +325,21 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
|
|||||||
int dirty;
|
int dirty;
|
||||||
|
|
||||||
/* flush tlb on mstatus fields that affect VM */
|
/* flush tlb on mstatus fields that affect VM */
|
||||||
if (env->priv_ver <= PRIV_VERSION_1_09_1) {
|
if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV |
|
||||||
if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP |
|
MSTATUS_MPRV | MSTATUS_SUM)) {
|
||||||
MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_VM)) {
|
tlb_flush(env_cpu(env));
|
||||||
tlb_flush(env_cpu(env));
|
|
||||||
}
|
|
||||||
mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
|
|
||||||
MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
|
|
||||||
MSTATUS_MPP | MSTATUS_MXR |
|
|
||||||
(validate_vm(env, get_field(val, MSTATUS_VM)) ?
|
|
||||||
MSTATUS_VM : 0);
|
|
||||||
}
|
}
|
||||||
if (env->priv_ver >= PRIV_VERSION_1_10_0) {
|
mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
|
||||||
if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV |
|
MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
|
||||||
MSTATUS_MPRV | MSTATUS_SUM)) {
|
MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR |
|
||||||
tlb_flush(env_cpu(env));
|
MSTATUS_TW;
|
||||||
}
|
|
||||||
mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
|
|
||||||
MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
|
|
||||||
MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR |
|
|
||||||
MSTATUS_TW;
|
|
||||||
#if defined(TARGET_RISCV64)
|
#if defined(TARGET_RISCV64)
|
||||||
/*
|
/*
|
||||||
* RV32: MPV and MTL are not in mstatus. The current plan is to
|
* RV32: MPV and MTL are not in mstatus. The current plan is to
|
||||||
* add them to mstatush. For now, we just don't support it.
|
* add them to mstatush. For now, we just don't support it.
|
||||||
*/
|
*/
|
||||||
mask |= MSTATUS_MTL | MSTATUS_MPV;
|
mask |= MSTATUS_MTL | MSTATUS_MPV;
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
mstatus = (mstatus & ~mask) | (val & mask);
|
mstatus = (mstatus & ~mask) | (val & mask);
|
||||||
|
|
||||||
@ -534,18 +488,12 @@ static int write_mtvec(CPURISCVState *env, int csrno, target_ulong val)
|
|||||||
|
|
||||||
static int read_mcounteren(CPURISCVState *env, int csrno, target_ulong *val)
|
static int read_mcounteren(CPURISCVState *env, int csrno, target_ulong *val)
|
||||||
{
|
{
|
||||||
if (env->priv_ver < PRIV_VERSION_1_10_0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*val = env->mcounteren;
|
*val = env->mcounteren;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_mcounteren(CPURISCVState *env, int csrno, target_ulong val)
|
static int write_mcounteren(CPURISCVState *env, int csrno, target_ulong val)
|
||||||
{
|
{
|
||||||
if (env->priv_ver < PRIV_VERSION_1_10_0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
env->mcounteren = val;
|
env->mcounteren = val;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -553,8 +501,7 @@ static int write_mcounteren(CPURISCVState *env, int csrno, target_ulong val)
|
|||||||
/* This regiser is replaced with CSR_MCOUNTINHIBIT in 1.11.0 */
|
/* This regiser is replaced with CSR_MCOUNTINHIBIT in 1.11.0 */
|
||||||
static int read_mscounteren(CPURISCVState *env, int csrno, target_ulong *val)
|
static int read_mscounteren(CPURISCVState *env, int csrno, target_ulong *val)
|
||||||
{
|
{
|
||||||
if (env->priv_ver > PRIV_VERSION_1_09_1
|
if (env->priv_ver < PRIV_VERSION_1_11_0) {
|
||||||
&& env->priv_ver < PRIV_VERSION_1_11_0) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*val = env->mcounteren;
|
*val = env->mcounteren;
|
||||||
@ -564,32 +511,13 @@ static int read_mscounteren(CPURISCVState *env, int csrno, target_ulong *val)
|
|||||||
/* This regiser is replaced with CSR_MCOUNTINHIBIT in 1.11.0 */
|
/* This regiser is replaced with CSR_MCOUNTINHIBIT in 1.11.0 */
|
||||||
static int write_mscounteren(CPURISCVState *env, int csrno, target_ulong val)
|
static int write_mscounteren(CPURISCVState *env, int csrno, target_ulong val)
|
||||||
{
|
{
|
||||||
if (env->priv_ver > PRIV_VERSION_1_09_1
|
if (env->priv_ver < PRIV_VERSION_1_11_0) {
|
||||||
&& env->priv_ver < PRIV_VERSION_1_11_0) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
env->mcounteren = val;
|
env->mcounteren = val;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_mucounteren(CPURISCVState *env, int csrno, target_ulong *val)
|
|
||||||
{
|
|
||||||
if (env->priv_ver > PRIV_VERSION_1_09_1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*val = env->scounteren;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int write_mucounteren(CPURISCVState *env, int csrno, target_ulong val)
|
|
||||||
{
|
|
||||||
if (env->priv_ver > PRIV_VERSION_1_09_1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
env->scounteren = val;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Machine Trap Handling */
|
/* Machine Trap Handling */
|
||||||
static int read_mscratch(CPURISCVState *env, int csrno, target_ulong *val)
|
static int read_mscratch(CPURISCVState *env, int csrno, target_ulong *val)
|
||||||
{
|
{
|
||||||
@ -663,16 +591,14 @@ static int rmw_mip(CPURISCVState *env, int csrno, target_ulong *ret_value,
|
|||||||
/* Supervisor Trap Setup */
|
/* Supervisor Trap Setup */
|
||||||
static int read_sstatus(CPURISCVState *env, int csrno, target_ulong *val)
|
static int read_sstatus(CPURISCVState *env, int csrno, target_ulong *val)
|
||||||
{
|
{
|
||||||
target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
|
target_ulong mask = (sstatus_v1_10_mask);
|
||||||
sstatus_v1_10_mask : sstatus_v1_9_mask);
|
|
||||||
*val = env->mstatus & mask;
|
*val = env->mstatus & mask;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
|
static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
|
||||||
{
|
{
|
||||||
target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
|
target_ulong mask = (sstatus_v1_10_mask);
|
||||||
sstatus_v1_10_mask : sstatus_v1_9_mask);
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
@ -722,18 +648,12 @@ static int write_stvec(CPURISCVState *env, int csrno, target_ulong val)
|
|||||||
|
|
||||||
static int read_scounteren(CPURISCVState *env, int csrno, target_ulong *val)
|
static int read_scounteren(CPURISCVState *env, int csrno, target_ulong *val)
|
||||||
{
|
{
|
||||||
if (env->priv_ver < PRIV_VERSION_1_10_0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*val = env->scounteren;
|
*val = env->scounteren;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_scounteren(CPURISCVState *env, int csrno, target_ulong val)
|
static int write_scounteren(CPURISCVState *env, int csrno, target_ulong val)
|
||||||
{
|
{
|
||||||
if (env->priv_ver < PRIV_VERSION_1_10_0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
env->scounteren = val;
|
env->scounteren = val;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -812,15 +732,15 @@ static int read_satp(CPURISCVState *env, int csrno, target_ulong *val)
|
|||||||
{
|
{
|
||||||
if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
|
if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
|
||||||
*val = 0;
|
*val = 0;
|
||||||
} else if (env->priv_ver >= PRIV_VERSION_1_10_0) {
|
return 0;
|
||||||
if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
*val = env->satp;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
*val = env->sptbr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
*val = env->satp;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -829,13 +749,7 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
|
|||||||
if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
|
if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (env->priv_ver <= PRIV_VERSION_1_09_1 && (val ^ env->sptbr)) {
|
if (validate_vm(env, get_field(val, SATP_MODE)) &&
|
||||||
tlb_flush(env_cpu(env));
|
|
||||||
env->sptbr = val & (((target_ulong)
|
|
||||||
1 << (TARGET_PHYS_ADDR_SPACE_BITS - PGSHIFT)) - 1);
|
|
||||||
}
|
|
||||||
if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
|
|
||||||
validate_vm(env, get_field(val, SATP_MODE)) &&
|
|
||||||
((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
|
((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
|
||||||
{
|
{
|
||||||
if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
|
if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
|
||||||
@ -1313,8 +1227,6 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
|
|||||||
[CSR_MSTATUSH] = { any, read_mstatush, write_mstatush },
|
[CSR_MSTATUSH] = { any, read_mstatush, write_mstatush },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Legacy Counter Setup (priv v1.9.1) */
|
|
||||||
[CSR_MUCOUNTEREN] = { any, read_mucounteren, write_mucounteren },
|
|
||||||
[CSR_MSCOUNTEREN] = { any, read_mscounteren, write_mscounteren },
|
[CSR_MSCOUNTEREN] = { any, read_mscounteren, write_mscounteren },
|
||||||
|
|
||||||
/* Machine Trap Handling */
|
/* Machine Trap Handling */
|
||||||
|
@ -85,30 +85,21 @@ static bool trans_wfi(DisasContext *ctx, arg_wfi *a)
|
|||||||
static bool trans_sfence_vma(DisasContext *ctx, arg_sfence_vma *a)
|
static bool trans_sfence_vma(DisasContext *ctx, arg_sfence_vma *a)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
if (ctx->priv_ver >= PRIV_VERSION_1_10_0) {
|
gen_helper_tlb_flush(cpu_env);
|
||||||
gen_helper_tlb_flush(cpu_env);
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool trans_sfence_vm(DisasContext *ctx, arg_sfence_vm *a)
|
static bool trans_sfence_vm(DisasContext *ctx, arg_sfence_vm *a)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_USER_ONLY
|
|
||||||
if (ctx->priv_ver <= PRIV_VERSION_1_09_1) {
|
|
||||||
gen_helper_tlb_flush(cpu_env);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a)
|
static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
if (ctx->priv_ver >= PRIV_VERSION_1_10_0 &&
|
if (has_ext(ctx, RVH)) {
|
||||||
has_ext(ctx, RVH)) {
|
|
||||||
/* Hpervisor extensions exist */
|
/* Hpervisor extensions exist */
|
||||||
/*
|
/*
|
||||||
* if (env->priv == PRV_M ||
|
* if (env->priv == PRV_M ||
|
||||||
@ -127,8 +118,7 @@ static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a)
|
|||||||
static bool trans_hfence_bvma(DisasContext *ctx, arg_sfence_vma *a)
|
static bool trans_hfence_bvma(DisasContext *ctx, arg_sfence_vma *a)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
if (ctx->priv_ver >= PRIV_VERSION_1_10_0 &&
|
if (has_ext(ctx, RVH)) {
|
||||||
has_ext(ctx, RVH)) {
|
|
||||||
/* Hpervisor extensions exist */
|
/* Hpervisor extensions exist */
|
||||||
/*
|
/*
|
||||||
* if (env->priv == PRV_M ||
|
* if (env->priv == PRV_M ||
|
||||||
|
@ -215,11 +215,6 @@ void hmp_info_mem(Monitor *mon, const QDict *qdict)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env->priv_ver < PRIV_VERSION_1_10_0) {
|
|
||||||
monitor_printf(mon, "Privileged mode < 1.10 unsupported\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(env->satp & SATP_MODE)) {
|
if (!(env->satp & SATP_MODE)) {
|
||||||
monitor_printf(mon, "No translation or protection\n");
|
monitor_printf(mon, "No translation or protection\n");
|
||||||
return;
|
return;
|
||||||
|
@ -84,8 +84,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
|
|||||||
riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
|
riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
|
if (get_field(env->mstatus, MSTATUS_TSR) && !(env->priv >= PRV_M)) {
|
||||||
get_field(env->mstatus, MSTATUS_TSR) && !(env->priv >= PRV_M)) {
|
|
||||||
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
|
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,10 +118,8 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
|
|||||||
} else {
|
} else {
|
||||||
prev_priv = get_field(mstatus, MSTATUS_SPP);
|
prev_priv = get_field(mstatus, MSTATUS_SPP);
|
||||||
|
|
||||||
mstatus = set_field(mstatus,
|
mstatus = set_field(mstatus, MSTATUS_SIE,
|
||||||
env->priv_ver >= PRIV_VERSION_1_10_0 ?
|
get_field(mstatus, MSTATUS_SPIE));
|
||||||
MSTATUS_SIE : MSTATUS_UIE << prev_priv,
|
|
||||||
get_field(mstatus, MSTATUS_SPIE));
|
|
||||||
mstatus = set_field(mstatus, MSTATUS_SPIE, 1);
|
mstatus = set_field(mstatus, MSTATUS_SPIE, 1);
|
||||||
mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
|
mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
|
||||||
env->mstatus = mstatus;
|
env->mstatus = mstatus;
|
||||||
@ -147,10 +144,8 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
|
|||||||
target_ulong mstatus = env->mstatus;
|
target_ulong mstatus = env->mstatus;
|
||||||
target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
|
target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
|
||||||
target_ulong prev_virt = MSTATUS_MPV_ISSET(env);
|
target_ulong prev_virt = MSTATUS_MPV_ISSET(env);
|
||||||
mstatus = set_field(mstatus,
|
mstatus = set_field(mstatus, MSTATUS_MIE,
|
||||||
env->priv_ver >= PRIV_VERSION_1_10_0 ?
|
get_field(mstatus, MSTATUS_MPIE));
|
||||||
MSTATUS_MIE : MSTATUS_UIE << prev_priv,
|
|
||||||
get_field(mstatus, MSTATUS_MPIE));
|
|
||||||
mstatus = set_field(mstatus, MSTATUS_MPIE, 1);
|
mstatus = set_field(mstatus, MSTATUS_MPIE, 1);
|
||||||
mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
|
mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
|
||||||
#ifdef TARGET_RISCV32
|
#ifdef TARGET_RISCV32
|
||||||
@ -177,7 +172,6 @@ void helper_wfi(CPURISCVState *env)
|
|||||||
CPUState *cs = env_cpu(env);
|
CPUState *cs = env_cpu(env);
|
||||||
|
|
||||||
if ((env->priv == PRV_S &&
|
if ((env->priv == PRV_S &&
|
||||||
env->priv_ver >= PRIV_VERSION_1_10_0 &&
|
|
||||||
get_field(env->mstatus, MSTATUS_TW)) ||
|
get_field(env->mstatus, MSTATUS_TW)) ||
|
||||||
riscv_cpu_virt_enabled(env)) {
|
riscv_cpu_virt_enabled(env)) {
|
||||||
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
|
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
|
||||||
@ -193,7 +187,6 @@ void helper_tlb_flush(CPURISCVState *env)
|
|||||||
CPUState *cs = env_cpu(env);
|
CPUState *cs = env_cpu(env);
|
||||||
if (!(env->priv >= PRV_S) ||
|
if (!(env->priv >= PRV_S) ||
|
||||||
(env->priv == PRV_S &&
|
(env->priv == PRV_S &&
|
||||||
env->priv_ver >= PRIV_VERSION_1_10_0 &&
|
|
||||||
get_field(env->mstatus, MSTATUS_TVM))) {
|
get_field(env->mstatus, MSTATUS_TVM))) {
|
||||||
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
|
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user