@@ -794,7 +794,7 @@ static Property riscv_cpu_properties[] = {
DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
DEFINE_PROP_BOOL("v", RISCVCPU, cfg.ext_v, false),
DEFINE_PROP_BOOL("h", RISCVCPU, cfg.ext_h, true),
- DEFINE_PROP_BOOL("pmu", RISCVCPU, cfg.ext_pmu, true),
+ DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16),
DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false),
@@ -378,7 +378,6 @@ struct RISCVCPUConfig {
bool ext_zbb;
bool ext_zbc;
bool ext_zbs;
- bool ext_pmu;
bool ext_ifencei;
bool ext_icsr;
bool ext_svinval;
@@ -396,6 +395,7 @@ struct RISCVCPUConfig {
/* Vendor-specific custom extensions */
bool ext_XVentanaCondOps;
+ uint8_t pmu_num;
char *priv_spec;
char *user_spec;
char *bext_spec;
@@ -71,9 +71,17 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
CPUState *cs = env_cpu(env);
RISCVCPU *cpu = RISCV_CPU(cs);
int ctr_index;
+ int base_csrno = CSR_HPMCOUNTER3;
+ bool rv32 = riscv_cpu_mxl(env) == MXL_RV32 ? true : false;
- if (!cpu->cfg.ext_pmu) {
- /* The PMU extension is not enabled */
+ if (rv32 && csrno >= CSR_CYCLEH) {
+ /* Offset for RV32 hpmcounternh counters */
+ base_csrno += 0x80;
+ }
+ ctr_index = csrno - base_csrno;
+
+ if (!cpu->cfg.pmu_num || ctr_index >= (cpu->cfg.pmu_num)) {
+ /* No counter is enabled in PMU or the counter is out of range */
return RISCV_EXCP_ILLEGAL_INST;
}
@@ -101,7 +109,7 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
}
break;
}
- if (riscv_cpu_mxl(env) == MXL_RV32) {
+ if (rv32) {
switch (csrno) {
case CSR_CYCLEH:
if (!get_field(env->mcounteren, COUNTEREN_CY)) {
@@ -156,7 +164,7 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
}
break;
}
- if (riscv_cpu_mxl(env) == MXL_RV32) {
+ if (rv32) {
switch (csrno) {
case CSR_CYCLEH:
if (!get_field(env->hcounteren, COUNTEREN_CY) &&
@@ -200,6 +208,26 @@ static RISCVException ctr32(CPURISCVState *env, int csrno)
}
#if !defined(CONFIG_USER_ONLY)
+static RISCVException mctr(CPURISCVState *env, int csrno)
+{
+ CPUState *cs = env_cpu(env);
+ RISCVCPU *cpu = RISCV_CPU(cs);
+ int ctr_index;
+ int base_csrno = CSR_MHPMCOUNTER3;
+
+ if ((riscv_cpu_mxl(env) == MXL_RV32) && csrno >= CSR_MCYCLEH) {
+ /* Offset for RV32 mhpmcounternh counters */
+ base_csrno += 0x80;
+ }
+ ctr_index = csrno - base_csrno;
+ if (!cpu->cfg.pmu_num || ctr_index >= cpu->cfg.pmu_num) {
+ /* The PMU is not enabled or counter is out of range*/
+ return RISCV_EXCP_ILLEGAL_INST;
+ }
+
+ return RISCV_EXCP_NONE;
+}
+
static RISCVException any(CPURISCVState *env, int csrno)
{
return RISCV_EXCP_NONE;
@@ -3571,35 +3599,35 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
[CSR_HPMCOUNTER30] = { "hpmcounter30", ctr, read_zero },
[CSR_HPMCOUNTER31] = { "hpmcounter31", ctr, read_zero },
- [CSR_MHPMCOUNTER3] = { "mhpmcounter3", any, read_zero },
- [CSR_MHPMCOUNTER4] = { "mhpmcounter4", any, read_zero },
- [CSR_MHPMCOUNTER5] = { "mhpmcounter5", any, read_zero },
- [CSR_MHPMCOUNTER6] = { "mhpmcounter6", any, read_zero },
- [CSR_MHPMCOUNTER7] = { "mhpmcounter7", any, read_zero },
- [CSR_MHPMCOUNTER8] = { "mhpmcounter8", any, read_zero },
- [CSR_MHPMCOUNTER9] = { "mhpmcounter9", any, read_zero },
- [CSR_MHPMCOUNTER10] = { "mhpmcounter10", any, read_zero },
- [CSR_MHPMCOUNTER11] = { "mhpmcounter11", any, read_zero },
- [CSR_MHPMCOUNTER12] = { "mhpmcounter12", any, read_zero },
- [CSR_MHPMCOUNTER13] = { "mhpmcounter13", any, read_zero },
- [CSR_MHPMCOUNTER14] = { "mhpmcounter14", any, read_zero },
- [CSR_MHPMCOUNTER15] = { "mhpmcounter15", any, read_zero },
- [CSR_MHPMCOUNTER16] = { "mhpmcounter16", any, read_zero },
- [CSR_MHPMCOUNTER17] = { "mhpmcounter17", any, read_zero },
- [CSR_MHPMCOUNTER18] = { "mhpmcounter18", any, read_zero },
- [CSR_MHPMCOUNTER19] = { "mhpmcounter19", any, read_zero },
- [CSR_MHPMCOUNTER20] = { "mhpmcounter20", any, read_zero },
- [CSR_MHPMCOUNTER21] = { "mhpmcounter21", any, read_zero },
- [CSR_MHPMCOUNTER22] = { "mhpmcounter22", any, read_zero },
- [CSR_MHPMCOUNTER23] = { "mhpmcounter23", any, read_zero },
- [CSR_MHPMCOUNTER24] = { "mhpmcounter24", any, read_zero },
- [CSR_MHPMCOUNTER25] = { "mhpmcounter25", any, read_zero },
- [CSR_MHPMCOUNTER26] = { "mhpmcounter26", any, read_zero },
- [CSR_MHPMCOUNTER27] = { "mhpmcounter27", any, read_zero },
- [CSR_MHPMCOUNTER28] = { "mhpmcounter28", any, read_zero },
- [CSR_MHPMCOUNTER29] = { "mhpmcounter29", any, read_zero },
- [CSR_MHPMCOUNTER30] = { "mhpmcounter30", any, read_zero },
- [CSR_MHPMCOUNTER31] = { "mhpmcounter31", any, read_zero },
+ [CSR_MHPMCOUNTER3] = { "mhpmcounter3", mctr, read_zero },
+ [CSR_MHPMCOUNTER4] = { "mhpmcounter4", mctr, read_zero },
+ [CSR_MHPMCOUNTER5] = { "mhpmcounter5", mctr, read_zero },
+ [CSR_MHPMCOUNTER6] = { "mhpmcounter6", mctr, read_zero },
+ [CSR_MHPMCOUNTER7] = { "mhpmcounter7", mctr, read_zero },
+ [CSR_MHPMCOUNTER8] = { "mhpmcounter8", mctr, read_zero },
+ [CSR_MHPMCOUNTER9] = { "mhpmcounter9", mctr, read_zero },
+ [CSR_MHPMCOUNTER10] = { "mhpmcounter10", mctr, read_zero },
+ [CSR_MHPMCOUNTER11] = { "mhpmcounter11", mctr, read_zero },
+ [CSR_MHPMCOUNTER12] = { "mhpmcounter12", mctr, read_zero },
+ [CSR_MHPMCOUNTER13] = { "mhpmcounter13", mctr, read_zero },
+ [CSR_MHPMCOUNTER14] = { "mhpmcounter14", mctr, read_zero },
+ [CSR_MHPMCOUNTER15] = { "mhpmcounter15", mctr, read_zero },
+ [CSR_MHPMCOUNTER16] = { "mhpmcounter16", mctr, read_zero },
+ [CSR_MHPMCOUNTER17] = { "mhpmcounter17", mctr, read_zero },
+ [CSR_MHPMCOUNTER18] = { "mhpmcounter18", mctr, read_zero },
+ [CSR_MHPMCOUNTER19] = { "mhpmcounter19", mctr, read_zero },
+ [CSR_MHPMCOUNTER20] = { "mhpmcounter20", mctr, read_zero },
+ [CSR_MHPMCOUNTER21] = { "mhpmcounter21", mctr, read_zero },
+ [CSR_MHPMCOUNTER22] = { "mhpmcounter22", mctr, read_zero },
+ [CSR_MHPMCOUNTER23] = { "mhpmcounter23", mctr, read_zero },
+ [CSR_MHPMCOUNTER24] = { "mhpmcounter24", mctr, read_zero },
+ [CSR_MHPMCOUNTER25] = { "mhpmcounter25", mctr, read_zero },
+ [CSR_MHPMCOUNTER26] = { "mhpmcounter26", mctr, read_zero },
+ [CSR_MHPMCOUNTER27] = { "mhpmcounter27", mctr, read_zero },
+ [CSR_MHPMCOUNTER28] = { "mhpmcounter28", mctr, read_zero },
+ [CSR_MHPMCOUNTER29] = { "mhpmcounter29", mctr, read_zero },
+ [CSR_MHPMCOUNTER30] = { "mhpmcounter30", mctr, read_zero },
+ [CSR_MHPMCOUNTER31] = { "mhpmcounter31", mctr, read_zero },
[CSR_MHPMEVENT3] = { "mhpmevent3", any, read_zero },
[CSR_MHPMEVENT4] = { "mhpmevent4", any, read_zero },