[PATCH 4/7] lib: sbi_pmu: Simplify FW counters to reduce memory usage
Anup Patel
apatel at ventanamicro.com
Wed Aug 24 21:51:41 PDT 2022
Currently, we have 32 elements (i.e. SBI_PMU_FW_EVENT_MAX) array of
"struct sbi_pmu_fw_event" for each of 128 possible HARTs
(i.e. SBI_HARTMASK_MAX_BITS).
To reduce memory usage of OpenSBI, we update FW counter implementation
as follows:
1) Remove SBI_PMU_FW_EVENT_MAX
2) Remove "struct sbi_pmu_fw_event"
3) Create per-HART bitmap of XLEN bits to track FW counters
which are started on each HART
4) Create per-HART uint64_t array to track values of FW
counters on each HART.
Signed-off-by: Anup Patel <apatel at ventanamicro.com>
Reviewed-by: Andrew Jones <ajones at ventanamicro.com>
---
include/sbi/sbi_pmu.h | 3 --
lib/sbi/sbi_pmu.c | 78 ++++++++++++++++++++-----------------------
2 files changed, 36 insertions(+), 45 deletions(-)
diff --git a/include/sbi/sbi_pmu.h b/include/sbi/sbi_pmu.h
index 34336f7..39cf007 100644
--- a/include/sbi/sbi_pmu.h
+++ b/include/sbi/sbi_pmu.h
@@ -19,9 +19,6 @@
/* Maximum number of hardware events that can mapped by OpenSBI */
#define SBI_PMU_HW_EVENT_MAX 256
-/* Maximum number of firmware events that can mapped by OpenSBI */
-#define SBI_PMU_FW_EVENT_MAX 32
-
/* Counter related macros */
#define SBI_PMU_FW_CTR_MAX 16
#define SBI_PMU_HW_CTR_MAX 32
diff --git a/lib/sbi/sbi_pmu.c b/lib/sbi/sbi_pmu.c
index 1c01d34..26c9406 100644
--- a/lib/sbi/sbi_pmu.c
+++ b/lib/sbi/sbi_pmu.c
@@ -33,15 +33,6 @@ struct sbi_pmu_hw_event {
uint64_t select_mask;
};
-/** Representation of a firmware event */
-struct sbi_pmu_fw_event {
- /* Current value of the counter */
- uint64_t curr_count;
-
- /* A flag indicating pmu event monitoring is started */
- bool bStarted;
-};
-
/* Information about PMU counters as per SBI specification */
union sbi_pmu_ctr_info {
unsigned long value;
@@ -63,8 +54,14 @@ static struct sbi_pmu_hw_event hw_event_map[SBI_PMU_HW_EVENT_MAX] = {0};
/* counter to enabled event mapping */
static uint32_t active_events[SBI_HARTMASK_MAX_BITS][SBI_PMU_HW_CTR_MAX + SBI_PMU_FW_CTR_MAX];
-/* Contains all the information about firmwares events */
-static struct sbi_pmu_fw_event fw_event_map[SBI_HARTMASK_MAX_BITS][SBI_PMU_FW_EVENT_MAX] = {0};
+/* Bitmap of firmware counters started on each HART */
+#if SBI_PMU_FW_CTR_MAX >= BITS_PER_LONG
+#error "Can't handle firmware counters beyond BITS_PER_LONG"
+#endif
+static unsigned long fw_counters_started[SBI_HARTMASK_MAX_BITS];
+
+/* Values of firmwares counters on each HART */
+static uint64_t fw_counters_value[SBI_HARTMASK_MAX_BITS][SBI_PMU_FW_CTR_MAX] = {0};
/* Maximum number of hardware events available */
static uint32_t num_hw_events;
@@ -172,14 +169,12 @@ int sbi_pmu_ctr_fw_read(uint32_t cidx, uint64_t *cval)
int event_idx_type;
uint32_t event_code;
u32 hartid = current_hartid();
- struct sbi_pmu_fw_event *fevent;
event_idx_type = pmu_ctr_validate(cidx, &event_code);
if (event_idx_type != SBI_PMU_EVENT_TYPE_FW)
return SBI_EINVAL;
- fevent = &fw_event_map[hartid][event_code];
- *cval = fevent->curr_count;
+ *cval = fw_counters_value[hartid][cidx - num_hw_ctrs];
return 0;
}
@@ -333,16 +328,13 @@ skip_inhibit_update:
return 0;
}
-static int pmu_ctr_start_fw(uint32_t cidx, uint32_t fw_evt_code,
- uint64_t ival, bool ival_update)
+static int pmu_ctr_start_fw(uint32_t cidx, uint64_t ival, bool ival_update)
{
u32 hartid = current_hartid();
- struct sbi_pmu_fw_event *fevent;
- fevent = &fw_event_map[hartid][fw_evt_code];
if (ival_update)
- fevent->curr_count = ival;
- fevent->bStarted = TRUE;
+ fw_counters_value[hartid][cidx - num_hw_ctrs] = ival;
+ fw_counters_started[hartid] |= BIT(cidx - num_hw_ctrs);
return 0;
}
@@ -369,7 +361,7 @@ int sbi_pmu_ctr_start(unsigned long cbase, unsigned long cmask,
/* Continue the start operation for other counters */
continue;
else if (event_idx_type == SBI_PMU_EVENT_TYPE_FW)
- ret = pmu_ctr_start_fw(cidx, event_code, ival, bUpdate);
+ ret = pmu_ctr_start_fw(cidx, ival, bUpdate);
else
ret = pmu_ctr_start_hw(cidx, ival, bUpdate);
}
@@ -399,11 +391,9 @@ static int pmu_ctr_stop_hw(uint32_t cidx)
return SBI_EALREADY_STOPPED;
}
-static int pmu_ctr_stop_fw(uint32_t cidx, uint32_t fw_evt_code)
+static int pmu_ctr_stop_fw(uint32_t cidx)
{
- u32 hartid = current_hartid();
-
- fw_event_map[hartid][fw_evt_code].bStarted = FALSE;
+ fw_counters_started[current_hartid()] &= ~BIT(cidx - num_hw_ctrs);
return 0;
}
@@ -444,7 +434,7 @@ int sbi_pmu_ctr_stop(unsigned long cbase, unsigned long cmask,
continue;
else if (event_idx_type == SBI_PMU_EVENT_TYPE_FW)
- ret = pmu_ctr_stop_fw(cidx, event_code);
+ ret = pmu_ctr_stop_fw(cidx);
else
ret = pmu_ctr_stop_hw(cidx);
@@ -624,8 +614,6 @@ int sbi_pmu_ctr_cfg_match(unsigned long cidx_base, unsigned long cidx_mask,
int ctr_idx = SBI_ENOTSUPP;
u32 hartid = current_hartid();
int event_type;
- struct sbi_pmu_fw_event *fevent;
- uint32_t fw_evt_code;
/* Do a basic sanity check of counter base & mask */
if ((cidx_base + sbi_fls(cidx_mask)) >= total_ctrs)
@@ -665,30 +653,36 @@ skip_match:
if (flags & SBI_PMU_CFG_FLAG_AUTO_START)
pmu_ctr_start_hw(ctr_idx, 0, false);
} else if (event_type == SBI_PMU_EVENT_TYPE_FW) {
- fw_evt_code = get_cidx_code(event_idx);
- fevent = &fw_event_map[hartid][fw_evt_code];
if (flags & SBI_PMU_CFG_FLAG_CLEAR_VALUE)
- fevent->curr_count = 0;
+ fw_counters_value[hartid][ctr_idx - num_hw_ctrs] = 0;
if (flags & SBI_PMU_CFG_FLAG_AUTO_START)
- fevent->bStarted = TRUE;
+ fw_counters_started[hartid] |= BIT(ctr_idx - num_hw_ctrs);
}
return ctr_idx;
}
-inline int sbi_pmu_ctr_incr_fw(enum sbi_pmu_fw_event_code_id fw_id)
+int sbi_pmu_ctr_incr_fw(enum sbi_pmu_fw_event_code_id fw_id)
{
- u32 hartid = current_hartid();
- struct sbi_pmu_fw_event *fevent;
+ u32 cidx, hartid = current_hartid();
+ uint64_t *fcounter = NULL;
+
+ if (likely(!fw_counters_started[hartid]))
+ return 0;
if (unlikely(fw_id >= SBI_PMU_FW_MAX))
return SBI_EINVAL;
- fevent = &fw_event_map[hartid][fw_id];
+ for (cidx = num_hw_ctrs; cidx < total_ctrs; cidx++) {
+ if (get_cidx_code(active_events[hartid][cidx]) == fw_id &&
+ (fw_counters_started[hartid] & BIT(cidx - num_hw_ctrs))) {
+ fcounter = &fw_counters_value[hartid][cidx - num_hw_ctrs];
+ break;
+ }
+ }
- /* PMU counters will be only enabled during performance debugging */
- if (unlikely(fevent->bStarted))
- fevent->curr_count++;
+ if (fcounter)
+ (*fcounter)++;
return 0;
}
@@ -735,9 +729,9 @@ static void pmu_reset_event_map(u32 hartid)
/* Initialize the counter to event mapping table */
for (j = 3; j < total_ctrs; j++)
active_events[hartid][j] = SBI_PMU_EVENT_IDX_INVALID;
- for (j = 0; j < SBI_PMU_FW_EVENT_MAX; j++)
- sbi_memset(&fw_event_map[hartid][j], 0,
- sizeof(struct sbi_pmu_fw_event));
+ for (j = 0; j < SBI_PMU_FW_CTR_MAX; j++)
+ fw_counters_value[hartid][j] = 0;
+ fw_counters_started[hartid] = 0;
}
void sbi_pmu_exit(struct sbi_scratch *scratch)
--
2.34.1
More information about the opensbi
mailing list