SBI v3.0 introduced a new raw event type that allows wider
mhpmeventX width to be programmed via CFG_MATCH.
Use the raw event v2 if SBI v3.0 is available.
Signed-off-by: Atish Patra <atishp@rivosinc.com>
---
arch/riscv/include/asm/sbi.h | 4 ++++
drivers/perf/riscv_pmu_sbi.c | 16 ++++++++++++----
2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
index 3d250824178b..6ce385a3a7bb 100644
--- a/arch/riscv/include/asm/sbi.h
+++ b/arch/riscv/include/asm/sbi.h
@@ -160,7 +160,10 @@ struct riscv_pmu_snapshot_data {
#define RISCV_PMU_RAW_EVENT_MASK GENMASK_ULL(47, 0)
#define RISCV_PMU_PLAT_FW_EVENT_MASK GENMASK_ULL(61, 0)
+/* SBI v3.0 allows extended hpmeventX width value */
+#define RISCV_PMU_RAW_EVENT_V2_MASK GENMASK_ULL(55, 0)
#define RISCV_PMU_RAW_EVENT_IDX 0x20000
+#define RISCV_PMU_RAW_EVENT_V2_IDX 0x30000
#define RISCV_PLAT_FW_EVENT 0xFFFF
/** General pmu event codes specified in SBI PMU extension */
@@ -218,6 +221,7 @@ enum sbi_pmu_event_type {
SBI_PMU_EVENT_TYPE_HW = 0x0,
SBI_PMU_EVENT_TYPE_CACHE = 0x1,
SBI_PMU_EVENT_TYPE_RAW = 0x2,
+ SBI_PMU_EVENT_TYPE_RAW_V2 = 0x3,
SBI_PMU_EVENT_TYPE_FW = 0xf,
};
diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
index cfd6946fca42..273ed70098a3 100644
--- a/drivers/perf/riscv_pmu_sbi.c
+++ b/drivers/perf/riscv_pmu_sbi.c
@@ -59,7 +59,7 @@ asm volatile(ALTERNATIVE( \
#define PERF_EVENT_FLAG_USER_ACCESS BIT(SYSCTL_USER_ACCESS)
#define PERF_EVENT_FLAG_LEGACY BIT(SYSCTL_LEGACY)
-PMU_FORMAT_ATTR(event, "config:0-47");
+PMU_FORMAT_ATTR(event, "config:0-55");
PMU_FORMAT_ATTR(firmware, "config:62-63");
static bool sbi_v2_available;
@@ -527,8 +527,10 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
break;
case PERF_TYPE_RAW:
/*
- * As per SBI specification, the upper 16 bits must be unused
- * for a hardware raw event.
+ * As per SBI v0.3 specification,
+ * -- the upper 16 bits must be unused for a hardware raw event.
+ * As per SBI v3.0 specification,
+ * -- the upper 8 bits must be unused for a hardware raw event.
* Bits 63:62 are used to distinguish between raw events
* 00 - Hardware raw event
* 10 - SBI firmware events
@@ -537,8 +539,14 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
switch (config >> 62) {
case 0:
+ if (sbi_v3_available) {
+ /* Return error any bits [56-63] is set as it is not allowed by the spec */
+ if (!(config & ~RISCV_PMU_RAW_EVENT_V2_MASK)) {
+ *econfig = config & RISCV_PMU_RAW_EVENT_V2_MASK;
+ ret = RISCV_PMU_RAW_EVENT_V2_IDX;
+ }
/* Return error any bits [48-63] is set as it is not allowed by the spec */
- if (!(config & ~RISCV_PMU_RAW_EVENT_MASK)) {
+ } else if (!(config & ~RISCV_PMU_RAW_EVENT_MASK)) {
*econfig = config & RISCV_PMU_RAW_EVENT_MASK;
ret = RISCV_PMU_RAW_EVENT_IDX;
}
--
2.43.0
On Fri, May 23, 2025 at 12:33 AM Atish Patra <atishp@rivosinc.com> wrote:
>
> SBI v3.0 introduced a new raw event type that allows wider
> mhpmeventX width to be programmed via CFG_MATCH.
>
> Use the raw event v2 if SBI v3.0 is available.
>
> Signed-off-by: Atish Patra <atishp@rivosinc.com>
> ---
> arch/riscv/include/asm/sbi.h | 4 ++++
> drivers/perf/riscv_pmu_sbi.c | 16 ++++++++++++----
> 2 files changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
> index 3d250824178b..6ce385a3a7bb 100644
> --- a/arch/riscv/include/asm/sbi.h
> +++ b/arch/riscv/include/asm/sbi.h
> @@ -160,7 +160,10 @@ struct riscv_pmu_snapshot_data {
>
> #define RISCV_PMU_RAW_EVENT_MASK GENMASK_ULL(47, 0)
> #define RISCV_PMU_PLAT_FW_EVENT_MASK GENMASK_ULL(61, 0)
> +/* SBI v3.0 allows extended hpmeventX width value */
> +#define RISCV_PMU_RAW_EVENT_V2_MASK GENMASK_ULL(55, 0)
> #define RISCV_PMU_RAW_EVENT_IDX 0x20000
> +#define RISCV_PMU_RAW_EVENT_V2_IDX 0x30000
> #define RISCV_PLAT_FW_EVENT 0xFFFF
>
> /** General pmu event codes specified in SBI PMU extension */
> @@ -218,6 +221,7 @@ enum sbi_pmu_event_type {
> SBI_PMU_EVENT_TYPE_HW = 0x0,
> SBI_PMU_EVENT_TYPE_CACHE = 0x1,
> SBI_PMU_EVENT_TYPE_RAW = 0x2,
> + SBI_PMU_EVENT_TYPE_RAW_V2 = 0x3,
> SBI_PMU_EVENT_TYPE_FW = 0xf,
> };
>
> diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
> index cfd6946fca42..273ed70098a3 100644
> --- a/drivers/perf/riscv_pmu_sbi.c
> +++ b/drivers/perf/riscv_pmu_sbi.c
> @@ -59,7 +59,7 @@ asm volatile(ALTERNATIVE( \
> #define PERF_EVENT_FLAG_USER_ACCESS BIT(SYSCTL_USER_ACCESS)
> #define PERF_EVENT_FLAG_LEGACY BIT(SYSCTL_LEGACY)
>
> -PMU_FORMAT_ATTR(event, "config:0-47");
> +PMU_FORMAT_ATTR(event, "config:0-55");
> PMU_FORMAT_ATTR(firmware, "config:62-63");
>
> static bool sbi_v2_available;
> @@ -527,8 +527,10 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
> break;
> case PERF_TYPE_RAW:
> /*
> - * As per SBI specification, the upper 16 bits must be unused
> - * for a hardware raw event.
> + * As per SBI v0.3 specification,
> + * -- the upper 16 bits must be unused for a hardware raw event.
> + * As per SBI v3.0 specification,
The text here should be "As-per SBI v2.0 ..."
> + * -- the upper 8 bits must be unused for a hardware raw event.
> * Bits 63:62 are used to distinguish between raw events
> * 00 - Hardware raw event
> * 10 - SBI firmware events
> @@ -537,8 +539,14 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
>
> switch (config >> 62) {
> case 0:
> + if (sbi_v3_available) {
> + /* Return error any bits [56-63] is set as it is not allowed by the spec */
> + if (!(config & ~RISCV_PMU_RAW_EVENT_V2_MASK)) {
> + *econfig = config & RISCV_PMU_RAW_EVENT_V2_MASK;
> + ret = RISCV_PMU_RAW_EVENT_V2_IDX;
> + }
> /* Return error any bits [48-63] is set as it is not allowed by the spec */
> - if (!(config & ~RISCV_PMU_RAW_EVENT_MASK)) {
> + } else if (!(config & ~RISCV_PMU_RAW_EVENT_MASK)) {
> *econfig = config & RISCV_PMU_RAW_EVENT_MASK;
> ret = RISCV_PMU_RAW_EVENT_IDX;
> }
>
> --
> 2.43.0
>
Otherwise, this looks good to me.
Reviewed-by: Anup Patel <anup@brainfault.org>
Regards,
Anup
© 2016 - 2025 Red Hat, Inc.