From 696bacde957bc5cdabc7710abc316ef56184d928 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 12 Apr 2023 13:43:24 +0200 Subject: [PATCH] target/riscv: Set MMU_2STAGE_BIT in riscv_cpu_mmu_index 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 Reviewed-by: Alistair Francis Reviewed-by: Weiwei Li Tested-by: Daniel Henrique Barboza Message-Id: <20230325105429.1142530-17-richard.henderson@linaro.org> Message-Id: <20230412114333.118895-17-richard.henderson@linaro.org> Signed-off-by: Alistair Francis --- target/riscv/cpu_helper.c | 49 ++++++++++++++------------------------- target/riscv/csr.c | 6 +---- 2 files changed, 18 insertions(+), 37 deletions(-) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index ccba3c45e7..baa4b3a1d2 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 = env->virt_enabled; + 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 } @@ -1162,7 +1164,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, } env->badaddr = addr; - env->two_stage_lookup = env->virt_enabled || mmuidx_2stage(mmu_idx); + env->two_stage_lookup = mmuidx_2stage(mmu_idx); env->two_stage_indirect_lookup = false; cpu_loop_exit_restore(cs, retaddr); } @@ -1187,7 +1189,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, g_assert_not_reached(); } env->badaddr = addr; - env->two_stage_lookup = env->virt_enabled || mmuidx_2stage(mmu_idx); + env->two_stage_lookup = mmuidx_2stage(mmu_idx); env->two_stage_indirect_lookup = false; cpu_loop_exit_restore(cs, retaddr); } @@ -1225,7 +1227,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; @@ -1237,24 +1239,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 (env->virt_enabled || - ((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, @@ -1350,8 +1336,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, - env->virt_enabled || 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 4a4d852bd1..865ee9efda 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1294,7 +1294,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, val = legalize_mpp(env, get_field(mstatus, MSTATUS_MPP), val); /* 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 | @@ -1342,10 +1342,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;