From: Anup Patel Date: Wed, 24 Aug 2022 07:57:19 +0000 (+0530) Subject: lib: sbi_pmu: Simplify FW counters to reduce memory usage X-Git-Tag: v1.2~84 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c9b388d578647c3283aea03f74bf1251503a58f0;p=platform%2Fkernel%2Fopensbi.git lib: sbi_pmu: Simplify FW counters to reduce memory usage 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 Reviewed-by: Andrew Jones Reviewed-by: Atish Patra --- 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)