target/riscv: Fix ssamoswap error handling

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>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20250924074818.230010-4-jim.shu@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Jim Shu 2025-09-24 15:48:18 +08:00 committed by Alistair Francis
parent 84c1605b76
commit 0b16c7b6a8
3 changed files with 62 additions and 0 deletions

View file

@ -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

View file

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

View file

@ -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 */