[PATCH v2] target/riscv: Reject Svinval instructions in U-mode

Zephyr Li posted 1 patch 1 week, 1 day ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260522033145.17850-1-fritchleybohrer@gmail.com
Maintainers: Palmer Dabbelt <palmer@dabbelt.com>, Alistair Francis <alistair.francis@wdc.com>, Weiwei Li <liwei1518@gmail.com>, Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>, Liu Zhiwei <zhiwei_liu@linux.alibaba.com>, Chao Liu <chao.liu.zevorn@gmail.com>
target/riscv/insn_trans/trans_svinval.c.inc | 12 ++++++++++++
1 file changed, 12 insertions(+)
[PATCH v2] target/riscv: Reject Svinval instructions in U-mode
Posted by Zephyr Li 1 week, 1 day ago
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
Re: [PATCH v2] target/riscv: Reject Svinval instructions in U-mode
Posted by Alistair Francis 3 days, 16 hours ago
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);
Re: [PATCH v2] target/riscv: Reject Svinval instructions in U-mode
Posted by Alistair Francis 3 days, 16 hours ago
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);
Re: [PATCH v2] target/riscv: Reject Svinval instructions in U-mode
Posted by Chao Liu 5 days, 12 hours ago
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
>
Re: [PATCH v2] target/riscv: Reject Svinval instructions in U-mode
Posted by Daniel Henrique Barboza 1 week ago

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);