summaryrefslogtreecommitdiff
path: root/lib/sbi
diff options
context:
space:
mode:
authorVincent Chen <vincent.chen@sifive.com>2021-12-02 04:45:42 +0300
committerAnup Patel <anup@brainfault.org>2021-12-03 07:07:03 +0300
commit2428987cc06310f0e54abd4ce2efe3ed60f52245 (patch)
tree5b57280da17750b6ec2c9b3b307011a806528bbe /lib/sbi
parent14faee6916bc973b9fdb816c5f4a45096e3f645a (diff)
downloadopensbi-2428987cc06310f0e54abd4ce2efe3ed60f52245.tar.xz
lib: pmu: support the event ID encoded by a bitmap.
RISC-V privilege specification does not specify how to encode the event ID. Therefore, each platform is allowed to customize its own encoding rule. The common encoding methods are as follow, directly assigning a number to an event, or every bit in the mphmevent CSR controls one specified event or mixes the above two methods. To enable OpenSBI to support the above three encoding methods simultaneously, this patch repurpose the dt property "riscv,raw-event-to-mhpmcounters". The "riscv,raw-event-to-mhpmcounters" will describes the one or multiple raw events that could be counted by a set of counters. But, the column number of "riscv,raw-event-to-mhpmcounters" is extended from 2 to 3. The 1st column (64bit) is the ID of the raw events. The 2nd column (64bit) represents a select_mask now to represent the bits used for event ID encoding. If a platform directly encodes each raw PMU event as a unique ID, the value of select_mask will be 0xffffffff_ffffffff. Signed-off-by: Vincent Chen <vincent.chen@sifive.com> Signed-off-by: Atish Patra<atishp@rivosinc.com> Reviewed-by: Anup Patel <anup.patel@wdc.com>
Diffstat (limited to 'lib/sbi')
-rw-r--r--lib/sbi/sbi_pmu.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/lib/sbi/sbi_pmu.c b/lib/sbi/sbi_pmu.c
index 5950a20..10668a3 100644
--- a/lib/sbi/sbi_pmu.c
+++ b/lib/sbi/sbi_pmu.c
@@ -21,8 +21,16 @@ struct sbi_pmu_hw_event {
uint32_t counters;
uint32_t start_idx;
uint32_t end_idx;
- /* Event selector value used only for raw events */
+ /* Event selector value used only for raw events. The event select value
+ * can be a even id or a selector value for set of events encoded in few
+ * bits. In case latter, the bits used for encoding of the events should
+ * be zeroed out in the select value.
+ */
uint64_t select;
+ /**
+ * The select_mask indicates which bits are encoded for the event(s).
+ */
+ uint64_t select_mask;
};
/** Representation of a firmware event */
@@ -91,9 +99,9 @@ static bool pmu_event_range_overlap(struct sbi_pmu_hw_event *evtA,
}
static bool pmu_event_select_overlap(struct sbi_pmu_hw_event *evt,
- uint64_t select_val)
+ uint64_t select_val, uint64_t select_mask)
{
- if (evt->select == select_val)
+ if ((evt->select == select_val) && (evt->select_mask == select_mask))
return TRUE;
return FALSE;
@@ -168,7 +176,7 @@ int sbi_pmu_ctr_read(uint32_t cidx, unsigned long *cval)
}
static int pmu_add_hw_event_map(u32 eidx_start, u32 eidx_end, u32 cmap,
- uint64_t select)
+ uint64_t select, uint64_t select_mask)
{
int i = 0;
bool is_overlap;
@@ -191,13 +199,15 @@ static int pmu_add_hw_event_map(u32 eidx_start, u32 eidx_end, u32 cmap,
for (i = 0; i < num_hw_events; i++) {
if (eidx_start == SBI_PMU_EVENT_RAW_IDX)
/* All raw events have same event idx. Just do sanity check on select */
- is_overlap = pmu_event_select_overlap(&hw_event_map[i], select);
+ is_overlap = pmu_event_select_overlap(&hw_event_map[i],
+ select, select_mask);
else
is_overlap = pmu_event_range_overlap(&hw_event_map[i], event);
if (is_overlap)
goto reset_event;
}
+ event->select_mask = select_mask;
event->counters = cmap;
event->select = select;
num_hw_events++;
@@ -221,13 +231,13 @@ int sbi_pmu_add_hw_event_counter_map(u32 eidx_start, u32 eidx_end, u32 cmap)
eidx_end == SBI_PMU_EVENT_RAW_IDX)
return SBI_EINVAL;
- return pmu_add_hw_event_map(eidx_start, eidx_end, cmap, 0);
+ return pmu_add_hw_event_map(eidx_start, eidx_end, cmap, 0, 0);
}
-int sbi_pmu_add_raw_event_counter_map(uint64_t select, u32 cmap)
+int sbi_pmu_add_raw_event_counter_map(uint64_t select, uint64_t select_mask, u32 cmap)
{
return pmu_add_hw_event_map(SBI_PMU_EVENT_RAW_IDX,
- SBI_PMU_EVENT_RAW_IDX, cmap, select);
+ SBI_PMU_EVENT_RAW_IDX, cmap, select, select_mask);
}
static int pmu_ctr_enable_irq_hw(int ctr_idx)
@@ -514,9 +524,13 @@ static int pmu_ctr_find_hw(unsigned long cbase, unsigned long cmask, unsigned lo
continue;
/* For raw events, event data is used as the select value */
- if ((event_idx == SBI_PMU_EVENT_RAW_IDX) && temp->select != data)
- continue;
+ if (event_idx == SBI_PMU_EVENT_RAW_IDX) {
+ uint64_t select_mask = temp->select_mask;
+ /* The non-event map bits of data should match the selector */
+ if (temp->select != (data & select_mask))
+ continue;
+ }
/* Fixed counters should not be part of the search */
ctr_mask = temp->counters & (cmask << cbase) &
(~SBI_PMU_FIXED_CTR_MASK);
@@ -546,7 +560,6 @@ static int pmu_ctr_find_hw(unsigned long cbase, unsigned long cmask, unsigned lo
else
return SBI_EFAIL;
}
-
ret = pmu_update_hw_mhpmevent(temp, ctr_idx, flags, event_idx, data);
if (!ret)