target/riscv: Allow specifying MMU stage

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:53 -08:00 committed by Palmer Dabbelt
parent ae84dd0ab7
commit 1448689c7b
No known key found for this signature in database
GPG Key ID: 2E1319F35FBB1889

View File

@ -277,10 +277,19 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
*
* Adapted from Spike's mmu_t::translate and mmu_t::walk
*
* @env: CPURISCVState
* @physical: This will be set to the calculated physical address
* @prot: The returned protection attributes
* @addr: The virtual address to be translated
* @access_type: The type of MMU access
* @mmu_idx: Indicates current privilege level
* @first_stage: Are we in first stage translation?
* Second stage is used for hypervisor guest translation
*/
static int get_physical_address(CPURISCVState *env, hwaddr *physical,
int *prot, target_ulong addr,
int access_type, int mmu_idx)
int access_type, int mmu_idx,
bool first_stage)
{
/* NOTE: the env->pc value visible here will not be
* correct, but the value visible to the exception handler
@ -485,13 +494,21 @@ restart:
}
static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
MMUAccessType access_type, bool pmp_violation)
MMUAccessType access_type, bool pmp_violation,
bool first_stage)
{
CPUState *cs = env_cpu(env);
int page_fault_exceptions =
(env->priv_ver >= PRIV_VERSION_1_10_0) &&
get_field(env->satp, SATP_MODE) != VM_1_10_MBARE &&
!pmp_violation;
int page_fault_exceptions;
if (first_stage) {
page_fault_exceptions =
(env->priv_ver >= PRIV_VERSION_1_10_0) &&
get_field(env->satp, SATP_MODE) != VM_1_10_MBARE &&
!pmp_violation;
} else {
page_fault_exceptions =
get_field(env->hgatp, HGATP_MODE) != VM_1_10_MBARE &&
!pmp_violation;
}
switch (access_type) {
case MMU_INST_FETCH:
cs->exception_index = page_fault_exceptions ?
@ -518,7 +535,8 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
int prot;
int mmu_idx = cpu_mmu_index(&cpu->env, false);
if (get_physical_address(&cpu->env, &phys_addr, &prot, addr, 0, mmu_idx)) {
if (get_physical_address(&cpu->env, &phys_addr, &prot, addr, 0, mmu_idx,
true)) {
return -1;
}
return phys_addr;
@ -583,7 +601,8 @@ 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);
ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx);
ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx,
true);
if (mode == PRV_M && access_type != MMU_INST_FETCH) {
if (get_field(env->mstatus, MSTATUS_MPRV)) {
@ -610,7 +629,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
} else if (probe) {
return false;
} else {
raise_mmu_exception(env, address, access_type, pmp_violation);
raise_mmu_exception(env, address, access_type, pmp_violation, true);
riscv_raise_exception(env, cs->exception_index, retaddr);
}
#else