From 4762dcda3cca4683f74c562a948509bf3fb58bde Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 8 Mar 2021 15:11:09 -0500 Subject: [PATCH] target/riscv: Remove the hyp load and store functions Remove the special Virtulisation load and store functions and just use the standard tcg tcg_gen_qemu_ld_tl() and tcg_gen_qemu_st_tl() functions instead. As part of this change we ensure we still run an access check to make sure we can perform the operations. Backports 743077b35b1ed88ed243daefafe9403d88a958f6 --- qemu/header_gen.py | 2 - qemu/riscv32.h | 2 - qemu/riscv64.h | 2 - qemu/target/riscv/cpu.h | 12 ++ qemu/target/riscv/helper.h | 2 - qemu/target/riscv/insn_trans/trans_rvh.inc.c | 133 +++++++------------ qemu/target/riscv/op_helper.c | 86 ------------ qemu/target/riscv/translate.c | 2 + 8 files changed, 59 insertions(+), 182 deletions(-) diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 7486cb27..66b5c986 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -6260,8 +6260,6 @@ riscv_symbols = ( 'helper_fsub_d', 'helper_fsub_s', 'helper_hyp_gvma_tlb_flush', - 'helper_hyp_load', - 'helper_hyp_store', 'helper_hyp_tlb_flush', 'helper_hyp_x_load', 'helper_mret', diff --git a/qemu/riscv32.h b/qemu/riscv32.h index 33bfa60b..465221ac 100644 --- a/qemu/riscv32.h +++ b/qemu/riscv32.h @@ -3696,8 +3696,6 @@ #define helper_fsub_d helper_fsub_d_riscv32 #define helper_fsub_s helper_fsub_s_riscv32 #define helper_hyp_gvma_tlb_flush helper_hyp_gvma_tlb_flush_riscv32 -#define helper_hyp_load helper_hyp_load_riscv32 -#define helper_hyp_store helper_hyp_store_riscv32 #define helper_hyp_tlb_flush helper_hyp_tlb_flush_riscv32 #define helper_hyp_x_load helper_hyp_x_load_riscv32 #define helper_mret helper_mret_riscv32 diff --git a/qemu/riscv64.h b/qemu/riscv64.h index d6fe4f8b..f7ebd14c 100644 --- a/qemu/riscv64.h +++ b/qemu/riscv64.h @@ -3696,8 +3696,6 @@ #define helper_fsub_d helper_fsub_d_riscv64 #define helper_fsub_s helper_fsub_s_riscv64 #define helper_hyp_gvma_tlb_flush helper_hyp_gvma_tlb_flush_riscv64 -#define helper_hyp_load helper_hyp_load_riscv64 -#define helper_hyp_store helper_hyp_store_riscv64 #define helper_hyp_tlb_flush helper_hyp_tlb_flush_riscv64 #define helper_hyp_x_load helper_hyp_x_load_riscv64 #define helper_mret helper_mret_riscv64 diff --git a/qemu/target/riscv/cpu.h b/qemu/target/riscv/cpu.h index 43bf0046..29f5f383 100644 --- a/qemu/target/riscv/cpu.h +++ b/qemu/target/riscv/cpu.h @@ -377,6 +377,8 @@ FIELD(TB_FLAGS, VL_EQ_VLMAX, 2, 1) FIELD(TB_FLAGS, LMUL, 3, 2) FIELD(TB_FLAGS, SEW, 5, 3) FIELD(TB_FLAGS, VILL, 8, 1) +/* Is a Hypervisor instruction load/store allowed? */ +FIELD(TB_FLAGS, HLSX, 9, 1) /* * A simplification for VLMAX @@ -423,7 +425,17 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, if (riscv_cpu_fp_enabled(env)) { flags |= env->mstatus & MSTATUS_FS; } + + if (riscv_has_ext(env, RVH)) { + 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))) { + flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1); + } + } #endif + *pflags = flags; } diff --git a/qemu/target/riscv/helper.h b/qemu/target/riscv/helper.h index 7341279a..b191b41f 100644 --- a/qemu/target/riscv/helper.h +++ b/qemu/target/riscv/helper.h @@ -84,8 +84,6 @@ DEF_HELPER_1(tlb_flush, void, env) #ifndef CONFIG_USER_ONLY DEF_HELPER_1(hyp_tlb_flush, void, env) DEF_HELPER_1(hyp_gvma_tlb_flush, void, env) -DEF_HELPER_4(hyp_load, tl, env, tl, tl, tl) -DEF_HELPER_5(hyp_store, void, env, tl, tl, tl, tl) DEF_HELPER_4(hyp_x_load, tl, env, tl, tl, tl) #endif diff --git a/qemu/target/riscv/insn_trans/trans_rvh.inc.c b/qemu/target/riscv/insn_trans/trans_rvh.inc.c index bb972909..2c87bedb 100644 --- a/qemu/target/riscv/insn_trans/trans_rvh.inc.c +++ b/qemu/target/riscv/insn_trans/trans_rvh.inc.c @@ -16,6 +16,18 @@ * this program. If not, see . */ +#ifndef CONFIG_USER_ONLY +static void check_access(DisasContext *ctx) { + if (!ctx->hlsx) { + if (ctx->virt_enabled) { + generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT); + } else { + generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); + } + } +} +#endif + static bool trans_hlv_b(DisasContext *ctx, arg_hlv_b *a) { REQUIRE_EXT(ctx, RVH); @@ -23,20 +35,15 @@ static bool trans_hlv_b(DisasContext *ctx, arg_hlv_b *a) TCGContext *tcg_ctx = ctx->uc->tcg_ctx; TCGv t0 = tcg_temp_new(tcg_ctx); TCGv t1 = tcg_temp_new(tcg_ctx); - TCGv mem_idx = tcg_temp_new(tcg_ctx); - TCGv memop = tcg_temp_new(tcg_ctx); + + check_access(ctx); gen_get_gpr(ctx, t0, a->rs1); - tcg_gen_movi_tl(tcg_ctx, mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(tcg_ctx, memop, MO_SB); - - gen_helper_hyp_load(tcg_ctx, t1, tcg_ctx->cpu_env, t0, mem_idx, memop); + tcg_gen_qemu_ld_tl(ctx->uc, t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_SB); gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(tcg_ctx, t0); tcg_temp_free(tcg_ctx, t1); - tcg_temp_free(tcg_ctx, mem_idx); - tcg_temp_free(tcg_ctx, memop); return true; #else return false; @@ -50,20 +57,15 @@ static bool trans_hlv_h(DisasContext *ctx, arg_hlv_h *a) TCGContext *tcg_ctx = ctx->uc->tcg_ctx; TCGv t0 = tcg_temp_new(tcg_ctx); TCGv t1 = tcg_temp_new(tcg_ctx); - TCGv mem_idx = tcg_temp_new(tcg_ctx); - TCGv memop = tcg_temp_new(tcg_ctx); + + check_access(ctx); gen_get_gpr(ctx, t0, a->rs1); - tcg_gen_movi_tl(tcg_ctx, mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(tcg_ctx, memop, MO_TESW); - - gen_helper_hyp_load(tcg_ctx, t1, tcg_ctx->cpu_env, t0, mem_idx, memop); + tcg_gen_qemu_ld_tl(ctx->uc, t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESW); gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(tcg_ctx, t0); tcg_temp_free(tcg_ctx, t1); - tcg_temp_free(tcg_ctx, mem_idx); - tcg_temp_free(tcg_ctx, memop); return true; #else return false; @@ -77,20 +79,15 @@ static bool trans_hlv_w(DisasContext *ctx, arg_hlv_w *a) TCGContext *tcg_ctx = ctx->uc->tcg_ctx; TCGv t0 = tcg_temp_new(tcg_ctx); TCGv t1 = tcg_temp_new(tcg_ctx); - TCGv mem_idx = tcg_temp_new(tcg_ctx); - TCGv memop = tcg_temp_new(tcg_ctx); + + check_access(ctx); gen_get_gpr(ctx, t0, a->rs1); - tcg_gen_movi_tl(tcg_ctx, mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(tcg_ctx, memop, MO_TESL); - - gen_helper_hyp_load(tcg_ctx, t1, tcg_ctx->cpu_env, t0, mem_idx, memop); + tcg_gen_qemu_ld_tl(ctx->uc, t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESL); gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(tcg_ctx, t0); tcg_temp_free(tcg_ctx, t1); - tcg_temp_free(tcg_ctx, mem_idx); - tcg_temp_free(tcg_ctx, memop); return true; #else return false; @@ -104,20 +101,15 @@ static bool trans_hlv_bu(DisasContext *ctx, arg_hlv_bu *a) TCGContext *tcg_ctx = ctx->uc->tcg_ctx; TCGv t0 = tcg_temp_new(tcg_ctx); TCGv t1 = tcg_temp_new(tcg_ctx); - TCGv mem_idx = tcg_temp_new(tcg_ctx); - TCGv memop = tcg_temp_new(tcg_ctx); + + check_access(ctx); gen_get_gpr(ctx, t0, a->rs1); - tcg_gen_movi_tl(tcg_ctx, mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(tcg_ctx, memop, MO_UB); - - gen_helper_hyp_load(tcg_ctx, t1, tcg_ctx->cpu_env, t0, mem_idx, memop); + tcg_gen_qemu_ld_tl(ctx->uc, t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_UB); gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(tcg_ctx, t0); tcg_temp_free(tcg_ctx, t1); - tcg_temp_free(tcg_ctx, mem_idx); - tcg_temp_free(tcg_ctx, memop); return true; #else return false; @@ -131,20 +123,15 @@ static bool trans_hlv_hu(DisasContext *ctx, arg_hlv_hu *a) TCGContext *tcg_ctx = ctx->uc->tcg_ctx; TCGv t0 = tcg_temp_new(tcg_ctx); TCGv t1 = tcg_temp_new(tcg_ctx); - TCGv mem_idx = tcg_temp_new(tcg_ctx); - TCGv memop = tcg_temp_new(tcg_ctx); + + check_access(ctx); gen_get_gpr(ctx, t0, a->rs1); - tcg_gen_movi_tl(tcg_ctx, mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(tcg_ctx, memop, MO_TEUW); - - gen_helper_hyp_load(tcg_ctx, t1, tcg_ctx->cpu_env, t0, mem_idx, memop); + tcg_gen_qemu_ld_tl(ctx->uc, t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEUW); gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(tcg_ctx, t0); tcg_temp_free(tcg_ctx, t1); - tcg_temp_free(tcg_ctx, mem_idx); - tcg_temp_free(tcg_ctx, memop); return true; #else return false; @@ -158,20 +145,15 @@ static bool trans_hsv_b(DisasContext *ctx, arg_hsv_b *a) TCGContext *tcg_ctx = ctx->uc->tcg_ctx; TCGv t0 = tcg_temp_new(tcg_ctx); TCGv dat = tcg_temp_new(tcg_ctx); - TCGv mem_idx = tcg_temp_new(tcg_ctx); - TCGv memop = tcg_temp_new(tcg_ctx); + + check_access(ctx); gen_get_gpr(ctx, t0, a->rs1); gen_get_gpr(ctx, dat, a->rs2); - tcg_gen_movi_tl(tcg_ctx, mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(tcg_ctx, memop, MO_SB); - - gen_helper_hyp_store(tcg_ctx, tcg_ctx->cpu_env, t0, dat, mem_idx, memop); + tcg_gen_qemu_st_tl(ctx->uc, dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_SB); tcg_temp_free(tcg_ctx, t0); tcg_temp_free(tcg_ctx, dat); - tcg_temp_free(tcg_ctx, mem_idx); - tcg_temp_free(tcg_ctx, memop); return true; #else return false; @@ -185,20 +167,15 @@ static bool trans_hsv_h(DisasContext *ctx, arg_hsv_h *a) TCGContext *tcg_ctx = ctx->uc->tcg_ctx; TCGv t0 = tcg_temp_new(tcg_ctx); TCGv dat = tcg_temp_new(tcg_ctx); - TCGv mem_idx = tcg_temp_new(tcg_ctx); - TCGv memop = tcg_temp_new(tcg_ctx); + + check_access(ctx); gen_get_gpr(ctx, t0, a->rs1); gen_get_gpr(ctx, dat, a->rs2); - tcg_gen_movi_tl(tcg_ctx, mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(tcg_ctx, memop, MO_TESW); - - gen_helper_hyp_store(tcg_ctx, tcg_ctx->cpu_env, t0, dat, mem_idx, memop); + tcg_gen_qemu_st_tl(ctx->uc, dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESW); tcg_temp_free(tcg_ctx, t0); tcg_temp_free(tcg_ctx, dat); - tcg_temp_free(tcg_ctx, mem_idx); - tcg_temp_free(tcg_ctx, memop); return true; #else return false; @@ -212,20 +189,15 @@ static bool trans_hsv_w(DisasContext *ctx, arg_hsv_w *a) TCGContext *tcg_ctx = ctx->uc->tcg_ctx; TCGv t0 = tcg_temp_new(tcg_ctx); TCGv dat = tcg_temp_new(tcg_ctx); - TCGv mem_idx = tcg_temp_new(tcg_ctx); - TCGv memop = tcg_temp_new(tcg_ctx); + + check_access(ctx); gen_get_gpr(ctx, t0, a->rs1); gen_get_gpr(ctx, dat, a->rs2); - tcg_gen_movi_tl(tcg_ctx, mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(tcg_ctx, memop, MO_TESL); - - gen_helper_hyp_store(tcg_ctx, tcg_ctx->cpu_env, t0, dat, mem_idx, memop); + tcg_gen_qemu_st_tl(ctx->uc, dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESL); tcg_temp_free(tcg_ctx, t0); tcg_temp_free(tcg_ctx, dat); - tcg_temp_free(tcg_ctx, mem_idx); - tcg_temp_free(tcg_ctx, memop); return true; #else return false; @@ -240,20 +212,15 @@ static bool trans_hlv_wu(DisasContext *ctx, arg_hlv_wu *a) TCGContext *tcg_ctx = ctx->uc->tcg_ctx; TCGv t0 = tcg_temp_new(tcg_ctx); TCGv t1 = tcg_temp_new(tcg_ctx); - TCGv mem_idx = tcg_temp_new(tcg_ctx); - TCGv memop = tcg_temp_new(tcg_ctx); + + check_access(ctx); gen_get_gpr(ctx, t0, a->rs1); - tcg_gen_movi_tl(tcg_ctx, mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(tcg_ctx, memop, MO_TEUL); - - gen_helper_hyp_load(tcg_ctx, t1, tcg_ctx->cpu_env, t0, mem_idx, memop); + tcg_gen_qemu_ld_tl(ctx->uc, t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEUL); gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(tcg_ctx, t0); tcg_temp_free(tcg_ctx, t1); - tcg_temp_free(tcg_ctx, mem_idx); - tcg_temp_free(tcg_ctx, memop); return true; #else return false; @@ -267,20 +234,15 @@ static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a) TCGContext *tcg_ctx = ctx->uc->tcg_ctx; TCGv t0 = tcg_temp_new(tcg_ctx); TCGv t1 = tcg_temp_new(tcg_ctx); - TCGv mem_idx = tcg_temp_new(tcg_ctx); - TCGv memop = tcg_temp_new(tcg_ctx); + + check_access(ctx); gen_get_gpr(ctx, t0, a->rs1); - tcg_gen_movi_tl(tcg_ctx, mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(tcg_ctx, memop, MO_TEQ); - - gen_helper_hyp_load(tcg_ctx, t1, tcg_ctx->cpu_env, t0, mem_idx, memop); + tcg_gen_qemu_ld_tl(ctx->uc, t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEQ); gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(tcg_ctx, t0); tcg_temp_free(tcg_ctx, t1); - tcg_temp_free(tcg_ctx, mem_idx); - tcg_temp_free(tcg_ctx, memop); return true; #else return false; @@ -294,20 +256,15 @@ static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a) TCGContext *tcg_ctx = ctx->uc->tcg_ctx; TCGv t0 = tcg_temp_new(tcg_ctx); TCGv dat = tcg_temp_new(tcg_ctx); - TCGv mem_idx = tcg_temp_new(tcg_ctx); - TCGv memop = tcg_temp_new(tcg_ctx); + + check_access(ctx); gen_get_gpr(ctx, t0, a->rs1); gen_get_gpr(ctx, dat, a->rs2); - tcg_gen_movi_tl(tcg_ctx, mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(tcg_ctx, memop, MO_TEQ); - - gen_helper_hyp_store(tcg_ctx, tcg_ctx->cpu_env, t0, dat, mem_idx, memop); + tcg_gen_qemu_st_tl(ctx->uc, dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEQ); tcg_temp_free(tcg_ctx, t0); tcg_temp_free(tcg_ctx, dat); - tcg_temp_free(tcg_ctx, mem_idx); - tcg_temp_free(tcg_ctx, memop); return true; #else return false; diff --git a/qemu/target/riscv/op_helper.c b/qemu/target/riscv/op_helper.c index 0b200241..5cba7e6d 100644 --- a/qemu/target/riscv/op_helper.c +++ b/qemu/target/riscv/op_helper.c @@ -227,92 +227,6 @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env) helper_hyp_tlb_flush(env); } -target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address, - target_ulong attrs, target_ulong memop) -{ - 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))) { - target_ulong pte; - int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; - - switch (memop) { - case MO_SB: - pte = cpu_ldsb_mmuidx_ra(env, address, mmu_idx, GETPC()); - break; - case MO_UB: - pte = cpu_ldub_mmuidx_ra(env, address, mmu_idx, GETPC()); - break; - case MO_TESW: - pte = cpu_ldsw_mmuidx_ra(env, address, mmu_idx, GETPC()); - break; - case MO_TEUW: - pte = cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC()); - break; - case MO_TESL: - pte = cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC()); - break; - case MO_TEUL: - pte = cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC()); - break; - case MO_TEQ: - pte = cpu_ldq_mmuidx_ra(env, address, mmu_idx, GETPC()); - break; - default: - g_assert_not_reached(); - } - - return pte; - } - - if (riscv_cpu_virt_enabled(env)) { - riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); - } else { - riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); - } - return 0; -} - -void helper_hyp_store(CPURISCVState *env, target_ulong address, - target_ulong val, target_ulong attrs, target_ulong memop) -{ - 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))) { - int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; - - switch (memop) { - case MO_SB: - case MO_UB: - cpu_stb_mmuidx_ra(env, address, val, mmu_idx, GETPC()); - break; - case MO_TESW: - case MO_TEUW: - cpu_stw_mmuidx_ra(env, address, val, mmu_idx, GETPC()); - break; - case MO_TESL: - case MO_TEUL: - cpu_stl_mmuidx_ra(env, address, val, mmu_idx, GETPC()); - break; - case MO_TEQ: - cpu_stq_mmuidx_ra(env, address, val, mmu_idx, GETPC()); - break; - default: - g_assert_not_reached(); - } - - return; - } - - if (riscv_cpu_virt_enabled(env)) { - riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); - } else { - riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); - } -} - target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, target_ulong attrs, target_ulong memop) { diff --git a/qemu/target/riscv/translate.c b/qemu/target/riscv/translate.c index df254360..e0f2d24e 100644 --- a/qemu/target/riscv/translate.c +++ b/qemu/target/riscv/translate.c @@ -54,6 +54,7 @@ typedef struct DisasContext { to reset this known value. */ int frm; bool ext_ifencei; + bool hlsx; /* vector extension */ bool vill; uint8_t lmul; @@ -838,6 +839,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->frm = -1; /* unknown rounding mode */ ctx->ext_ifencei = cpu->cfg.ext_ifencei; ctx->vlen = cpu->cfg.vlen; + ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX); ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL); ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW); ctx->lmul = FIELD_EX32(tb_flags, TB_FLAGS, LMUL);