[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v3 03/13] target/riscv: Do two-stage lookups on hlv/hlvx/hsv inst
From: |
Alistair Francis |
Subject: |
[PATCH v3 03/13] target/riscv: Do two-stage lookups on hlv/hlvx/hsv instructions |
Date: |
Wed, 12 Aug 2020 12:13:22 -0700 |
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
target/riscv/cpu_helper.c | 60 ++++++++++++++++-----------------------
1 file changed, 25 insertions(+), 35 deletions(-)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 68abccc993..10c9f8b63b 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -340,22 +340,13 @@ static int get_physical_address(CPURISCVState *env,
hwaddr *physical,
* was called. Background registers will be used if the guest has
* forced a two stage translation to be on (in HS or M mode).
*/
+ if (riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH) {
+ use_background = true;
+ }
+
if (mode == PRV_M && access_type != MMU_INST_FETCH) {
if (get_field(env->mstatus, MSTATUS_MPRV)) {
mode = get_field(env->mstatus, MSTATUS_MPP);
-
- if (riscv_has_ext(env, RVH) &&
- MSTATUS_MPV_ISSET(env)) {
- use_background = true;
- }
- }
- }
-
- if (mode == PRV_S && access_type != MMU_INST_FETCH &&
- riscv_has_ext(env, RVH) && !riscv_cpu_virt_enabled(env)) {
- if (get_field(env->hstatus, HSTATUS_SPRV)) {
- mode = get_field(env->mstatus, SSTATUS_SPP);
- use_background = true;
}
}
@@ -607,7 +598,8 @@ static void raise_mmu_exception(CPURISCVState *env,
target_ulong address,
}
break;
case MMU_DATA_LOAD:
- if (riscv_cpu_virt_enabled(env) && !first_stage) {
+ if ((riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(env)) &&
+ !first_stage) {
cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT;
} else {
cs->exception_index = page_fault_exceptions ?
@@ -615,7 +607,8 @@ static void raise_mmu_exception(CPURISCVState *env,
target_ulong address,
}
break;
case MMU_DATA_STORE:
- if (riscv_cpu_virt_enabled(env) && !first_stage) {
+ if ((riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(env)) &&
+ !first_stage) {
cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT;
} else {
cs->exception_index = page_fault_exceptions ?
@@ -705,8 +698,6 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int
size,
hwaddr pa = 0;
int prot, prot2;
bool pmp_violation = false;
- bool m_mode_two_stage = false;
- bool hs_mode_two_stage = false;
bool first_stage_error = true;
int ret = TRANSLATE_FAIL;
int mode = mmu_idx;
@@ -716,30 +707,21 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int
size,
qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
__func__, address, access_type, mmu_idx);
- /*
- * Determine if we are in M mode and MPRV is set or in HS mode and SPRV is
- * set and we want to access a virtulisation address.
- */
- if (riscv_has_ext(env, RVH)) {
- m_mode_two_stage = env->priv == PRV_M &&
- access_type != MMU_INST_FETCH &&
- get_field(env->mstatus, MSTATUS_MPRV) &&
- MSTATUS_MPV_ISSET(env);
-
- hs_mode_two_stage = env->priv == PRV_S &&
- !riscv_cpu_virt_enabled(env) &&
- access_type != MMU_INST_FETCH &&
- get_field(env->hstatus, HSTATUS_SPRV) &&
- get_field(env->hstatus, HSTATUS_SPV);
- }
-
if (mode == PRV_M && access_type != MMU_INST_FETCH) {
if (get_field(env->mstatus, MSTATUS_MPRV)) {
mode = get_field(env->mstatus, MSTATUS_MPP);
}
}
- if (riscv_cpu_virt_enabled(env) || m_mode_two_stage || hs_mode_two_stage) {
+ if (riscv_has_ext(env, RVH) && env->priv == PRV_M &&
+ access_type != MMU_INST_FETCH &&
+ get_field(env->mstatus, MSTATUS_MPRV) &&
+ MSTATUS_MPV_ISSET(env)) {
+ riscv_cpu_set_two_stage_lookup(env, true);
+ }
+
+ if (riscv_cpu_virt_enabled(env) ||
+ (riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH)) {
/* Two stage lookup */
ret = get_physical_address(env, &pa, &prot, address, access_type,
mmu_idx, true, true);
@@ -791,6 +773,14 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int
size,
__func__, address, ret, pa, prot);
}
+ /* We did the two stage lookup based on MPRV, unset the lookup */
+ if (riscv_has_ext(env, RVH) && env->priv == PRV_M &&
+ access_type != MMU_INST_FETCH &&
+ get_field(env->mstatus, MSTATUS_MPRV) &&
+ MSTATUS_MPV_ISSET(env)) {
+ riscv_cpu_set_two_stage_lookup(env, false);
+ }
+
if (riscv_feature(env, RISCV_FEATURE_PMP) &&
(ret == TRANSLATE_SUCCESS) &&
!pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) {
--
2.27.0
- [PATCH v3 00/13] RISC-V: Update the Hypervisor spec to v0.6.1, Alistair Francis, 2020/08/12
- [PATCH v3 01/13] target/riscv: Allow setting a two-stage lookup in the virt status, Alistair Francis, 2020/08/12
- [PATCH v3 02/13] target/riscv: Allow generating hlv/hlvx/hsv instructions, Alistair Francis, 2020/08/12
- [PATCH v3 03/13] target/riscv: Do two-stage lookups on hlv/hlvx/hsv instructions,
Alistair Francis <=
- [PATCH v3 04/13] target/riscv: Don't allow guest to write to htinst, Alistair Francis, 2020/08/12
- [PATCH v3 05/13] target/riscv: Convert MSTATUS MTL to GVA, Alistair Francis, 2020/08/12
- [PATCH v3 06/13] target/riscv: Fix the interrupt cause code, Alistair Francis, 2020/08/12
- [PATCH v3 07/13] target/riscv: Update the Hypervisor trap return/entry, Alistair Francis, 2020/08/12
- [PATCH v3 08/13] target/riscv: Update the CSRs to the v0.6 Hyp extension, Alistair Francis, 2020/08/12
- [PATCH v3 09/13] target/riscv: Only support a single VSXL length, Alistair Francis, 2020/08/12
- [PATCH v3 10/13] target/riscv: Only support little endian guests, Alistair Francis, 2020/08/12
- [PATCH v3 12/13] target/riscv: Return the exception from invalid CSR accesses, Alistair Francis, 2020/08/12
- [PATCH v3 11/13] target/riscv: Support the v0.6 Hypervisor extension CRSs, Alistair Francis, 2020/08/12
- [PATCH v3 13/13] target/riscv: Support the Virtual Instruction fault, Alistair Francis, 2020/08/12