mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 07:13:54 -06:00
target/riscv: Add support for Control Transfer Records extension CSRs.
This commit adds support for [m|s|vs]ctrcontrol, sctrstatus and sctrdepth CSRs handling. Signed-off-by: Rajnesh Kanwal <rkanwal@rivosinc.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20250205-b4-ctr_upstream_v6-v6-3-439d8e06c8ef@rivosinc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
3f833f8920
commit
c48bd18eae
3 changed files with 151 additions and 0 deletions
|
@ -313,6 +313,11 @@ struct CPUArchState {
|
|||
target_ulong mcause;
|
||||
target_ulong mtval; /* since: priv-1.10.0 */
|
||||
|
||||
uint64_t mctrctl;
|
||||
uint32_t sctrdepth;
|
||||
uint32_t sctrstatus;
|
||||
uint64_t vsctrctl;
|
||||
|
||||
/* Machine and Supervisor interrupt priorities */
|
||||
uint8_t miprio[64];
|
||||
uint8_t siprio[64];
|
||||
|
|
|
@ -133,6 +133,8 @@ struct RISCVCPUConfig {
|
|||
bool ext_zvfhmin;
|
||||
bool ext_smaia;
|
||||
bool ext_ssaia;
|
||||
bool ext_smctr;
|
||||
bool ext_ssctr;
|
||||
bool ext_sscofpmf;
|
||||
bool ext_smepmp;
|
||||
bool ext_smrnmi;
|
||||
|
|
|
@ -635,6 +635,48 @@ static RISCVException hgatp(CPURISCVState *env, int csrno)
|
|||
return hmode(env, csrno);
|
||||
}
|
||||
|
||||
/*
|
||||
* M-mode:
|
||||
* Without ext_smctr raise illegal inst excep.
|
||||
* Otherwise everything is accessible to m-mode.
|
||||
*
|
||||
* S-mode:
|
||||
* Without ext_ssctr or mstateen.ctr raise illegal inst excep.
|
||||
* Otherwise everything other than mctrctl is accessible.
|
||||
*
|
||||
* VS-mode:
|
||||
* Without ext_ssctr or mstateen.ctr raise illegal inst excep.
|
||||
* Without hstateen.ctr raise virtual illegal inst excep.
|
||||
* Otherwise allow sctrctl (vsctrctl), sctrstatus, 0x200-0x2ff entry range.
|
||||
* Always raise illegal instruction exception for sctrdepth.
|
||||
*/
|
||||
static RISCVException ctr_mmode(CPURISCVState *env, int csrno)
|
||||
{
|
||||
/* Check if smctr-ext is present */
|
||||
if (riscv_cpu_cfg(env)->ext_smctr) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
static RISCVException ctr_smode(CPURISCVState *env, int csrno)
|
||||
{
|
||||
const RISCVCPUConfig *cfg = riscv_cpu_cfg(env);
|
||||
|
||||
if (!cfg->ext_smctr && !cfg->ext_ssctr) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
RISCVException ret = smstateen_acc_ok(env, 0, SMSTATEEN0_CTR);
|
||||
if (ret == RISCV_EXCP_NONE && csrno == CSR_SCTRDEPTH &&
|
||||
env->virt_enabled) {
|
||||
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static RISCVException aia_hmode(CPURISCVState *env, int csrno)
|
||||
{
|
||||
int ret;
|
||||
|
@ -3216,6 +3258,10 @@ static RISCVException write_mstateen0(CPURISCVState *env, int csrno,
|
|||
wr_mask |= (SMSTATEEN0_AIA | SMSTATEEN0_IMSIC);
|
||||
}
|
||||
|
||||
if (riscv_cpu_cfg(env)->ext_ssctr) {
|
||||
wr_mask |= SMSTATEEN0_CTR;
|
||||
}
|
||||
|
||||
return write_mstateen(env, csrno, wr_mask, new_val);
|
||||
}
|
||||
|
||||
|
@ -3255,6 +3301,10 @@ static RISCVException write_mstateen0h(CPURISCVState *env, int csrno,
|
|||
wr_mask |= SMSTATEEN0_P1P13;
|
||||
}
|
||||
|
||||
if (riscv_cpu_cfg(env)->ext_ssctr) {
|
||||
wr_mask |= SMSTATEEN0_CTR;
|
||||
}
|
||||
|
||||
return write_mstateenh(env, csrno, wr_mask, new_val);
|
||||
}
|
||||
|
||||
|
@ -3309,6 +3359,10 @@ static RISCVException write_hstateen0(CPURISCVState *env, int csrno,
|
|||
wr_mask |= (SMSTATEEN0_AIA | SMSTATEEN0_IMSIC);
|
||||
}
|
||||
|
||||
if (riscv_cpu_cfg(env)->ext_ssctr) {
|
||||
wr_mask |= SMSTATEEN0_CTR;
|
||||
}
|
||||
|
||||
return write_hstateen(env, csrno, wr_mask, new_val);
|
||||
}
|
||||
|
||||
|
@ -3348,6 +3402,10 @@ static RISCVException write_hstateen0h(CPURISCVState *env, int csrno,
|
|||
{
|
||||
uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
|
||||
|
||||
if (riscv_cpu_cfg(env)->ext_ssctr) {
|
||||
wr_mask |= SMSTATEEN0_CTR;
|
||||
}
|
||||
|
||||
return write_hstateenh(env, csrno, wr_mask, new_val);
|
||||
}
|
||||
|
||||
|
@ -4068,6 +4126,86 @@ static RISCVException write_satp(CPURISCVState *env, int csrno,
|
|||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException rmw_sctrdepth(CPURISCVState *env, int csrno,
|
||||
target_ulong *ret_val,
|
||||
target_ulong new_val, target_ulong wr_mask)
|
||||
{
|
||||
uint64_t mask = wr_mask & SCTRDEPTH_MASK;
|
||||
|
||||
if (ret_val) {
|
||||
*ret_val = env->sctrdepth;
|
||||
}
|
||||
|
||||
env->sctrdepth = (env->sctrdepth & ~mask) | (new_val & mask);
|
||||
|
||||
/* Correct depth. */
|
||||
if (mask) {
|
||||
uint64_t depth = get_field(env->sctrdepth, SCTRDEPTH_MASK);
|
||||
|
||||
if (depth > SCTRDEPTH_MAX) {
|
||||
depth = SCTRDEPTH_MAX;
|
||||
env->sctrdepth = set_field(env->sctrdepth, SCTRDEPTH_MASK, depth);
|
||||
}
|
||||
|
||||
/* Update sctrstatus.WRPTR with a legal value */
|
||||
depth = 16 << depth;
|
||||
env->sctrstatus =
|
||||
env->sctrstatus & (~SCTRSTATUS_WRPTR_MASK | (depth - 1));
|
||||
}
|
||||
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException rmw_sctrstatus(CPURISCVState *env, int csrno,
|
||||
target_ulong *ret_val,
|
||||
target_ulong new_val, target_ulong wr_mask)
|
||||
{
|
||||
uint32_t depth = 16 << get_field(env->sctrdepth, SCTRDEPTH_MASK);
|
||||
uint32_t mask = wr_mask & SCTRSTATUS_MASK;
|
||||
|
||||
if (ret_val) {
|
||||
*ret_val = env->sctrstatus;
|
||||
}
|
||||
|
||||
env->sctrstatus = (env->sctrstatus & ~mask) | (new_val & mask);
|
||||
|
||||
/* Update sctrstatus.WRPTR with a legal value */
|
||||
env->sctrstatus = env->sctrstatus & (~SCTRSTATUS_WRPTR_MASK | (depth - 1));
|
||||
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException rmw_xctrctl(CPURISCVState *env, int csrno,
|
||||
target_ulong *ret_val,
|
||||
target_ulong new_val, target_ulong wr_mask)
|
||||
{
|
||||
uint64_t csr_mask, mask = wr_mask;
|
||||
uint64_t *ctl_ptr = &env->mctrctl;
|
||||
|
||||
if (csrno == CSR_MCTRCTL) {
|
||||
csr_mask = MCTRCTL_MASK;
|
||||
} else if (csrno == CSR_SCTRCTL && !env->virt_enabled) {
|
||||
csr_mask = SCTRCTL_MASK;
|
||||
} else {
|
||||
/*
|
||||
* This is for csrno == CSR_SCTRCTL and env->virt_enabled == true
|
||||
* or csrno == CSR_VSCTRCTL.
|
||||
*/
|
||||
csr_mask = VSCTRCTL_MASK;
|
||||
ctl_ptr = &env->vsctrctl;
|
||||
}
|
||||
|
||||
mask &= csr_mask;
|
||||
|
||||
if (ret_val) {
|
||||
*ret_val = *ctl_ptr & csr_mask;
|
||||
}
|
||||
|
||||
*ctl_ptr = (*ctl_ptr & ~mask) | (new_val & mask);
|
||||
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException read_vstopi(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
{
|
||||
|
@ -5821,6 +5959,12 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
|
|||
[CSR_TINFO] = { "tinfo", debug, read_tinfo, write_ignore },
|
||||
[CSR_MCONTEXT] = { "mcontext", debug, read_mcontext, write_mcontext },
|
||||
|
||||
[CSR_MCTRCTL] = { "mctrctl", ctr_mmode, NULL, NULL, rmw_xctrctl },
|
||||
[CSR_SCTRCTL] = { "sctrctl", ctr_smode, NULL, NULL, rmw_xctrctl },
|
||||
[CSR_VSCTRCTL] = { "vsctrctl", ctr_smode, NULL, NULL, rmw_xctrctl },
|
||||
[CSR_SCTRDEPTH] = { "sctrdepth", ctr_smode, NULL, NULL, rmw_sctrdepth },
|
||||
[CSR_SCTRSTATUS] = { "sctrstatus", ctr_smode, NULL, NULL, rmw_sctrstatus },
|
||||
|
||||
/* Performance Counters */
|
||||
[CSR_HPMCOUNTER3] = { "hpmcounter3", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER4] = { "hpmcounter4", ctr, read_hpmcounter },
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue