mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2025-08-25 07:41:42 +01:00
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 <apatel@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Atish Patra <atishp@rivosinc.com>
This commit is contained in:
@@ -19,9 +19,6 @@
|
|||||||
/* Maximum number of hardware events that can mapped by OpenSBI */
|
/* Maximum number of hardware events that can mapped by OpenSBI */
|
||||||
#define SBI_PMU_HW_EVENT_MAX 256
|
#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 */
|
/* Counter related macros */
|
||||||
#define SBI_PMU_FW_CTR_MAX 16
|
#define SBI_PMU_FW_CTR_MAX 16
|
||||||
#define SBI_PMU_HW_CTR_MAX 32
|
#define SBI_PMU_HW_CTR_MAX 32
|
||||||
|
@@ -33,15 +33,6 @@ struct sbi_pmu_hw_event {
|
|||||||
uint64_t select_mask;
|
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 */
|
/* Information about PMU counters as per SBI specification */
|
||||||
union sbi_pmu_ctr_info {
|
union sbi_pmu_ctr_info {
|
||||||
unsigned long value;
|
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 */
|
/* counter to enabled event mapping */
|
||||||
static uint32_t active_events[SBI_HARTMASK_MAX_BITS][SBI_PMU_HW_CTR_MAX + SBI_PMU_FW_CTR_MAX];
|
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 */
|
/* Bitmap of firmware counters started on each HART */
|
||||||
static struct sbi_pmu_fw_event fw_event_map[SBI_HARTMASK_MAX_BITS][SBI_PMU_FW_EVENT_MAX] = {0};
|
#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 */
|
/* Maximum number of hardware events available */
|
||||||
static uint32_t num_hw_events;
|
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;
|
int event_idx_type;
|
||||||
uint32_t event_code;
|
uint32_t event_code;
|
||||||
u32 hartid = current_hartid();
|
u32 hartid = current_hartid();
|
||||||
struct sbi_pmu_fw_event *fevent;
|
|
||||||
|
|
||||||
event_idx_type = pmu_ctr_validate(cidx, &event_code);
|
event_idx_type = pmu_ctr_validate(cidx, &event_code);
|
||||||
if (event_idx_type != SBI_PMU_EVENT_TYPE_FW)
|
if (event_idx_type != SBI_PMU_EVENT_TYPE_FW)
|
||||||
return SBI_EINVAL;
|
return SBI_EINVAL;
|
||||||
|
|
||||||
fevent = &fw_event_map[hartid][event_code];
|
*cval = fw_counters_value[hartid][cidx - num_hw_ctrs];
|
||||||
*cval = fevent->curr_count;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -333,16 +328,13 @@ skip_inhibit_update:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pmu_ctr_start_fw(uint32_t cidx, uint32_t fw_evt_code,
|
static int pmu_ctr_start_fw(uint32_t cidx, uint64_t ival, bool ival_update)
|
||||||
uint64_t ival, bool ival_update)
|
|
||||||
{
|
{
|
||||||
u32 hartid = current_hartid();
|
u32 hartid = current_hartid();
|
||||||
struct sbi_pmu_fw_event *fevent;
|
|
||||||
|
|
||||||
fevent = &fw_event_map[hartid][fw_evt_code];
|
|
||||||
if (ival_update)
|
if (ival_update)
|
||||||
fevent->curr_count = ival;
|
fw_counters_value[hartid][cidx - num_hw_ctrs] = ival;
|
||||||
fevent->bStarted = TRUE;
|
fw_counters_started[hartid] |= BIT(cidx - num_hw_ctrs);
|
||||||
|
|
||||||
return 0;
|
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 the start operation for other counters */
|
||||||
continue;
|
continue;
|
||||||
else if (event_idx_type == SBI_PMU_EVENT_TYPE_FW)
|
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
|
else
|
||||||
ret = pmu_ctr_start_hw(cidx, ival, bUpdate);
|
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;
|
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_counters_started[current_hartid()] &= ~BIT(cidx - num_hw_ctrs);
|
||||||
|
|
||||||
fw_event_map[hartid][fw_evt_code].bStarted = FALSE;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -444,7 +434,7 @@ int sbi_pmu_ctr_stop(unsigned long cbase, unsigned long cmask,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
else if (event_idx_type == SBI_PMU_EVENT_TYPE_FW)
|
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
|
else
|
||||||
ret = pmu_ctr_stop_hw(cidx);
|
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;
|
int ctr_idx = SBI_ENOTSUPP;
|
||||||
u32 hartid = current_hartid();
|
u32 hartid = current_hartid();
|
||||||
int event_type;
|
int event_type;
|
||||||
struct sbi_pmu_fw_event *fevent;
|
|
||||||
uint32_t fw_evt_code;
|
|
||||||
|
|
||||||
/* Do a basic sanity check of counter base & mask */
|
/* Do a basic sanity check of counter base & mask */
|
||||||
if ((cidx_base + sbi_fls(cidx_mask)) >= total_ctrs)
|
if ((cidx_base + sbi_fls(cidx_mask)) >= total_ctrs)
|
||||||
@@ -665,30 +653,36 @@ skip_match:
|
|||||||
if (flags & SBI_PMU_CFG_FLAG_AUTO_START)
|
if (flags & SBI_PMU_CFG_FLAG_AUTO_START)
|
||||||
pmu_ctr_start_hw(ctr_idx, 0, false);
|
pmu_ctr_start_hw(ctr_idx, 0, false);
|
||||||
} else if (event_type == SBI_PMU_EVENT_TYPE_FW) {
|
} 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)
|
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)
|
if (flags & SBI_PMU_CFG_FLAG_AUTO_START)
|
||||||
fevent->bStarted = TRUE;
|
fw_counters_started[hartid] |= BIT(ctr_idx - num_hw_ctrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctr_idx;
|
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();
|
u32 cidx, hartid = current_hartid();
|
||||||
struct sbi_pmu_fw_event *fevent;
|
uint64_t *fcounter = NULL;
|
||||||
|
|
||||||
|
if (likely(!fw_counters_started[hartid]))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (unlikely(fw_id >= SBI_PMU_FW_MAX))
|
if (unlikely(fw_id >= SBI_PMU_FW_MAX))
|
||||||
return SBI_EINVAL;
|
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 (fcounter)
|
||||||
if (unlikely(fevent->bStarted))
|
(*fcounter)++;
|
||||||
fevent->curr_count++;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -735,9 +729,9 @@ static void pmu_reset_event_map(u32 hartid)
|
|||||||
/* Initialize the counter to event mapping table */
|
/* Initialize the counter to event mapping table */
|
||||||
for (j = 3; j < total_ctrs; j++)
|
for (j = 3; j < total_ctrs; j++)
|
||||||
active_events[hartid][j] = SBI_PMU_EVENT_IDX_INVALID;
|
active_events[hartid][j] = SBI_PMU_EVENT_IDX_INVALID;
|
||||||
for (j = 0; j < SBI_PMU_FW_EVENT_MAX; j++)
|
for (j = 0; j < SBI_PMU_FW_CTR_MAX; j++)
|
||||||
sbi_memset(&fw_event_map[hartid][j], 0,
|
fw_counters_value[hartid][j] = 0;
|
||||||
sizeof(struct sbi_pmu_fw_event));
|
fw_counters_started[hartid] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sbi_pmu_exit(struct sbi_scratch *scratch)
|
void sbi_pmu_exit(struct sbi_scratch *scratch)
|
||||||
|
Reference in New Issue
Block a user