target/riscv/insn_trans/trans_svinval.c.inc | 12 ++++++++++++ 1 file changed, 12 insertions(+)
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 <daniel.barboza@oss.qualcomm.com>
Signed-off-by: Zephyr Li <fritchleybohrer@gmail.com>
---
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.43.0
On Fri, 2026-05-22 at 11:31 +0800, Zephyr Li wrote:
> 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
> <daniel.barboza@oss.qualcomm.com>
>
> Signed-off-by: Zephyr Li <fritchleybohrer@gmail.com>
Thanks!
Applied to riscv-to-apply.next
Alistair
> ---
> 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);
On Fri, 2026-05-22 at 11:31 +0800, Zephyr Li wrote:
> 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
> <daniel.barboza@oss.qualcomm.com>
>
> Signed-off-by: Zephyr Li <fritchleybohrer@gmail.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Alistair
> ---
> 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);
On Fri, May 22, 2026 at 11:31:44AM +0800, Zephyr Li wrote:
> 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 <daniel.barboza@oss.qualcomm.com>
>
> Signed-off-by: Zephyr Li <fritchleybohrer@gmail.com>
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
> ---
> 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.43.0
>
On 5/22/2026 12:31 AM, Zephyr Li wrote:
> 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 <daniel.barboza@oss.qualcomm.com>
>
> Signed-off-by: Zephyr Li <fritchleybohrer@gmail.com>
> ---
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> 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);
© 2016 - 2026 Red Hat, Inc.