target/riscv: Add CTR sctrclr instruction.

CTR extension adds a new instruction sctrclr to quickly
clear the recorded entries buffer.

Signed-off-by: Rajnesh Kanwal <rkanwal@rivosinc.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20250205-b4-ctr_upstream_v6-v6-5-439d8e06c8ef@rivosinc.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Rajnesh Kanwal 2025-02-05 11:18:49 +00:00 committed by Alistair Francis
parent 4ff7a27adc
commit 9e69e760fd
6 changed files with 50 additions and 0 deletions

View file

@ -619,6 +619,7 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool virt_en);
void riscv_ctr_add_entry(CPURISCVState *env, target_long src, target_long dst, void riscv_ctr_add_entry(CPURISCVState *env, target_long src, target_long dst,
enum CTRType type, target_ulong prev_priv, bool prev_virt); enum CTRType type, target_ulong prev_priv, bool prev_virt);
void riscv_ctr_clear(CPURISCVState *env);
void riscv_translate_init(void); void riscv_translate_init(void);
void riscv_translate_code(CPUState *cs, TranslationBlock *tb, void riscv_translate_code(CPUState *cs, TranslationBlock *tb,

View file

@ -887,6 +887,13 @@ static void riscv_ctr_freeze(CPURISCVState *env, uint64_t freeze_mask,
} }
} }
void riscv_ctr_clear(CPURISCVState *env)
{
memset(env->ctr_src, 0x0, sizeof(env->ctr_src));
memset(env->ctr_dst, 0x0, sizeof(env->ctr_dst));
memset(env->ctr_data, 0x0, sizeof(env->ctr_data));
}
static uint64_t riscv_ctr_priv_to_mask(target_ulong priv, bool virt) static uint64_t riscv_ctr_priv_to_mask(target_ulong priv, bool virt)
{ {
switch (priv) { switch (priv) {

View file

@ -132,6 +132,7 @@ DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl)
DEF_HELPER_1(sret, tl, env) DEF_HELPER_1(sret, tl, env)
DEF_HELPER_1(mret, tl, env) DEF_HELPER_1(mret, tl, env)
DEF_HELPER_1(mnret, tl, env) DEF_HELPER_1(mnret, tl, env)
DEF_HELPER_1(ctr_clear, void, env)
DEF_HELPER_1(wfi, void, env) DEF_HELPER_1(wfi, void, env)
DEF_HELPER_1(wrs_nto, void, env) DEF_HELPER_1(wrs_nto, void, env)
DEF_HELPER_1(tlb_flush, void, env) DEF_HELPER_1(tlb_flush, void, env)

View file

@ -114,6 +114,7 @@
# *** Privileged Instructions *** # *** Privileged Instructions ***
ecall 000000000000 00000 000 00000 1110011 ecall 000000000000 00000 000 00000 1110011
ebreak 000000000001 00000 000 00000 1110011 ebreak 000000000001 00000 000 00000 1110011
sctrclr 000100000100 00000 000 00000 1110011
uret 0000000 00010 00000 000 00000 1110011 uret 0000000 00010 00000 000 00000 1110011
sret 0001000 00010 00000 000 00000 1110011 sret 0001000 00010 00000 000 00000 1110011
mret 0011000 00010 00000 000 00000 1110011 mret 0011000 00010 00000 000 00000 1110011

View file

@ -75,6 +75,17 @@ static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a)
return true; return true;
} }
static bool trans_sctrclr(DisasContext *ctx, arg_sctrclr *a)
{
#ifndef CONFIG_USER_ONLY
if (ctx->cfg_ptr->ext_smctr || ctx->cfg_ptr->ext_ssctr) {
gen_helper_ctr_clear(tcg_env);
return true;
}
#endif
return false;
}
static bool trans_uret(DisasContext *ctx, arg_uret *a) static bool trans_uret(DisasContext *ctx, arg_uret *a)
{ {
return false; return false;

View file

@ -485,6 +485,35 @@ void helper_ctr_add_entry(CPURISCVState *env, target_ulong src,
env->priv, env->virt_enabled); env->priv, env->virt_enabled);
} }
void helper_ctr_clear(CPURISCVState *env)
{
/*
* It's safe to call smstateen_acc_ok() for umode access regardless of the
* state of bit 54 (CTR bit in case of m/hstateen) of sstateen. If the bit
* is zero, smstateen_acc_ok() will return the correct exception code and
* if it's one, smstateen_acc_ok() will return RISCV_EXCP_NONE. In that
* scenario the U-mode check below will handle that case.
*/
RISCVException ret = smstateen_acc_ok(env, 0, SMSTATEEN0_CTR);
if (ret != RISCV_EXCP_NONE) {
riscv_raise_exception(env, ret, GETPC());
}
if (env->priv == PRV_U) {
/*
* One corner case is when sctrclr is executed from VU-mode and
* mstateen.CTR = 0, in which case we are supposed to raise
* RISCV_EXCP_ILLEGAL_INST. This case is already handled in
* smstateen_acc_ok().
*/
uint32_t excep = env->virt_enabled ? RISCV_EXCP_VIRT_INSTRUCTION_FAULT :
RISCV_EXCP_ILLEGAL_INST;
riscv_raise_exception(env, excep, GETPC());
}
riscv_ctr_clear(env);
}
void helper_wfi(CPURISCVState *env) void helper_wfi(CPURISCVState *env)
{ {
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);