The qemu_log_mask(CPU_LOG_MMU,... calls trigger false positive checkpatch errors which are being ignored.
Signed-off-by: Alistair Francis <alistair.fran...@wdc.com> --- target/riscv/cpu_helper.c | 118 ++++++++++++++++++++++++++++++++------ 1 file changed, 99 insertions(+), 19 deletions(-) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index ece3eadf66..023368c2ce 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -582,15 +582,23 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address, hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) { RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; hwaddr phys_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, - true, false)) { + if (get_physical_address(env, &phys_addr, &prot, addr, 0, mmu_idx, + true, riscv_cpu_virt_enabled(env))) { return -1; } + if (riscv_cpu_virt_enabled(env)) { + if (get_physical_address(env, &phys_addr, &prot, phys_addr, + 0, mmu_idx, false, true)) { + return -1; + } + } + return phys_addr; } @@ -641,34 +649,106 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, #ifndef CONFIG_USER_ONLY RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; + vaddr im_address; hwaddr pa = 0; int prot; + bool m_mode_two_stage = false; + bool hs_mode_two_stage = false; int ret = TRANSLATE_FAIL; 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, - true, false); + /* + * 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) && + get_field(env->mstatus, MSTATUS_MPV); + + 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 (riscv_cpu_virt_enabled(env) || m_mode_two_stage || hs_mode_two_stage) { + /* Two stage lookup */ + ret = get_physical_address(env, &pa, &prot, address, access_type, + mmu_idx, true, true); - qemu_log_mask(CPU_LOG_MMU, - "%s address=%" VADDR_PRIx " ret %d physical " TARGET_FMT_plx - " prot %d\n", __func__, address, ret, pa, prot); + qemu_log_mask(CPU_LOG_MMU, + "%s 1st-stage address=%" VADDR_PRIx " ret %d physical " + TARGET_FMT_plx " prot %d\n", + __func__, address, ret, pa, prot); - if (riscv_feature(env, RISCV_FEATURE_PMP) && - !pmp_hart_has_privs(env, pa, TARGET_PAGE_SIZE, 1 << access_type)) { - ret = TRANSLATE_FAIL; - } - if (ret == TRANSLATE_SUCCESS) { - tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK, - prot, mmu_idx, TARGET_PAGE_SIZE); - return true; - } else if (probe) { - return false; + if (ret == TRANSLATE_FAIL) { + if (!probe) { + raise_mmu_exception(env, address, access_type, true); + riscv_raise_exception(env, cs->exception_index, retaddr); + } + return ret; + } + + /* Second stage lookup */ + im_address = pa; + + ret = get_physical_address(env, &pa, &prot, im_address, access_type, mmu_idx, + false, true); + + qemu_log_mask(CPU_LOG_MMU, + "%s 2nd-stage address=%" VADDR_PRIx " ret %d physical " + TARGET_FMT_plx " prot %d\n", + __func__, im_address, ret, pa, prot); + + if (riscv_feature(env, RISCV_FEATURE_PMP) && + !pmp_hart_has_privs(env, pa, TARGET_PAGE_SIZE, 1 << access_type)) { + ret = TRANSLATE_FAIL; + } + + if (ret == TRANSLATE_FAIL) { + /* + * Guest physical address translation failed, this is a HS + * level exception + */ + if (!probe) { + raise_mmu_exception(env, im_address | (address & (TARGET_PAGE_SIZE - 1)), access_type, false); + riscv_raise_exception(env, cs->exception_index, retaddr); + } + return ret; + } } else { - raise_mmu_exception(env, address, access_type, true); - riscv_raise_exception(env, cs->exception_index, retaddr); + /* Single stage lookup */ + ret = get_physical_address(env, &pa, &prot, address, access_type, + mmu_idx, true, false); + + qemu_log_mask(CPU_LOG_MMU, + "%s address=%" VADDR_PRIx " ret %d physical " + TARGET_FMT_plx " prot %d\n", + __func__, address, ret, pa, prot); + + if (riscv_feature(env, RISCV_FEATURE_PMP) && + !pmp_hart_has_privs(env, pa, TARGET_PAGE_SIZE, 1 << access_type)) { + ret = TRANSLATE_FAIL; + } + + if (ret == TRANSLATE_FAIL) { + if (!probe) { + raise_mmu_exception(env, address, access_type, true); + riscv_raise_exception(env, cs->exception_index, retaddr); + } + return ret; + } } + + tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK, + prot, mmu_idx, TARGET_PAGE_SIZE); + return true; + #else switch (access_type) { case MMU_INST_FETCH: -- 2.21.0