Skip to content

Commit adffbd0

Browse files
atishp04avpatel
authored andcommitted
drivers/perf: riscv: Implement PMU event info function
With the new SBI PMU event info function, we can query the availability of the all standard SBI PMU events at boot time with a single ecall. This improves the bootime by avoiding making an SBI call for each standard PMU event. Since this function is defined only in SBI v3.0, invoke this only if the underlying SBI implementation is v3.0 or higher. Signed-off-by: Atish Patra <[email protected]> Reviewed-by: Anup Patel <[email protected]> Acked-by: Paul Walmsley <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Anup Patel <[email protected]>
1 parent 190b741 commit adffbd0

2 files changed

Lines changed: 78 additions & 0 deletions

File tree

arch/riscv/include/asm/sbi.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ enum sbi_ext_pmu_fid {
136136
SBI_EXT_PMU_COUNTER_FW_READ,
137137
SBI_EXT_PMU_COUNTER_FW_READ_HI,
138138
SBI_EXT_PMU_SNAPSHOT_SET_SHMEM,
139+
SBI_EXT_PMU_EVENT_GET_INFO,
139140
};
140141

141142
union sbi_pmu_ctr_info {
@@ -159,6 +160,14 @@ struct riscv_pmu_snapshot_data {
159160
u64 reserved[447];
160161
};
161162

163+
struct riscv_pmu_event_info {
164+
u32 event_idx;
165+
u32 output;
166+
u64 event_data;
167+
};
168+
169+
#define RISCV_PMU_EVENT_INFO_OUTPUT_MASK 0x01
170+
162171
#define RISCV_PMU_RAW_EVENT_MASK GENMASK_ULL(47, 0)
163172
#define RISCV_PMU_PLAT_FW_EVENT_MASK GENMASK_ULL(61, 0)
164173
/* SBI v3.0 allows extended hpmeventX width value */

drivers/perf/riscv_pmu_sbi.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,66 @@ static struct sbi_pmu_event_data pmu_cache_event_map[PERF_COUNT_HW_CACHE_MAX]
299299
},
300300
};
301301

302+
static int pmu_sbi_check_event_info(void)
303+
{
304+
int num_events = ARRAY_SIZE(pmu_hw_event_map) + PERF_COUNT_HW_CACHE_MAX *
305+
PERF_COUNT_HW_CACHE_OP_MAX * PERF_COUNT_HW_CACHE_RESULT_MAX;
306+
struct riscv_pmu_event_info *event_info_shmem;
307+
phys_addr_t base_addr;
308+
int i, j, k, result = 0, count = 0;
309+
struct sbiret ret;
310+
311+
event_info_shmem = kcalloc(num_events, sizeof(*event_info_shmem), GFP_KERNEL);
312+
if (!event_info_shmem)
313+
return -ENOMEM;
314+
315+
for (i = 0; i < ARRAY_SIZE(pmu_hw_event_map); i++)
316+
event_info_shmem[count++].event_idx = pmu_hw_event_map[i].event_idx;
317+
318+
for (i = 0; i < ARRAY_SIZE(pmu_cache_event_map); i++) {
319+
for (j = 0; j < ARRAY_SIZE(pmu_cache_event_map[i]); j++) {
320+
for (k = 0; k < ARRAY_SIZE(pmu_cache_event_map[i][j]); k++)
321+
event_info_shmem[count++].event_idx =
322+
pmu_cache_event_map[i][j][k].event_idx;
323+
}
324+
}
325+
326+
base_addr = __pa(event_info_shmem);
327+
if (IS_ENABLED(CONFIG_32BIT))
328+
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_EVENT_GET_INFO, lower_32_bits(base_addr),
329+
upper_32_bits(base_addr), count, 0, 0, 0);
330+
else
331+
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_EVENT_GET_INFO, base_addr, 0,
332+
count, 0, 0, 0);
333+
if (ret.error) {
334+
result = -EOPNOTSUPP;
335+
goto free_mem;
336+
}
337+
338+
for (i = 0; i < ARRAY_SIZE(pmu_hw_event_map); i++) {
339+
if (!(event_info_shmem[i].output & RISCV_PMU_EVENT_INFO_OUTPUT_MASK))
340+
pmu_hw_event_map[i].event_idx = -ENOENT;
341+
}
342+
343+
count = ARRAY_SIZE(pmu_hw_event_map);
344+
345+
for (i = 0; i < ARRAY_SIZE(pmu_cache_event_map); i++) {
346+
for (j = 0; j < ARRAY_SIZE(pmu_cache_event_map[i]); j++) {
347+
for (k = 0; k < ARRAY_SIZE(pmu_cache_event_map[i][j]); k++) {
348+
if (!(event_info_shmem[count].output &
349+
RISCV_PMU_EVENT_INFO_OUTPUT_MASK))
350+
pmu_cache_event_map[i][j][k].event_idx = -ENOENT;
351+
count++;
352+
}
353+
}
354+
}
355+
356+
free_mem:
357+
kfree(event_info_shmem);
358+
359+
return result;
360+
}
361+
302362
static void pmu_sbi_check_event(struct sbi_pmu_event_data *edata)
303363
{
304364
struct sbiret ret;
@@ -316,6 +376,15 @@ static void pmu_sbi_check_event(struct sbi_pmu_event_data *edata)
316376

317377
static void pmu_sbi_check_std_events(struct work_struct *work)
318378
{
379+
int ret;
380+
381+
if (sbi_v3_available) {
382+
ret = pmu_sbi_check_event_info();
383+
if (ret)
384+
pr_err("pmu_sbi_check_event_info failed with error %d\n", ret);
385+
return;
386+
}
387+
319388
for (int i = 0; i < ARRAY_SIZE(pmu_hw_event_map); i++)
320389
pmu_sbi_check_event(&pmu_hw_event_map[i]);
321390

0 commit comments

Comments
 (0)