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 * 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, static int get_physical_address(CPURISCVState *env, hwaddr *physical,
int *prot, target_ulong addr, 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 /* NOTE: the env->pc value visible here will not be
* correct, but the value visible to the exception handler * correct, but the value visible to the exception handler
@ -485,13 +494,21 @@ restart:
} }
static void raise_mmu_exception(CPURISCVState *env, target_ulong address, 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); CPUState *cs = env_cpu(env);
int page_fault_exceptions = int page_fault_exceptions;
(env->priv_ver >= PRIV_VERSION_1_10_0) && if (first_stage) {
get_field(env->satp, SATP_MODE) != VM_1_10_MBARE && page_fault_exceptions =
!pmp_violation; (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) { switch (access_type) {
case MMU_INST_FETCH: case MMU_INST_FETCH:
cs->exception_index = page_fault_exceptions ? cs->exception_index = page_fault_exceptions ?
@ -518,7 +535,8 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
int prot; int prot;
int mmu_idx = cpu_mmu_index(&cpu->env, false); 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 -1;
} }
return phys_addr; 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", qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
__func__, address, access_type, mmu_idx); __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 (mode == PRV_M && access_type != MMU_INST_FETCH) {
if (get_field(env->mstatus, MSTATUS_MPRV)) { 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) { } else if (probe) {
return false; return false;
} else { } 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); riscv_raise_exception(env, cs->exception_index, retaddr);
} }
#else #else