From: Zephyr Li <[email protected]> The RISC-V privileged specification requires SFENCE.W.INVAL and SFENCE.INVAL.IR to raise an illegal instruction exception when executed in U-mode. Check the current privilege mode during translation and reject these instructions in U-mode, so they are reported as illegal instructions.
Add a helper to reject these instructions in U-mode during translation. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3493 Suggested-by: Daniel Henrique Barboza <[email protected]> Signed-off-by: Zephyr Li <[email protected]> Reviewed-by: Alistair Francis <[email protected]> Reviewed-by: Chao Liu <[email protected]> Reviewed-by: Daniel Henrique Barboza <[email protected]> Message-ID: <[email protected]> Signed-off-by: Alistair Francis <[email protected]> --- target/riscv/insn_trans/trans_svinval.c.inc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/target/riscv/insn_trans/trans_svinval.c.inc b/target/riscv/insn_trans/trans_svinval.c.inc index a06c3b214f..4614c1489c 100644 --- a/target/riscv/insn_trans/trans_svinval.c.inc +++ b/target/riscv/insn_trans/trans_svinval.c.inc @@ -22,11 +22,19 @@ } \ } while (0) +/* Test if priv level is M or S. */ +#define REQUIRE_PRIV_MS(ctx) do { \ + if (ctx->priv == PRV_U) { \ + return false; \ + } \ +} while (0) + static bool trans_sinval_vma(DisasContext *ctx, arg_sinval_vma *a) { REQUIRE_SVINVAL(ctx); /* Do the same as sfence.vma currently */ REQUIRE_EXT(ctx, RVS); + REQUIRE_PRIV_MS(ctx); #ifndef CONFIG_USER_ONLY decode_save_opc(ctx, 0); gen_helper_tlb_flush(tcg_env); @@ -39,6 +47,7 @@ static bool trans_sfence_w_inval(DisasContext *ctx, arg_sfence_w_inval *a) { REQUIRE_SVINVAL(ctx); REQUIRE_EXT(ctx, RVS); + REQUIRE_PRIV_MS(ctx); /* Do nothing currently */ return true; } @@ -47,6 +56,7 @@ static bool trans_sfence_inval_ir(DisasContext *ctx, arg_sfence_inval_ir *a) { REQUIRE_SVINVAL(ctx); REQUIRE_EXT(ctx, RVS); + REQUIRE_PRIV_MS(ctx); /* Do nothing currently */ return true; } @@ -56,6 +66,7 @@ static bool trans_hinval_vvma(DisasContext *ctx, arg_hinval_vvma *a) REQUIRE_SVINVAL(ctx); /* Do the same as hfence.vvma currently */ REQUIRE_EXT(ctx, RVH); + REQUIRE_PRIV_MS(ctx); #ifndef CONFIG_USER_ONLY decode_save_opc(ctx, 0); gen_helper_hyp_tlb_flush(tcg_env); @@ -69,6 +80,7 @@ static bool trans_hinval_gvma(DisasContext *ctx, arg_hinval_gvma *a) REQUIRE_SVINVAL(ctx); /* Do the same as hfence.gvma currently */ REQUIRE_EXT(ctx, RVH); + REQUIRE_PRIV_MS(ctx); #ifndef CONFIG_USER_ONLY decode_save_opc(ctx, 0); gen_helper_hyp_gvma_tlb_flush(tcg_env); -- 2.54.0
