lib: sbi: Map only the counters enabled in hardware
authorAtish Patra <atishp@rivosinc.com>
Fri, 7 Jan 2022 18:54:07 +0000 (10:54 -0800)
committerAnup Patel <anup@brainfault.org>
Fri, 4 Feb 2022 04:37:07 +0000 (10:07 +0530)
The counter mapping in DT may be incorrect if all the counters specified
in the mapping are actually not physically present in the hardware.
OpenSBI should only keep a mapping of counters enabled in hardware and
defined in DT. This assume that all the programmable hpmcounters are
consecutive as it doesn't make sense to build a system with sparse
hpmcounters.

Signed-off-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
lib/sbi/sbi_pmu.c

index 5b845f8..376afec 100644 (file)
@@ -181,6 +181,9 @@ static int pmu_add_hw_event_map(u32 eidx_start, u32 eidx_end, u32 cmap,
        int i = 0;
        bool is_overlap;
        struct sbi_pmu_hw_event *event = &hw_event_map[num_hw_events];
+       struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
+       int hw_ctr_avail = sbi_hart_mhpm_count(scratch);
+       uint32_t ctr_avail_mask = ((uint32_t)(~0) >> (32 - (hw_ctr_avail + 3)));
 
        /* The first two counters are reserved by priv spec */
        if (eidx_start > SBI_PMU_HW_INSTRUCTIONS && (cmap & SBI_PMU_FIXED_CTR_MASK))
@@ -208,7 +211,8 @@ static int pmu_add_hw_event_map(u32 eidx_start, u32 eidx_end, u32 cmap,
        }
 
        event->select_mask = select_mask;
-       event->counters = cmap;
+       /* Map the only the counters that are available in the hardware */
+       event->counters = cmap & ctr_avail_mask;
        event->select = select;
        num_hw_events++;