* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#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);
#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();
+
+ check_access(ctx);
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;
#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();
+
+ check_access(ctx);
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;
#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();
+
+ check_access(ctx);
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;
#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();
+
+ check_access(ctx);
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;
#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);
+ check_access(ctx);
- 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;
#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();
+
+ check_access(ctx);
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;
#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();
+
+ check_access(ctx);
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;
#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();
+
+ check_access(ctx);
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;
#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();
+
+ check_access(ctx);
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;
#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();
+
+ check_access(ctx);
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;
#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();
+
+ check_access(ctx);
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;
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)
{