Message ID | 20230325105429.1142530-17-richard.henderson@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | target/riscv: MSTATUS_SUM + cleanups | expand |
On Sat, Mar 25, 2023 at 9:58 PM Richard Henderson <richard.henderson@linaro.org> wrote: > > Incorporate the virt_enabled and MPV checks into the cpu_mmu_index > function, so we don't have to keep doing it within tlb_fill and > subroutines. This also elides a flush on changes to MPV. > > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Alistair > --- > target/riscv/cpu_helper.c | 50 +++++++++++++-------------------------- > target/riscv/csr.c | 6 +---- > 2 files changed, 18 insertions(+), 38 deletions(-) > > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c > index 0adfd4a12b..6c42f9c6fd 100644 > --- a/target/riscv/cpu_helper.c > +++ b/target/riscv/cpu_helper.c > @@ -37,19 +37,21 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch) > #ifdef CONFIG_USER_ONLY > return 0; > #else > - if (ifetch) { > - return env->priv; > - } > + bool virt = riscv_cpu_virt_enabled(env); > + int mode = env->priv; > > /* All priv -> mmu_idx mapping are here */ > - int mode = env->priv; > - if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) { > - mode = get_field(env->mstatus, MSTATUS_MPP); > + if (!ifetch) { > + if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) { > + mode = get_field(env->mstatus, MSTATUS_MPP); > + virt = get_field(env->mstatus, MSTATUS_MPV); > + } > + if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) { > + mode = MMUIdx_S_SUM; > + } > } > - if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) { > - return MMUIdx_S_SUM; > - } > - return mode; > + > + return mode | (virt ? MMU_2STAGE_BIT : 0); > #endif > } > > @@ -1165,8 +1167,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, > } > > env->badaddr = addr; > - env->two_stage_lookup = riscv_cpu_virt_enabled(env) || > - mmuidx_2stage(mmu_idx); > + env->two_stage_lookup = mmuidx_2stage(mmu_idx); > env->two_stage_indirect_lookup = false; > cpu_loop_exit_restore(cs, retaddr); > } > @@ -1191,8 +1192,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, > g_assert_not_reached(); > } > env->badaddr = addr; > - env->two_stage_lookup = riscv_cpu_virt_enabled(env) || > - mmuidx_2stage(mmu_idx); > + env->two_stage_lookup = mmuidx_2stage(mmu_idx); > env->two_stage_indirect_lookup = false; > cpu_loop_exit_restore(cs, retaddr); > } > @@ -1230,7 +1230,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, > int prot, prot2, prot_pmp; > bool pmp_violation = false; > bool first_stage_error = true; > - bool two_stage_lookup = false; > + bool two_stage_lookup = mmuidx_2stage(mmu_idx); > bool two_stage_indirect_error = false; > int ret = TRANSLATE_FAIL; > int mode = mmu_idx; > @@ -1242,22 +1242,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); > > - /* MPRV does not affect the virtual-machine load/store > - instructions, HLV, HLVX, and HSV. */ > - if (mmuidx_2stage(mmu_idx)) { > - ; > - } else if (mode == PRV_M && access_type != MMU_INST_FETCH && > - get_field(env->mstatus, MSTATUS_MPRV)) { > - mode = get_field(env->mstatus, MSTATUS_MPP); > - if (riscv_has_ext(env, RVH) && get_field(env->mstatus, MSTATUS_MPV)) { > - two_stage_lookup = true; > - } > - } > - > pmu_tlb_fill_incr_ctr(cpu, access_type); > - if (riscv_cpu_virt_enabled(env) || > - ((mmuidx_2stage(mmu_idx) || two_stage_lookup) && > - access_type != MMU_INST_FETCH)) { > + if (two_stage_lookup) { > /* Two stage lookup */ > ret = get_physical_address(env, &pa, &prot, address, > &env->guest_phys_fault_addr, access_type, > @@ -1352,9 +1338,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, > return false; > } else { > raise_mmu_exception(env, address, access_type, pmp_violation, > - first_stage_error, > - riscv_cpu_virt_enabled(env) || > - mmuidx_2stage(mmu_idx), > + first_stage_error, two_stage_lookup, > two_stage_indirect_error); > cpu_loop_exit_restore(cs, retaddr); > } > diff --git a/target/riscv/csr.c b/target/riscv/csr.c > index b79758a606..1b635373c6 100644 > --- a/target/riscv/csr.c > +++ b/target/riscv/csr.c > @@ -1246,7 +1246,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, > RISCVMXL xl = riscv_cpu_mxl(env); > > /* flush tlb on mstatus fields that affect VM */ > - if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPV)) { > + if ((val ^ mstatus) & MSTATUS_MXR) { > tlb_flush(env_cpu(env)); > } > mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE | > @@ -1294,10 +1294,6 @@ static RISCVException write_mstatush(CPURISCVState *env, int csrno, > uint64_t valh = (uint64_t)val << 32; > uint64_t mask = MSTATUS_MPV | MSTATUS_GVA; > > - if ((valh ^ env->mstatus) & (MSTATUS_MPV)) { > - tlb_flush(env_cpu(env)); > - } > - > env->mstatus = (env->mstatus & ~mask) | (valh & mask); > > return RISCV_EXCP_NONE; > -- > 2.34.1 > >
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 0adfd4a12b..6c42f9c6fd 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -37,19 +37,21 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch) #ifdef CONFIG_USER_ONLY return 0; #else - if (ifetch) { - return env->priv; - } + bool virt = riscv_cpu_virt_enabled(env); + int mode = env->priv; /* All priv -> mmu_idx mapping are here */ - int mode = env->priv; - if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) { - mode = get_field(env->mstatus, MSTATUS_MPP); + if (!ifetch) { + if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) { + mode = get_field(env->mstatus, MSTATUS_MPP); + virt = get_field(env->mstatus, MSTATUS_MPV); + } + if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) { + mode = MMUIdx_S_SUM; + } } - if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) { - return MMUIdx_S_SUM; - } - return mode; + + return mode | (virt ? MMU_2STAGE_BIT : 0); #endif } @@ -1165,8 +1167,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, } env->badaddr = addr; - env->two_stage_lookup = riscv_cpu_virt_enabled(env) || - mmuidx_2stage(mmu_idx); + env->two_stage_lookup = mmuidx_2stage(mmu_idx); env->two_stage_indirect_lookup = false; cpu_loop_exit_restore(cs, retaddr); } @@ -1191,8 +1192,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, g_assert_not_reached(); } env->badaddr = addr; - env->two_stage_lookup = riscv_cpu_virt_enabled(env) || - mmuidx_2stage(mmu_idx); + env->two_stage_lookup = mmuidx_2stage(mmu_idx); env->two_stage_indirect_lookup = false; cpu_loop_exit_restore(cs, retaddr); } @@ -1230,7 +1230,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, int prot, prot2, prot_pmp; bool pmp_violation = false; bool first_stage_error = true; - bool two_stage_lookup = false; + bool two_stage_lookup = mmuidx_2stage(mmu_idx); bool two_stage_indirect_error = false; int ret = TRANSLATE_FAIL; int mode = mmu_idx; @@ -1242,22 +1242,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); - /* MPRV does not affect the virtual-machine load/store - instructions, HLV, HLVX, and HSV. */ - if (mmuidx_2stage(mmu_idx)) { - ; - } else if (mode == PRV_M && access_type != MMU_INST_FETCH && - get_field(env->mstatus, MSTATUS_MPRV)) { - mode = get_field(env->mstatus, MSTATUS_MPP); - if (riscv_has_ext(env, RVH) && get_field(env->mstatus, MSTATUS_MPV)) { - two_stage_lookup = true; - } - } - pmu_tlb_fill_incr_ctr(cpu, access_type); - if (riscv_cpu_virt_enabled(env) || - ((mmuidx_2stage(mmu_idx) || two_stage_lookup) && - access_type != MMU_INST_FETCH)) { + if (two_stage_lookup) { /* Two stage lookup */ ret = get_physical_address(env, &pa, &prot, address, &env->guest_phys_fault_addr, access_type, @@ -1352,9 +1338,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, return false; } else { raise_mmu_exception(env, address, access_type, pmp_violation, - first_stage_error, - riscv_cpu_virt_enabled(env) || - mmuidx_2stage(mmu_idx), + first_stage_error, two_stage_lookup, two_stage_indirect_error); cpu_loop_exit_restore(cs, retaddr); } diff --git a/target/riscv/csr.c b/target/riscv/csr.c index b79758a606..1b635373c6 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1246,7 +1246,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, RISCVMXL xl = riscv_cpu_mxl(env); /* flush tlb on mstatus fields that affect VM */ - if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPV)) { + if ((val ^ mstatus) & MSTATUS_MXR) { tlb_flush(env_cpu(env)); } mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE | @@ -1294,10 +1294,6 @@ static RISCVException write_mstatush(CPURISCVState *env, int csrno, uint64_t valh = (uint64_t)val << 32; uint64_t mask = MSTATUS_MPV | MSTATUS_GVA; - if ((valh ^ env->mstatus) & (MSTATUS_MPV)) { - tlb_flush(env_cpu(env)); - } - env->mstatus = (env->mstatus & ~mask) | (valh & mask); return RISCV_EXCP_NONE;
Incorporate the virt_enabled and MPV checks into the cpu_mmu_index function, so we don't have to keep doing it within tlb_fill and subroutines. This also elides a flush on changes to MPV. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/riscv/cpu_helper.c | 50 +++++++++++++-------------------------- target/riscv/csr.c | 6 +---- 2 files changed, 18 insertions(+), 38 deletions(-)