summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShifrin Dmitry <dmitry.shifrin@syntacore.com>2025-11-10 14:31:40 +0300
committerAnup Patel <anup@brainfault.org>2025-12-01 11:06:36 +0530
commitc9f856e23f61e7ccbd7d8414bb98c45a5f4f04f4 (patch)
tree29c6d3d6059bbb064a56d2e181ffb6a658bd43c7
parentda05980de6ef4ed47354b9b2ac8b578f67e84039 (diff)
downloadopensbi-c9f856e23f61e7ccbd7d8414bb98c45a5f4f04f4.tar.gz
opensbi-c9f856e23f61e7ccbd7d8414bb98c45a5f4f04f4.zip
lib: sbi_pmu: Fix xINH bits configuring
Before this patch sbi_pmu_ctr_start() ignores flags received in sbi_pmu_ctr_cfg_match() including inhibit ones. To prevent it, save flags together with event_data and use them both in sbi_pmu_ctr_start(). Fixes: 1db95da2997b ("lib: sbi: sbi_pmu: fixed hw counters start for hart") Signed-off-by: Shifrin Dmitry <dmitry.shifrin@syntacore.com> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20251110113140.80561-1-dmitry.shifrin@syntacore.com Signed-off-by: Anup Patel <anup@brainfault.org>
-rw-r--r--include/sbi/sbi_ecall_interface.h9
-rw-r--r--lib/sbi/sbi_pmu.c33
2 files changed, 35 insertions, 7 deletions
diff --git a/include/sbi/sbi_ecall_interface.h b/include/sbi/sbi_ecall_interface.h
index af7a05af..76624e3f 100644
--- a/include/sbi/sbi_ecall_interface.h
+++ b/include/sbi/sbi_ecall_interface.h
@@ -291,6 +291,15 @@ struct sbi_pmu_event_info {
#define SBI_PMU_CFG_FLAG_SET_UINH (1 << 5)
#define SBI_PMU_CFG_FLAG_SET_SINH (1 << 6)
#define SBI_PMU_CFG_FLAG_SET_MINH (1 << 7)
+/* Event configuration mask */
+#define SBI_PMU_CFG_EVENT_MASK \
+ ( \
+ SBI_PMU_CFG_FLAG_SET_VUINH | \
+ SBI_PMU_CFG_FLAG_SET_VSINH | \
+ SBI_PMU_CFG_FLAG_SET_UINH | \
+ SBI_PMU_CFG_FLAG_SET_SINH | \
+ SBI_PMU_CFG_FLAG_SET_MINH \
+ )
/* Flags defined for counter start function */
#define SBI_PMU_START_FLAG_SET_INIT_VALUE (1 << 0)
diff --git a/lib/sbi/sbi_pmu.c b/lib/sbi/sbi_pmu.c
index 70c49abc..e24e485d 100644
--- a/lib/sbi/sbi_pmu.c
+++ b/lib/sbi/sbi_pmu.c
@@ -56,6 +56,14 @@ union sbi_pmu_ctr_info {
#error "Can't handle firmware counters beyond BITS_PER_LONG"
#endif
+/** HW event configuration parameters */
+struct sbi_pmu_hw_event_config {
+ /* event_data value from sbi_pmu_ctr_cfg_match() */
+ uint64_t event_data;
+ /* HW events flags from sbi_pmu_ctr_cfg_match() */
+ uint64_t flags;
+};
+
/** Per-HART state of the PMU counters */
struct sbi_pmu_hart_state {
/* HART to which this state belongs */
@@ -72,11 +80,12 @@ struct sbi_pmu_hart_state {
* and hence can optimally share the same memory.
*/
uint64_t fw_counters_data[SBI_PMU_FW_CTR_MAX];
- /* Data values from sbi_pmu_ctr_cfg_match() command which
- * is used for restoring RAW hardware events after
+ /* HW events configuration parameters from
+ * sbi_pmu_ctr_cfg_match() command which are
+ * used for restoring RAW hardware events after
* cpu suspending.
*/
- uint64_t hw_counters_data[SBI_PMU_HW_CTR_MAX];
+ struct sbi_pmu_hw_event_config hw_counters_cfg[SBI_PMU_HW_CTR_MAX];
};
/** Offset of pointer to PMU HART state in scratch space */
@@ -561,9 +570,13 @@ int sbi_pmu_ctr_start(unsigned long cbase, unsigned long cmask,
ival, bUpdate);
} else {
if (cidx >= 3) {
+ struct sbi_pmu_hw_event_config *ev_cfg =
+ &phs->hw_counters_cfg[cidx];
+
ret = pmu_update_hw_mhpmevent(&hw_event_map[cidx], cidx,
- 0, phs->active_events[cidx],
- phs->hw_counters_data[cidx]);
+ ev_cfg->flags,
+ phs->active_events[cidx],
+ ev_cfg->event_data);
if (ret)
return ret;
}
@@ -892,8 +905,14 @@ int sbi_pmu_ctr_cfg_match(unsigned long cidx_base, unsigned long cidx_mask,
} else {
ctr_idx = pmu_ctr_find_hw(phs, cidx_base, cidx_mask, flags,
event_idx, event_data);
- if (ctr_idx >= 0)
- phs->hw_counters_data[ctr_idx] = event_data;
+ if (ctr_idx >= 0) {
+ struct sbi_pmu_hw_event_config *ev_cfg =
+ &phs->hw_counters_cfg[ctr_idx];
+
+ ev_cfg->event_data = event_data;
+ /* Remove flags that are used in match call only */
+ ev_cfg->flags = flags & SBI_PMU_CFG_EVENT_MASK;
+ }
}
if (ctr_idx < 0)