@@ -81,8 +81,7 @@ 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_1(hyp_access_check, void, env)
DEF_HELPER_4(hyp_x_load, tl, env, tl, tl, tl)
#endif
@@ -230,82 +230,12 @@ 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)
+void helper_hyp_access_check(CPURISCVState *env)
{
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;
}
@@ -22,20 +22,16 @@ static bool trans_hlv_b(DisasContext *ctx, arg_hlv_b *a)
#ifndef CONFIG_USER_ONLY
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
- TCGv mem_idx = tcg_temp_new();
- TCGv memop = tcg_temp_new();
+
+ gen_helper_hyp_access_check(cpu_env);
gen_get_gpr(t0, a->rs1);
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
- tcg_gen_movi_tl(memop, MO_SB);
- gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_SB);
gen_set_gpr(a->rd, t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- tcg_temp_free(mem_idx);
- tcg_temp_free(memop);
return true;
#else
return false;
@@ -48,20 +44,16 @@ static bool trans_hlv_h(DisasContext *ctx, arg_hlv_h *a)
#ifndef CONFIG_USER_ONLY
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
- TCGv mem_idx = tcg_temp_new();
- TCGv memop = tcg_temp_new();
+
+ gen_helper_hyp_access_check(cpu_env);
gen_get_gpr(t0, a->rs1);
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
- tcg_gen_movi_tl(memop, MO_TESW);
- gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESW);
gen_set_gpr(a->rd, t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- tcg_temp_free(mem_idx);
- tcg_temp_free(memop);
return true;
#else
return false;
@@ -74,20 +66,16 @@ static bool trans_hlv_w(DisasContext *ctx, arg_hlv_w *a)
#ifndef CONFIG_USER_ONLY
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
- TCGv mem_idx = tcg_temp_new();
- TCGv memop = tcg_temp_new();
+
+ gen_helper_hyp_access_check(cpu_env);
gen_get_gpr(t0, a->rs1);
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
- tcg_gen_movi_tl(memop, MO_TESL);
- gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESL);
gen_set_gpr(a->rd, t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- tcg_temp_free(mem_idx);
- tcg_temp_free(memop);
return true;
#else
return false;
@@ -100,20 +88,16 @@ static bool trans_hlv_bu(DisasContext *ctx, arg_hlv_bu *a)
#ifndef CONFIG_USER_ONLY
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
- TCGv mem_idx = tcg_temp_new();
- TCGv memop = tcg_temp_new();
+
+ gen_helper_hyp_access_check(cpu_env);
gen_get_gpr(t0, a->rs1);
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
- tcg_gen_movi_tl(memop, MO_UB);
- gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_UB);
gen_set_gpr(a->rd, t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- tcg_temp_free(mem_idx);
- tcg_temp_free(memop);
return true;
#else
return false;
@@ -126,20 +110,15 @@ static bool trans_hlv_hu(DisasContext *ctx, arg_hlv_hu *a)
#ifndef CONFIG_USER_ONLY
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
- TCGv mem_idx = tcg_temp_new();
- TCGv memop = tcg_temp_new();
- gen_get_gpr(t0, a->rs1);
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
- tcg_gen_movi_tl(memop, MO_TEUW);
+ gen_helper_hyp_access_check(cpu_env);
- gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
+ gen_get_gpr(t0, a->rs1);
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEUW);
gen_set_gpr(a->rd, t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- tcg_temp_free(mem_idx);
- tcg_temp_free(memop);
return true;
#else
return false;
@@ -152,20 +131,16 @@ static bool trans_hsv_b(DisasContext *ctx, arg_hsv_b *a)
#ifndef CONFIG_USER_ONLY
TCGv t0 = tcg_temp_new();
TCGv dat = tcg_temp_new();
- TCGv mem_idx = tcg_temp_new();
- TCGv memop = tcg_temp_new();
+
+ gen_helper_hyp_access_check(cpu_env);
gen_get_gpr(t0, a->rs1);
gen_get_gpr(dat, a->rs2);
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
- tcg_gen_movi_tl(memop, MO_SB);
- gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop);
+ tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_SB);
tcg_temp_free(t0);
tcg_temp_free(dat);
- tcg_temp_free(mem_idx);
- tcg_temp_free(memop);
return true;
#else
return false;
@@ -178,20 +153,16 @@ static bool trans_hsv_h(DisasContext *ctx, arg_hsv_h *a)
#ifndef CONFIG_USER_ONLY
TCGv t0 = tcg_temp_new();
TCGv dat = tcg_temp_new();
- TCGv mem_idx = tcg_temp_new();
- TCGv memop = tcg_temp_new();
+
+ gen_helper_hyp_access_check(cpu_env);
gen_get_gpr(t0, a->rs1);
gen_get_gpr(dat, a->rs2);
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
- tcg_gen_movi_tl(memop, MO_TESW);
- gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop);
+ tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESW);
tcg_temp_free(t0);
tcg_temp_free(dat);
- tcg_temp_free(mem_idx);
- tcg_temp_free(memop);
return true;
#else
return false;
@@ -204,20 +175,16 @@ static bool trans_hsv_w(DisasContext *ctx, arg_hsv_w *a)
#ifndef CONFIG_USER_ONLY
TCGv t0 = tcg_temp_new();
TCGv dat = tcg_temp_new();
- TCGv mem_idx = tcg_temp_new();
- TCGv memop = tcg_temp_new();
+
+ gen_helper_hyp_access_check(cpu_env);
gen_get_gpr(t0, a->rs1);
gen_get_gpr(dat, a->rs2);
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
- tcg_gen_movi_tl(memop, MO_TESL);
- gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop);
+ tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESL);
tcg_temp_free(t0);
tcg_temp_free(dat);
- tcg_temp_free(mem_idx);
- tcg_temp_free(memop);
return true;
#else
return false;
@@ -231,20 +198,16 @@ static bool trans_hlv_wu(DisasContext *ctx, arg_hlv_wu *a)
#ifndef CONFIG_USER_ONLY
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
- TCGv mem_idx = tcg_temp_new();
- TCGv memop = tcg_temp_new();
+
+ gen_helper_hyp_access_check(cpu_env);
gen_get_gpr(t0, a->rs1);
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
- tcg_gen_movi_tl(memop, MO_TEUL);
- gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEUL);
gen_set_gpr(a->rd, t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- tcg_temp_free(mem_idx);
- tcg_temp_free(memop);
return true;
#else
return false;
@@ -257,20 +220,16 @@ static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a)
#ifndef CONFIG_USER_ONLY
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
- TCGv mem_idx = tcg_temp_new();
- TCGv memop = tcg_temp_new();
+
+ gen_helper_hyp_access_check(cpu_env);
gen_get_gpr(t0, a->rs1);
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
- tcg_gen_movi_tl(memop, MO_TEQ);
- gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEQ);
gen_set_gpr(a->rd, t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- tcg_temp_free(mem_idx);
- tcg_temp_free(memop);
return true;
#else
return false;
@@ -283,20 +242,16 @@ static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a)
#ifndef CONFIG_USER_ONLY
TCGv t0 = tcg_temp_new();
TCGv dat = tcg_temp_new();
- TCGv mem_idx = tcg_temp_new();
- TCGv memop = tcg_temp_new();
+
+ gen_helper_hyp_access_check(cpu_env);
gen_get_gpr(t0, a->rs1);
gen_get_gpr(dat, a->rs2);
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
- tcg_gen_movi_tl(memop, MO_TEQ);
- gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop);
+ tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEQ);
tcg_temp_free(t0);
tcg_temp_free(dat);
- tcg_temp_free(mem_idx);
- tcg_temp_free(memop);
return true;
#else
return false;
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. Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/helper.h | 3 +- target/riscv/op_helper.c | 72 +-------------- target/riscv/insn_trans/trans_rvh.c.inc | 111 +++++++----------------- 3 files changed, 35 insertions(+), 151 deletions(-)