summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAtish Patra <atishp@rivosinc.com>2022-01-07 21:54:07 +0300
committerAnup Patel <anup@brainfault.org>2022-02-04 07:37:07 +0300
commit632f59392bbaa05176376b7d7a9f77f611816614 (patch)
tree05bb7435d4374cc07fdabfa72a049f9fa352a2f9
parent5d025eb2353550eadbd2fa9b8083a92fe9b07bd9 (diff)
downloadopensbi-632f59392bbaa05176376b7d7a9f77f611816614.tar.xz
lib: sbi: Map only the counters enabled in hardware
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>
-rw-r--r--lib/sbi/sbi_pmu.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/lib/sbi/sbi_pmu.c b/lib/sbi/sbi_pmu.c
index 5b845f8..376afec 100644
--- a/lib/sbi/sbi_pmu.c
+++ b/lib/sbi/sbi_pmu.c
@@ -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++;