From bd81c057ed1511246b09c832a8cfaa6789743c84 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 8 Mar 2021 15:03:13 -0500 Subject: [PATCH] target/riscv: Remove the HS_TWO_STAGE flag The HS_TWO_STAGE flag is no longer required as the MMU index contains the information if we are performing a two stage access. Backports 1c1c060aa866986ef8b7eb334abbb8c104a46e5c --- qemu/header_gen.py | 1 - qemu/riscv32.h | 1 - qemu/riscv64.h | 1 - qemu/target/riscv/cpu.h | 3 +- qemu/target/riscv/cpu_bits.h | 1 - qemu/target/riscv/cpu_helper.c | 60 ++++++++++++++-------------------- qemu/target/riscv/op_helper.c | 11 ------- 7 files changed, 25 insertions(+), 53 deletions(-) diff --git a/qemu/header_gen.py b/qemu/header_gen.py index d8306fd3..7486cb27 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -7324,7 +7324,6 @@ riscv_symbols = ( 'riscv_cpu_set_force_hs_excep', 'riscv_cpu_set_mode', 'riscv_cpu_set_rdtime_fn', - 'riscv_cpu_set_two_stage_lookup', 'riscv_cpu_set_virt_enabled', 'riscv_cpu_swap_hypervisor_regs', 'riscv_cpu_tlb_fill', diff --git a/qemu/riscv32.h b/qemu/riscv32.h index dac20744..33bfa60b 100644 --- a/qemu/riscv32.h +++ b/qemu/riscv32.h @@ -4760,7 +4760,6 @@ #define riscv_cpu_set_force_hs_excep riscv_cpu_set_force_hs_excep_riscv32 #define riscv_cpu_set_mode riscv_cpu_set_mode_riscv32 #define riscv_cpu_set_rdtime_fn riscv_cpu_set_rdtime_fn_riscv32 -#define riscv_cpu_set_two_stage_lookup riscv_cpu_set_two_stage_lookup_riscv32 #define riscv_cpu_set_virt_enabled riscv_cpu_set_virt_enabled_riscv32 #define riscv_cpu_swap_hypervisor_regs riscv_cpu_swap_hypervisor_regs_riscv32 #define riscv_cpu_tlb_fill riscv_cpu_tlb_fill_riscv32 diff --git a/qemu/riscv64.h b/qemu/riscv64.h index 99f3dcbb..d6fe4f8b 100644 --- a/qemu/riscv64.h +++ b/qemu/riscv64.h @@ -4760,7 +4760,6 @@ #define riscv_cpu_set_force_hs_excep riscv_cpu_set_force_hs_excep_riscv64 #define riscv_cpu_set_mode riscv_cpu_set_mode_riscv64 #define riscv_cpu_set_rdtime_fn riscv_cpu_set_rdtime_fn_riscv64 -#define riscv_cpu_set_two_stage_lookup riscv_cpu_set_two_stage_lookup_riscv64 #define riscv_cpu_set_virt_enabled riscv_cpu_set_virt_enabled_riscv64 #define riscv_cpu_swap_hypervisor_regs riscv_cpu_swap_hypervisor_regs_riscv64 #define riscv_cpu_tlb_fill riscv_cpu_tlb_fill_riscv64 diff --git a/qemu/target/riscv/cpu.h b/qemu/target/riscv/cpu.h index 7f86d438..43bf0046 100644 --- a/qemu/target/riscv/cpu.h +++ b/qemu/target/riscv/cpu.h @@ -328,8 +328,7 @@ bool riscv_cpu_virt_enabled(CPURISCVState *env); void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable); bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env); void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable); -bool riscv_cpu_two_stage_lookup(CPURISCVState *env); -void riscv_cpu_set_two_stage_lookup(CPURISCVState *env, bool enable); +bool riscv_cpu_two_stage_lookup(int mmu_idx); int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch); hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, diff --git a/qemu/target/riscv/cpu_bits.h b/qemu/target/riscv/cpu_bits.h index 4a573223..53a25b04 100644 --- a/qemu/target/riscv/cpu_bits.h +++ b/qemu/target/riscv/cpu_bits.h @@ -469,7 +469,6 @@ * page table fault. */ #define FORCE_HS_EXCEP 2 -#define HS_TWO_STAGE 4 /* RV32 satp CSR field masks */ #define SATP32_MODE 0x80000000 diff --git a/qemu/target/riscv/cpu_helper.c b/qemu/target/riscv/cpu_helper.c index 68055fe9..4a63457d 100644 --- a/qemu/target/riscv/cpu_helper.c +++ b/qemu/target/riscv/cpu_helper.c @@ -207,22 +207,9 @@ void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable) env->virt = set_field(env->virt, FORCE_HS_EXCEP, enable); } -bool riscv_cpu_two_stage_lookup(CPURISCVState *env) +bool riscv_cpu_two_stage_lookup(int mmu_idx) { - if (!riscv_has_ext(env, RVH)) { - return false; - } - - return get_field(env->virt, HS_TWO_STAGE); -} - -void riscv_cpu_set_two_stage_lookup(CPURISCVState *env, bool enable) -{ - if (!riscv_has_ext(env, RVH)) { - return; - } - - env->virt = set_field(env->virt, HS_TWO_STAGE, enable); + return mmu_idx & TB_FLAGS_PRIV_HYP_ACCESS_MASK; } int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts) @@ -327,7 +314,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical, * was called. Background registers will be used if the guest has * forced a two stage translation to be on (in HS or M mode). */ - if (riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH) { + if (!riscv_cpu_virt_enabled(env) && riscv_cpu_two_stage_lookup(mmu_idx)) { use_background = true; } @@ -566,7 +553,7 @@ restart: static void raise_mmu_exception(CPURISCVState *env, target_ulong address, MMUAccessType access_type, bool pmp_violation, - bool first_stage) + bool first_stage, bool two_stage) { CPUState *cs = env_cpu(env); int page_fault_exceptions; @@ -589,8 +576,7 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address, } break; case MMU_DATA_LOAD: - if ((riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(env)) && - !first_stage) { + if (two_stage && !first_stage) { cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT; } else { cs->exception_index = page_fault_exceptions ? @@ -598,8 +584,7 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address, } break; case MMU_DATA_STORE: - if ((riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(env)) && - !first_stage) { + if (two_stage && !first_stage) { cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT; } else { cs->exception_index = page_fault_exceptions ? @@ -687,6 +672,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, int prot, prot2; bool pmp_violation = false; bool first_stage_error = true; + bool two_stage_lookup = false; int ret = TRANSLATE_FAIL; int mode = mmu_idx; target_ulong tlb_size = 0; @@ -706,11 +692,12 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, access_type != MMU_INST_FETCH && get_field(env->mstatus, MSTATUS_MPRV) && get_field(env->mstatus, MSTATUS_MPV)) { - riscv_cpu_set_two_stage_lookup(env, true); + two_stage_lookup = true; } if (riscv_cpu_virt_enabled(env) || - (riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH)) { + ((riscv_cpu_two_stage_lookup(mmu_idx) || two_stage_lookup) && + access_type != MMU_INST_FETCH)) { /* Two stage lookup */ ret = get_physical_address(env, &pa, &prot, address, &env->guest_phys_fault_addr, access_type, @@ -773,14 +760,6 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, __func__, address, ret, pa, prot); } - /* We did the two stage lookup based on MPRV, unset the lookup */ - if (riscv_has_ext(env, RVH) && env->priv == PRV_M && - access_type != MMU_INST_FETCH && - get_field(env->mstatus, MSTATUS_MPRV) && - get_field(env->mstatus, MSTATUS_MPV)) { - riscv_cpu_set_two_stage_lookup(env, false); - } - if (riscv_feature(env, RISCV_FEATURE_PMP) && (ret == TRANSLATE_SUCCESS) && !pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) { @@ -802,7 +781,10 @@ 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, first_stage_error); + raise_mmu_exception(env, address, access_type, pmp_violation, + first_stage_error, + riscv_cpu_virt_enabled(env) || + riscv_cpu_two_stage_lookup(mmu_idx)); riscv_raise_exception(env, cs->exception_index, retaddr); } @@ -902,9 +884,16 @@ void riscv_cpu_do_interrupt(CPUState *cs) /* handle the trap in S-mode */ if (riscv_has_ext(env, RVH)) { target_ulong hdeleg = async ? env->hideleg : env->hedeleg; + bool two_stage_lookup = false; - if ((riscv_cpu_virt_enabled(env) || - riscv_cpu_two_stage_lookup(env)) && write_tval) { + if (env->priv == PRV_M || + (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || + (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && + get_field(env->hstatus, HSTATUS_HU))) { + two_stage_lookup = true; + } + + if ((riscv_cpu_virt_enabled(env) || two_stage_lookup) && write_tval) { /* * If we are writing a guest virtual address to stval, set * this to 1. If we are trapping to VS we will set this to 0 @@ -942,11 +931,10 @@ void riscv_cpu_do_interrupt(CPUState *cs) riscv_cpu_set_force_hs_excep(env, 0); } else { /* Trap into HS mode */ - if (!riscv_cpu_two_stage_lookup(env)) { + if (!two_stage_lookup) { env->hstatus = set_field(env->hstatus, HSTATUS_SPV, riscv_cpu_virt_enabled(env)); } - riscv_cpu_set_two_stage_lookup(env, false); htval = env->guest_phys_fault_addr; } } diff --git a/qemu/target/riscv/op_helper.c b/qemu/target/riscv/op_helper.c index 6d104b78..0b200241 100644 --- a/qemu/target/riscv/op_helper.c +++ b/qemu/target/riscv/op_helper.c @@ -237,8 +237,6 @@ target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address, target_ulong pte; int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; - riscv_cpu_set_two_stage_lookup(env, true); - switch (memop) { case MO_SB: pte = cpu_ldsb_mmuidx_ra(env, address, mmu_idx, GETPC()); @@ -265,8 +263,6 @@ target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address, g_assert_not_reached(); } - riscv_cpu_set_two_stage_lookup(env, false); - return pte; } @@ -286,7 +282,6 @@ void helper_hyp_store(CPURISCVState *env, target_ulong address, (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && get_field(env->hstatus, HSTATUS_HU))) { int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; - riscv_cpu_set_two_stage_lookup(env, true); switch (memop) { case MO_SB: @@ -308,8 +303,6 @@ void helper_hyp_store(CPURISCVState *env, target_ulong address, g_assert_not_reached(); } - riscv_cpu_set_two_stage_lookup(env, false); - return; } @@ -330,8 +323,6 @@ target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, target_ulong pte; int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; - riscv_cpu_set_two_stage_lookup(env, true); - switch (memop) { case MO_TEUW: pte = cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC()); @@ -343,8 +334,6 @@ target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, g_assert_not_reached(); } - riscv_cpu_set_two_stage_lookup(env, false); - return pte; }