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:
parent
ae84dd0ab7
commit
1448689c7b
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user