6666 */
6767#define DSU_PMU_IDX_CYCLE_COUNTER 31
6868
69- /* All event counters are 32bit, with a 64bit Cycle counter */
70- #define DSU_PMU_COUNTER_WIDTH (idx ) \
71- (((idx) == DSU_PMU_IDX_CYCLE_COUNTER) ? 64 : 32)
72-
73- #define DSU_PMU_COUNTER_MASK (idx ) \
74- GENMASK_ULL((DSU_PMU_COUNTER_WIDTH((idx)) - 1), 0)
75-
7669#define DSU_EXT_ATTR (_name , _func , _config ) \
7770 (&((struct dev_ext_attribute[]) { \
7871 { \
@@ -107,6 +100,7 @@ struct dsu_hw_events {
107100 * @num_counters : Number of event counters implemented by the PMU,
108101 * excluding the cycle counter.
109102 * @irq : Interrupt line for counter overflow.
103+ * @has_32b_pmevcntr : Are the non-cycle counters only 32-bit?
110104 * @cpmceid_bitmap : Bitmap for the availability of architected common
111105 * events (event_code < 0x40).
112106 */
@@ -120,6 +114,7 @@ struct dsu_pmu {
120114 struct hlist_node cpuhp_node ;
121115 s8 num_counters ;
122116 int irq ;
117+ bool has_32b_pmevcntr ;
123118 DECLARE_BITMAP (cpmceid_bitmap , DSU_PMU_MAX_COMMON_EVENTS );
124119};
125120
@@ -328,6 +323,11 @@ static inline void dsu_pmu_set_event(struct dsu_pmu *dsu_pmu,
328323 raw_spin_unlock_irqrestore (& dsu_pmu -> pmu_lock , flags );
329324}
330325
326+ static u64 dsu_pmu_counter_mask (struct hw_perf_event * hw )
327+ {
328+ return (hw -> flags && hw -> idx != DSU_PMU_IDX_CYCLE_COUNTER ) ? U32_MAX : U64_MAX ;
329+ }
330+
331331static void dsu_pmu_event_update (struct perf_event * event )
332332{
333333 struct hw_perf_event * hwc = & event -> hw ;
@@ -339,7 +339,7 @@ static void dsu_pmu_event_update(struct perf_event *event)
339339 new_count = dsu_pmu_read_counter (event );
340340 } while (local64_cmpxchg (& hwc -> prev_count , prev_count , new_count ) !=
341341 prev_count );
342- delta = (new_count - prev_count ) & DSU_PMU_COUNTER_MASK (hwc -> idx );
342+ delta = (new_count - prev_count ) & dsu_pmu_counter_mask (hwc );
343343 local64_add (delta , & event -> count );
344344}
345345
@@ -362,8 +362,7 @@ static inline u32 dsu_pmu_get_reset_overflow(void)
362362 */
363363static void dsu_pmu_set_event_period (struct perf_event * event )
364364{
365- int idx = event -> hw .idx ;
366- u64 val = DSU_PMU_COUNTER_MASK (idx ) >> 1 ;
365+ u64 val = dsu_pmu_counter_mask (& event -> hw ) >> 1 ;
367366
368367 local64_set (& event -> hw .prev_count , val );
369368 dsu_pmu_write_counter (event , val );
@@ -564,6 +563,7 @@ static int dsu_pmu_event_init(struct perf_event *event)
564563 return - EINVAL ;
565564
566565 event -> hw .config_base = event -> attr .config ;
566+ event -> hw .flags = dsu_pmu -> has_32b_pmevcntr ;
567567 return 0 ;
568568}
569569
@@ -664,6 +664,10 @@ static void dsu_pmu_probe_pmu(struct dsu_pmu *dsu_pmu)
664664 cpmceid [1 ] = __dsu_pmu_read_pmceid (1 );
665665 bitmap_from_arr32 (dsu_pmu -> cpmceid_bitmap , cpmceid ,
666666 DSU_PMU_MAX_COMMON_EVENTS );
667+ /* Newer DSUs have 64-bit counters */
668+ __dsu_pmu_write_counter (0 , U64_MAX );
669+ if (__dsu_pmu_read_counter (0 ) != U64_MAX )
670+ dsu_pmu -> has_32b_pmevcntr = true;
667671}
668672
669673static void dsu_pmu_set_active_cpu (int cpu , struct dsu_pmu * dsu_pmu )
0 commit comments