Instead of using an external helper to ensure we can perform the Hypervisor load/store instructions let's do it inline using TB_FLAGS.
Signed-off-by: Alistair Francis <alistair.fran...@wdc.com> --- target/riscv/cpu.h | 12 +++ target/riscv/helper.h | 1 - target/riscv/op_helper.c | 16 ---- target/riscv/translate.c | 2 + target/riscv/insn_trans/trans_rvh.c.inc | 121 +++++++++++++++++++++--- 5 files changed, 124 insertions(+), 28 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 0cf48a1521..c0a326c843 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -375,6 +375,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 @@ -421,7 +423,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/target/riscv/helper.h b/target/riscv/helper.h index 7dbdd117d2..ee35311052 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -81,7 +81,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_1(hyp_access_check, void, env) DEF_HELPER_4(hyp_x_load, tl, env, tl, tl, tl) #endif diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index d81d8282cc..980d4f39e1 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -227,22 +227,6 @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env) helper_hyp_tlb_flush(env); } -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))) { - 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/target/riscv/translate.c b/target/riscv/translate.c index 79dca2291b..554d52a4be 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -56,6 +56,7 @@ typedef struct DisasContext { to reset this known value. */ int frm; bool ext_ifencei; + bool hlsx; /* vector extension */ bool vill; uint8_t lmul; @@ -807,6 +808,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); diff --git a/target/riscv/insn_trans/trans_rvh.c.inc b/target/riscv/insn_trans/trans_rvh.c.inc index 79968701e9..b780ec8bc4 100644 --- a/target/riscv/insn_trans/trans_rvh.c.inc +++ b/target/riscv/insn_trans/trans_rvh.c.inc @@ -23,7 +23,16 @@ static bool trans_hlv_b(DisasContext *ctx, arg_hlv_b *a) TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - gen_helper_hyp_access_check(cpu_env); + if (!ctx->hlsx) { + if (ctx->virt_enabled) { + generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT); + } else { + generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); + } + exit_tb(ctx); /* no chaining */ + ctx->base.is_jmp = DISAS_NORETURN; + return false; + } gen_get_gpr(t0, a->rs1); @@ -45,7 +54,16 @@ static bool trans_hlv_h(DisasContext *ctx, arg_hlv_h *a) TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - gen_helper_hyp_access_check(cpu_env); + if (!ctx->hlsx) { + if (ctx->virt_enabled) { + generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT); + } else { + generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); + } + exit_tb(ctx); /* no chaining */ + ctx->base.is_jmp = DISAS_NORETURN; + return false; + } gen_get_gpr(t0, a->rs1); @@ -67,7 +85,16 @@ static bool trans_hlv_w(DisasContext *ctx, arg_hlv_w *a) TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - gen_helper_hyp_access_check(cpu_env); + if (!ctx->hlsx) { + if (ctx->virt_enabled) { + generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT); + } else { + generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); + } + exit_tb(ctx); /* no chaining */ + ctx->base.is_jmp = DISAS_NORETURN; + return false; + } gen_get_gpr(t0, a->rs1); @@ -89,7 +116,16 @@ static bool trans_hlv_bu(DisasContext *ctx, arg_hlv_bu *a) TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - gen_helper_hyp_access_check(cpu_env); + if (!ctx->hlsx) { + if (ctx->virt_enabled) { + generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT); + } else { + generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); + } + exit_tb(ctx); /* no chaining */ + ctx->base.is_jmp = DISAS_NORETURN; + return false; + } gen_get_gpr(t0, a->rs1); @@ -111,7 +147,16 @@ static bool trans_hlv_hu(DisasContext *ctx, arg_hlv_hu *a) TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - gen_helper_hyp_access_check(cpu_env); + if (!ctx->hlsx) { + if (ctx->virt_enabled) { + generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT); + } else { + generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); + } + exit_tb(ctx); /* no chaining */ + ctx->base.is_jmp = DISAS_NORETURN; + return false; + } gen_get_gpr(t0, a->rs1); tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEUW); @@ -132,7 +177,16 @@ static bool trans_hsv_b(DisasContext *ctx, arg_hsv_b *a) TCGv t0 = tcg_temp_new(); TCGv dat = tcg_temp_new(); - gen_helper_hyp_access_check(cpu_env); + if (!ctx->hlsx) { + if (ctx->virt_enabled) { + generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT); + } else { + generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); + } + exit_tb(ctx); /* no chaining */ + ctx->base.is_jmp = DISAS_NORETURN; + return false; + } gen_get_gpr(t0, a->rs1); gen_get_gpr(dat, a->rs2); @@ -154,7 +208,16 @@ static bool trans_hsv_h(DisasContext *ctx, arg_hsv_h *a) TCGv t0 = tcg_temp_new(); TCGv dat = tcg_temp_new(); - gen_helper_hyp_access_check(cpu_env); + if (!ctx->hlsx) { + if (ctx->virt_enabled) { + generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT); + } else { + generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); + } + exit_tb(ctx); /* no chaining */ + ctx->base.is_jmp = DISAS_NORETURN; + return false; + } gen_get_gpr(t0, a->rs1); gen_get_gpr(dat, a->rs2); @@ -176,7 +239,16 @@ static bool trans_hsv_w(DisasContext *ctx, arg_hsv_w *a) TCGv t0 = tcg_temp_new(); TCGv dat = tcg_temp_new(); - gen_helper_hyp_access_check(cpu_env); + if (!ctx->hlsx) { + if (ctx->virt_enabled) { + generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT); + } else { + generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); + } + exit_tb(ctx); /* no chaining */ + ctx->base.is_jmp = DISAS_NORETURN; + return false; + } gen_get_gpr(t0, a->rs1); gen_get_gpr(dat, a->rs2); @@ -199,7 +271,16 @@ static bool trans_hlv_wu(DisasContext *ctx, arg_hlv_wu *a) TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - gen_helper_hyp_access_check(cpu_env); + if (!ctx->hlsx) { + if (ctx->virt_enabled) { + generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT); + } else { + generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); + } + exit_tb(ctx); /* no chaining */ + ctx->base.is_jmp = DISAS_NORETURN; + return false; + } gen_get_gpr(t0, a->rs1); @@ -221,7 +302,16 @@ static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a) TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - gen_helper_hyp_access_check(cpu_env); + if (!ctx->hlsx) { + if (ctx->virt_enabled) { + generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT); + } else { + generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); + } + exit_tb(ctx); /* no chaining */ + ctx->base.is_jmp = DISAS_NORETURN; + return false; + } gen_get_gpr(t0, a->rs1); @@ -243,7 +333,16 @@ static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a) TCGv t0 = tcg_temp_new(); TCGv dat = tcg_temp_new(); - gen_helper_hyp_access_check(cpu_env); + if (!ctx->hlsx) { + if (ctx->virt_enabled) { + generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT); + } else { + generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); + } + exit_tb(ctx); /* no chaining */ + ctx->base.is_jmp = DISAS_NORETURN; + return false; + } gen_get_gpr(t0, a->rs1); gen_get_gpr(dat, a->rs2); -- 2.28.0