target/riscv: Implement checks for hfence

Call the helper_hyp_tlb_flush() function on hfence instructions which
will generate an illegal insruction execption if we don't have
permission to flush the Hypervisor level TLBs.

Backports commit 2761db5fc20943bbd606b6fd49640ac000398de6 from qemu
This commit is contained in:
Alistair Francis 2021-02-25 12:02:09 -05:00 committed by Lioncash
parent 8eb8bc290f
commit e1f49dc888
6 changed files with 27 additions and 24 deletions

View file

@ -5707,6 +5707,7 @@ riscv_symbols = (
'helper_fsqrt_s',
'helper_fsub_d',
'helper_fsub_s',
'helper_hyp_tlb_flush',
'helper_mret',
'helper_tlb_flush',
'helper_set_rounding_mode',

View file

@ -3458,6 +3458,7 @@
#define helper_fsqrt_s helper_fsqrt_s_riscv32
#define helper_fsub_d helper_fsub_d_riscv32
#define helper_fsub_s helper_fsub_s_riscv32
#define helper_hyp_tlb_flush helper_hyp_tlb_flush_riscv32
#define helper_mret helper_mret_riscv32
#define helper_tlb_flush helper_tlb_flush_riscv32
#define helper_set_rounding_mode helper_set_rounding_mode_riscv32

View file

@ -3458,6 +3458,7 @@
#define helper_fsqrt_s helper_fsqrt_s_riscv64
#define helper_fsub_d helper_fsub_d_riscv64
#define helper_fsub_s helper_fsub_s_riscv64
#define helper_hyp_tlb_flush helper_hyp_tlb_flush_riscv64
#define helper_mret helper_mret_riscv64
#define helper_tlb_flush helper_tlb_flush_riscv64
#define helper_set_rounding_mode helper_set_rounding_mode_riscv64

View file

@ -79,3 +79,8 @@ DEF_HELPER_2(mret, tl, env, tl)
DEF_HELPER_1(wfi, void, env)
DEF_HELPER_1(tlb_flush, void, env)
#endif
/* Hypervisor functions */
#ifndef CONFIG_USER_ONLY
DEF_HELPER_1(hyp_tlb_flush, void, env)
#endif

View file

@ -18,40 +18,22 @@
static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a)
{
REQUIRE_EXT(ctx, RVH);
#ifndef CONFIG_USER_ONLY
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
if (has_ext(ctx, RVH)) {
/* Hpervisor extensions exist */
/*
* if (env->priv == PRV_M ||
* (env->priv == PRV_S &&
* !riscv_cpu_virt_enabled(env) &&
* get_field(ctx->mstatus_fs, MSTATUS_TVM))) {
*/
gen_helper_tlb_flush(tcg_ctx, tcg_ctx->cpu_env);
gen_helper_hyp_tlb_flush(tcg_ctx, tcg_ctx->cpu_env);
return true;
/* } */
}
#endif
return false;
}
static bool trans_hfence_vvma(DisasContext *ctx, arg_sfence_vma *a)
{
REQUIRE_EXT(ctx, RVH);
#ifndef CONFIG_USER_ONLY
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
if (has_ext(ctx, RVH)) {
/* Hpervisor extensions exist */
/*
* if (env->priv == PRV_M ||
* (env->priv == PRV_S &&
* !riscv_cpu_virt_enabled(env) &&
* get_field(ctx->mstatus_fs, MSTATUS_TVM))) {
*/
gen_helper_tlb_flush(tcg_ctx, tcg_ctx->cpu_env);
gen_helper_hyp_tlb_flush(tcg_ctx, tcg_ctx->cpu_env);
return true;
/* } */
}
#endif
return false;
}

View file

@ -193,4 +193,17 @@ void helper_tlb_flush(CPURISCVState *env)
}
}
void helper_hyp_tlb_flush(CPURISCVState *env)
{
CPUState *cs = env_cpu(env);
if (env->priv == PRV_M ||
(env->priv == PRV_S && !riscv_cpu_virt_enabled(env))) {
tlb_flush(cs);
return;
}
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
}
#endif /* !CONFIG_USER_ONLY */