Message ID | 39abe56d7ba4d0ba392af6df09986af849f19403.1566603412.git.alistair.francis@wdc.com |
---|---|
State | New |
Headers | show |
Series | Add RISC-V Hypervisor Extension v0.4 | expand |
On Fri, 23 Aug 2019 16:38:55 PDT (-0700), Alistair Francis wrote: > The qemu_log_mask(CPU_LOG_MMU,... calls trigger false positive > checkpatch errors which are being ignored. > > Signed-off-by: Alistair Francis <alistair.francis@wdc.com> > --- > target/riscv/cpu_helper.c | 94 +++++++++++++++++++++++++++++++++++---- > 1 file changed, 86 insertions(+), 8 deletions(-) > > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c > index 188d5cb39f..0761191f11 100644 > --- a/target/riscv/cpu_helper.c > +++ b/target/riscv/cpu_helper.c > @@ -642,15 +642,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; > } > > @@ -701,17 +709,35 @@ 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 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; > > 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 (mode == PRV_M && access_type != MMU_INST_FETCH) { > if (get_field(*env->mstatus, MSTATUS_MPRV)) { > @@ -719,10 +745,58 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, > } > } > > - 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_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 1st-stage address=%" VADDR_PRIx " ret %d physical " > + TARGET_FMT_plx " prot %d\n", > + __func__, address, ret, pa, prot); > + > + if (ret == TRANSLATE_FAIL) { > + goto tlb_lookup_done; > + } > + > + /* 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) && > + (ret == TRANSLATE_SUCCESS) && > + !pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) { > + ret = TRANSLATE_PMP_FAIL; > + } > + > + if (ret != TRANSLATE_SUCCESS) { > + /* > + * Guest physical address translation failed, this is a HS > + * level exception > + */ > + first_stage_error = false; > + address = im_address | (address & (TARGET_PAGE_SIZE - 1)); > + goto tlb_lookup_done; > + } > + } else { > + /* 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); > + } > + > +tlb_lookup_done: > if (riscv_feature(env, RISCV_FEATURE_PMP) && > (ret == TRANSLATE_SUCCESS) && > !pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) { > @@ -731,6 +805,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, > if (ret == TRANSLATE_PMP_FAIL) { > pmp_violation = true; > } > + > if (ret == TRANSLATE_SUCCESS) { > tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK, > prot, mmu_idx, TARGET_PAGE_SIZE); > @@ -738,9 +813,12 @@ 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, true); > + raise_mmu_exception(env, address, access_type, pmp_violation, first_stage_error); > riscv_raise_exception(env, cs->exception_index, retaddr); > } > + > + return true; > + > #else > switch (access_type) { > case MMU_INST_FETCH: Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 188d5cb39f..0761191f11 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -642,15 +642,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; } @@ -701,17 +709,35 @@ 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 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; 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 (mode == PRV_M && access_type != MMU_INST_FETCH) { if (get_field(*env->mstatus, MSTATUS_MPRV)) { @@ -719,10 +745,58 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, } } - 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_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 1st-stage address=%" VADDR_PRIx " ret %d physical " + TARGET_FMT_plx " prot %d\n", + __func__, address, ret, pa, prot); + + if (ret == TRANSLATE_FAIL) { + goto tlb_lookup_done; + } + + /* 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) && + (ret == TRANSLATE_SUCCESS) && + !pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) { + ret = TRANSLATE_PMP_FAIL; + } + + if (ret != TRANSLATE_SUCCESS) { + /* + * Guest physical address translation failed, this is a HS + * level exception + */ + first_stage_error = false; + address = im_address | (address & (TARGET_PAGE_SIZE - 1)); + goto tlb_lookup_done; + } + } else { + /* 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); + } + +tlb_lookup_done: if (riscv_feature(env, RISCV_FEATURE_PMP) && (ret == TRANSLATE_SUCCESS) && !pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) { @@ -731,6 +805,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, if (ret == TRANSLATE_PMP_FAIL) { pmp_violation = true; } + if (ret == TRANSLATE_SUCCESS) { tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK, prot, mmu_idx, TARGET_PAGE_SIZE); @@ -738,9 +813,12 @@ 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, true); + raise_mmu_exception(env, address, access_type, pmp_violation, first_stage_error); riscv_raise_exception(env, cs->exception_index, retaddr); } + + return true; + #else switch (access_type) { case MMU_INST_FETCH:
The qemu_log_mask(CPU_LOG_MMU,... calls trigger false positive checkpatch errors which are being ignored. Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu_helper.c | 94 +++++++++++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 8 deletions(-)