Follow the RISC-V CFI v1.0 spec [1] to fix the exception type
when ssamoswap is disabled by xSSE.
[1] RISC-V CFI spec v1.0, ch2.7 Atomic Swap from a Shadow Stack Location
Signed-off-by: Jim Shu <jim.shu@sifive.com>
---
target/riscv/helper.h | 5 ++
target/riscv/insn_trans/trans_rvzicfiss.c.inc | 8 +++
target/riscv/op_helper.c | 49 +++++++++++++++++++
3 files changed, 62 insertions(+)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index f712b1c368..c82bacdc39 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1284,3 +1284,8 @@ DEF_HELPER_4(vgmul_vv, void, ptr, ptr, env, i32)
DEF_HELPER_5(vsm4k_vi, void, ptr, ptr, i32, env, i32)
DEF_HELPER_4(vsm4r_vv, void, ptr, ptr, env, i32)
DEF_HELPER_4(vsm4r_vs, void, ptr, ptr, env, i32)
+
+/* CFI (zicfiss) helpers */
+#ifndef CONFIG_USER_ONLY
+DEF_HELPER_1(ssamoswap_disabled, void, env)
+#endif
diff --git a/target/riscv/insn_trans/trans_rvzicfiss.c.inc b/target/riscv/insn_trans/trans_rvzicfiss.c.inc
index 45686af4d6..f4a1c12ca0 100644
--- a/target/riscv/insn_trans/trans_rvzicfiss.c.inc
+++ b/target/riscv/insn_trans/trans_rvzicfiss.c.inc
@@ -91,7 +91,11 @@ static bool trans_ssamoswap_w(DisasContext *ctx, arg_amoswap_w *a)
}
if (!ctx->bcfi_enabled) {
+#ifndef CONFIG_USER_ONLY
+ gen_helper_ssamoswap_disabled(tcg_env);
+#else
return false;
+#endif
}
TCGv dest = dest_gpr(ctx, a->rd);
@@ -116,7 +120,11 @@ static bool trans_ssamoswap_d(DisasContext *ctx, arg_amoswap_w *a)
}
if (!ctx->bcfi_enabled) {
+#ifndef CONFIG_USER_ONLY
+ gen_helper_ssamoswap_disabled(tcg_env);
+#else
return false;
+#endif
}
TCGv dest = dest_gpr(ctx, a->rd);
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 110292e84d..8382aa94cb 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -717,4 +717,53 @@ target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong addr)
return cpu_ldl_code_mmu(env, addr, oi, ra);
}
+void helper_ssamoswap_disabled(CPURISCVState *env)
+{
+ int exception = RISCV_EXCP_ILLEGAL_INST;
+
+ /*
+ * Here we follow the RISC-V CFI spec [1] to implement the exception type
+ * of ssamoswap* instruction.
+ *
+ * [1] RISC-V CFI spec v1.0, ch2.7 Atomic Swap from a Shadow Stack Location
+ *
+ * Note: We have already checked some conditions in trans_* functions:
+ * 1. The effective priv mode is not M-mode.
+ * 2. The xSSE specific to the effictive priv mode is disabled.
+ */
+ if (!get_field(env->menvcfg, MENVCFG_SSE)) {
+ /*
+ * Disabled M-mode SSE always trigger illegal instruction when
+ * current priv mode is not M-mode.
+ */
+ exception = RISCV_EXCP_ILLEGAL_INST;
+ goto done;
+ }
+
+ if (!riscv_has_ext(env, RVS)) {
+ /* S-mode is not implemented */
+ exception = RISCV_EXCP_ILLEGAL_INST;
+ goto done;
+ } else if (env->virt_enabled) {
+ /*
+ * VU/VS-mode with disabled xSSE will trigger the virtual instruction
+ * exception.
+ */
+ exception = RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ goto done;
+ } else {
+ /*
+ * U-mode with disabled S-mode SSE will trigger the illegal instruction
+ * exception.
+ *
+ * Note: S-mode is already handled in the disabled M-mode SSE case.
+ */
+ exception = RISCV_EXCP_ILLEGAL_INST;
+ goto done;
+ }
+
+done:
+ riscv_raise_exception(env, exception, GETPC());
+}
+
#endif /* !CONFIG_USER_ONLY */
--
2.43.0