From c9f856e23f61e7ccbd7d8414bb98c45a5f4f04f4 Mon Sep 17 00:00:00 2001 From: Shifrin Dmitry Date: Mon, 10 Nov 2025 14:31:40 +0300 Subject: [PATCH] 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 Reviewed-by: Anup Patel Link: https://lore.kernel.org/r/20251110113140.80561-1-dmitry.shifrin@syntacore.com Signed-off-by: Anup Patel --- include/sbi/sbi_ecall_interface.h | 9 +++++++++ lib/sbi/sbi_pmu.c | 33 ++++++++++++++++++++++++------- 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)