Add initial support for the Sspesa (Precise Event Sample Attribution) extension from the RISC-V Performance Event Sampling specification.
Added the 'sspesa' and ssplcofi CPU properties, and the shpmspc and shpmsdata CSRs. Signed-off-by: Mayuresh Chitale <[email protected]> --- target/riscv/cpu.c | 24 ++++++++++++++ target/riscv/cpu.h | 4 +++ target/riscv/cpu_bits.h | 12 +++++++ target/riscv/cpu_cfg_fields.h.inc | 2 ++ target/riscv/machine.c | 20 +++++++++++ target/riscv/tcg/csr.c | 55 +++++++++++++++++++++++++++++++ 6 files changed, 117 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ae750f85c6..99a01ac412 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -282,6 +282,8 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(ssctr, PRIV_VERSION_1_12_0, ext_ssctr), ISA_EXT_DATA_ENTRY(ssdbltrp, PRIV_VERSION_1_13_0, ext_ssdbltrp), ISA_EXT_DATA_ENTRY(ssnpm, PRIV_VERSION_1_13_0, ext_ssnpm), + ISA_EXT_DATA_ENTRY(sspesa, PRIV_VERSION_1_13_0, ext_sspesa), + ISA_EXT_DATA_ENTRY(ssplcofi, PRIV_VERSION_1_13_0, ext_ssplcofi), ISA_EXT_DATA_ENTRY(sspm, PRIV_VERSION_1_13_0, ext_sspm), ISA_INTERNAL_EXT_DATA_ENTRY(ssstateen, PRIV_VERSION_1_12_0, ext_ssstateen), ISA_INTERNAL_EXT_DATA_ENTRY(ssstrict, PRIV_VERSION_1_12_0, has_priv_1_12), @@ -1070,6 +1072,8 @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type) } pmp_unlock_entries(env); + env->shpmspc = 0; + env->shpmsdata = 0; #endif /* ifdef CONFIG_TCG */ #else env->priv = PRV_U; @@ -2933,6 +2937,24 @@ static RISCVCPUImpliedExtsRule SSSTATEEN_IMPLIED = { }, }; +static RISCVCPUImpliedExtsRule SSPLCOFI_IMPLIED = { + .ext = CPU_CFG_OFFSET(ext_ssplcofi), + .implied_multi_exts = { + CPU_CFG_OFFSET(ext_sspesa), + + RISCV_IMPLIED_EXTS_RULE_END + }, +}; + +static RISCVCPUImpliedExtsRule SSPESA_IMPLIED = { + .ext = CPU_CFG_OFFSET(ext_sspesa), + .implied_multi_exts = { + CPU_CFG_OFFSET(ext_sscofpmf), + + RISCV_IMPLIED_EXTS_RULE_END + }, +}; + static RISCVCPUImpliedExtsRule ZVFBFA_IMPLIED = { .ext = CPU_CFG_OFFSET(ext_zvfbfa), .implied_multi_exts = { @@ -3013,6 +3035,8 @@ RISCVCPUImpliedExtsRule *riscv_multi_ext_implied_rules[] = { &SSSTATEEN_IMPLIED, &XSFVQMACCDOD_IMPLIED, &XSFVQMACCQOQ_IMPLIED, + &SSPESA_IMPLIED, + &SSPLCOFI_IMPLIED, NULL }; diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 49a1186bdb..afd893e3a8 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -470,6 +470,10 @@ struct CPUArchState { uint64_t sscratch; uint64_t mscratch; + /* Sspesa CSRs */ + target_ulong shpmspc; + target_ulong shpmsdata; + /* Sstc CSRs */ uint64_t stimecmp; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 3579789a1f..61258ce6e1 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -634,6 +634,18 @@ #define CSR_SCOUNTOVF 0xda0 + /* Temporary addresses for Sspesa (Precise Event Sample Attribution) CSRs. */ +#define CSR_SHPMSPC 0x5d0 +#define CSR_SHPMSDATA 0x5d1 + +/* shpmsdata fields */ +#define SHPMSDATA_CNTRID 0x1f +#define SHPMSDATA_MODE 0x60 +#define SHPMSDATA_V 0x80 +#define SHPMSDATA_MODE_U 0x00 +#define SHPMSDATA_MODE_S 0x20 +#define SHPMSDATA_VALID_MASK (SHPMSDATA_CNTRID | SHPMSDATA_MODE | SHPMSDATA_V) + /* Crypto Extension */ #define CSR_SEED 0x015 diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_fields.h.inc index bcff8f55f1..6e67c6f739 100644 --- a/target/riscv/cpu_cfg_fields.h.inc +++ b/target/riscv/cpu_cfg_fields.h.inc @@ -112,6 +112,8 @@ BOOL_FIELD(ext_ssaia) BOOL_FIELD(ext_smctr) BOOL_FIELD(ext_ssctr) BOOL_FIELD(ext_sscofpmf) +BOOL_FIELD(ext_sspesa) +BOOL_FIELD(ext_ssplcofi) BOOL_FIELD(ext_smepmp) BOOL_FIELD(ext_smrnmi) BOOL_FIELD(ext_ssnpm) diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 0de06e9588..6e20ad0591 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -475,6 +475,25 @@ static const VMStateDescription vmstate_pmu_ctr_state = { } }; +static bool sspesa_needed(void *opaque) +{ + RISCVCPU *cpu = opaque; + + return cpu->cfg.ext_sspesa; +} + +static const VMStateDescription vmstate_sspesa = { + .name = "cpu/sspesa", + .version_id = 1, + .minimum_version_id = 1, + .needed = sspesa_needed, + .fields = (const VMStateField[]) { + VMSTATE_UINTTL(env.shpmspc, RISCVCPU), + VMSTATE_UINTTL(env.shpmsdata, RISCVCPU), + VMSTATE_END_OF_LIST() + } +}; + static bool jvt_needed(void *opaque) { RISCVCPU *cpu = opaque; @@ -653,6 +672,7 @@ const VMStateDescription vmstate_riscv_cpu = { &vmstate_elp, &vmstate_ssp, &vmstate_ctr, + &vmstate_sspesa, &vmstate_sstc, &vmstate_mseccfg, &vmstate_sdext, diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c index 063590f56a..c9b5b54c97 100644 --- a/target/riscv/tcg/csr.c +++ b/target/riscv/tcg/csr.c @@ -279,6 +279,28 @@ static RISCVException smcntrpmf(CPURISCVState *env, int csrno) return RISCV_EXCP_NONE; } +static RISCVException sspesa(CPURISCVState *env, int csrno) +{ + bool menvcfg_cde; + + if (!riscv_cpu_cfg(env)->ext_sspesa) { + return RISCV_EXCP_ILLEGAL_INST; + } + + if (env->priv == PRV_M) { + return RISCV_EXCP_NONE; + } + + menvcfg_cde = get_field(env->menvcfg, MENVCFG_CDE); + /* Access to shpmspc/shpmsdata from VS-mode always causes a fault */ + if (env->virt_enabled) { + return menvcfg_cde ? RISCV_EXCP_VIRT_INSTRUCTION_FAULT : + RISCV_EXCP_ILLEGAL_INST; + } + + return menvcfg_cde ? RISCV_EXCP_NONE : RISCV_EXCP_ILLEGAL_INST; +} + static RISCVException smcntrpmf_32(CPURISCVState *env, int csrno) { if (riscv_cpu_mxl(env) != MXL_RV32) { @@ -1677,6 +1699,34 @@ static RISCVException read_scountovf(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +static RISCVException read_shpmspc(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->shpmspc; + return RISCV_EXCP_NONE; +} + +static RISCVException write_shpmspc(CPURISCVState *env, int csrno, + target_ulong val, uintptr_t ra) +{ + env->shpmspc = val; + return RISCV_EXCP_NONE; +} + +static RISCVException read_shpmsdata(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->shpmsdata; + return RISCV_EXCP_NONE; +} + +static RISCVException write_shpmsdata(CPURISCVState *env, int csrno, + target_ulong val, uintptr_t ra) +{ + env->shpmsdata = val & SHPMSDATA_VALID_MASK; + return RISCV_EXCP_NONE; +} + static RISCVException read_time(CPURISCVState *env, int csrno, target_ulong *val) { @@ -6978,6 +7028,11 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { write_mhpmcounterh }, [CSR_SCOUNTOVF] = { "scountovf", sscofpmf, read_scountovf, .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_SHPMSPC] = { "shpmspc", sspesa, read_shpmspc, write_shpmspc, + .min_priv_ver = PRIV_VERSION_1_13_0 }, + [CSR_SHPMSDATA] = { "shpmsdata", sspesa, read_shpmsdata, + write_shpmsdata, + .min_priv_ver = PRIV_VERSION_1_13_0 }, #endif /* !CONFIG_USER_ONLY */ }; -- 2.43.0
