History

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.

Atish Patra committed 1 year ago

Commit adffbd01 parent 190b7412 files · +78 −0Browse files

Unified · Split

2 files
  1. arch/riscv/include/asm/sbi.h +9 −0
  2. drivers/perf/riscv_pmu_sbi.c +69 −0
arch/riscv/include/asm/sbi.h+9−0
@@ -136,6 +136,7 @@ enum sbi_ext_pmu_fid { · 135 unmodified lines
136 SBI_EXT_PMU_COUNTER_FW_READ,136 SBI_EXT_PMU_COUNTER_FW_READ,
137 SBI_EXT_PMU_COUNTER_FW_READ_HI,137 SBI_EXT_PMU_COUNTER_FW_READ_HI,
138 SBI_EXT_PMU_SNAPSHOT_SET_SHMEM,138 SBI_EXT_PMU_SNAPSHOT_SET_SHMEM,
139 SBI_EXT_PMU_EVENT_GET_INFO,
139};140};
140 141
141union sbi_pmu_ctr_info {142union sbi_pmu_ctr_info {
@@ -159,6 +160,14 @@ struct riscv_pmu_snapshot_data { · 17 unmodified lines
159 u64 reserved[447];160 u64 reserved[447];
160};161};
161 162
163struct 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
162#define RISCV_PMU_RAW_EVENT_MASK GENMASK_ULL(47, 0)171#define RISCV_PMU_RAW_EVENT_MASK GENMASK_ULL(47, 0)
163#define RISCV_PMU_PLAT_FW_EVENT_MASK GENMASK_ULL(61, 0)172#define RISCV_PMU_PLAT_FW_EVENT_MASK GENMASK_ULL(61, 0)
164/* SBI v3.0 allows extended hpmeventX width value */173/* SBI v3.0 allows extended hpmeventX width value */
drivers/perf/riscv_pmu_sbi.c+69−0
@@ -299,6 +299,66 @@ static struct sbi_pmu_event_data pmu_cache_event_map[PERF_COUNT_HW_CACHE_MAX] · 298 unmodified lines
299 },299 },
300};300};
301 301
302static 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
356free_mem:
357 kfree(event_info_shmem);
358
359 return result;
360}
361
302static void pmu_sbi_check_event(struct sbi_pmu_event_data *edata)362static void pmu_sbi_check_event(struct sbi_pmu_event_data *edata)
303{363{
304 struct sbiret ret;364 struct sbiret ret;
@@ -316,6 +376,15 @@ static void pmu_sbi_check_event(struct sbi_pmu_event_data *edata) · 11 unmodified lines
316 376
317static void pmu_sbi_check_std_events(struct work_struct *work)377static void pmu_sbi_check_std_events(struct work_struct *work)
318{378{
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
319 for (int i = 0; i < ARRAY_SIZE(pmu_hw_event_map); i++)388 for (int i = 0; i < ARRAY_SIZE(pmu_hw_event_map); i++)
320 pmu_sbi_check_event(&pmu_hw_event_map[i]);389 pmu_sbi_check_event(&pmu_hw_event_map[i]);
321 390

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t