@@ -76,7 +76,6 @@ static inline int ctr_stcctm(enum cpumf_ctr_set set, u64 range, u64 *dest)
7676}
7777
7878struct cpu_cf_events {
79- struct cpumf_ctr_info info ;
8079 atomic_t ctr_set [CPUMF_CTR_SET_MAX ];
8180 u64 state ; /* For perf_event_open SVC */
8281 u64 dev_state ; /* For /dev/hwctr */
@@ -95,6 +94,15 @@ static DEFINE_PER_CPU(struct cpu_cf_events, cpu_cf_events);
9594static unsigned int cfdiag_cpu_speed ; /* CPU speed for CF_DIAG trailer */
9695static debug_info_t * cf_dbg ;
9796
97+ /*
98+ * The CPU Measurement query counter information instruction contains
99+ * information which varies per machine generation, but is constant and
100+ * does not change when running on a particular machine, such as counter
101+ * first and second version number. This is needed to determine the size
102+ * of counter sets. Extract this information at device driver initialization.
103+ */
104+ static struct cpumf_ctr_info cpumf_ctr_info ;
105+
98106#define CF_DIAG_CTRSET_DEF 0xfeef /* Counter set header mark */
99107 /* interval in seconds */
100108
@@ -167,11 +175,10 @@ struct cf_trailer_entry { /* CPU-M CF_DIAG trailer (64 byte) */
167175/* Create the trailer data at the end of a page. */
168176static void cfdiag_trailer (struct cf_trailer_entry * te )
169177{
170- struct cpu_cf_events * cpuhw = this_cpu_ptr (& cpu_cf_events );
171178 struct cpuid cpuid ;
172179
173- te -> cfvn = cpuhw -> info .cfvn ; /* Counter version numbers */
174- te -> csvn = cpuhw -> info .csvn ;
180+ te -> cfvn = cpumf_ctr_info .cfvn ; /* Counter version numbers */
181+ te -> csvn = cpumf_ctr_info .csvn ;
175182
176183 get_cpu_id (& cpuid ); /* Machine type */
177184 te -> mach_type = cpuid .machine ;
@@ -184,50 +191,60 @@ static void cfdiag_trailer(struct cf_trailer_entry *te)
184191}
185192
186193/*
187- * Return the maximum possible counter set size (in number of 8 byte counters)
188- * depending on type and model number.
194+ * The number of counters per counter set varies between machine generations,
195+ * but is constant when running on a particular machine generation.
196+ * Determine each counter set size at device driver initialization and
197+ * retrieve it later.
189198 */
190- static size_t cpum_cf_ctrset_size ( enum cpumf_ctr_set ctrset ,
191- struct cpumf_ctr_info * info )
199+ static size_t cpumf_ctr_setsizes [ CPUMF_CTR_SET_MAX ];
200+ static void cpum_cf_make_setsize ( enum cpumf_ctr_set ctrset )
192201{
193202 size_t ctrset_size = 0 ;
194203
195204 switch (ctrset ) {
196205 case CPUMF_CTR_SET_BASIC :
197- if (info -> cfvn >= 1 )
206+ if (cpumf_ctr_info . cfvn >= 1 )
198207 ctrset_size = 6 ;
199208 break ;
200209 case CPUMF_CTR_SET_USER :
201- if (info -> cfvn == 1 )
210+ if (cpumf_ctr_info . cfvn == 1 )
202211 ctrset_size = 6 ;
203- else if (info -> cfvn >= 3 )
212+ else if (cpumf_ctr_info . cfvn >= 3 )
204213 ctrset_size = 2 ;
205214 break ;
206215 case CPUMF_CTR_SET_CRYPTO :
207- if (info -> csvn >= 1 && info -> csvn <= 5 )
216+ if (cpumf_ctr_info . csvn >= 1 && cpumf_ctr_info . csvn <= 5 )
208217 ctrset_size = 16 ;
209- else if (info -> csvn == 6 || info -> csvn == 7 )
218+ else if (cpumf_ctr_info . csvn == 6 || cpumf_ctr_info . csvn == 7 )
210219 ctrset_size = 20 ;
211220 break ;
212221 case CPUMF_CTR_SET_EXT :
213- if (info -> csvn == 1 )
222+ if (cpumf_ctr_info . csvn == 1 )
214223 ctrset_size = 32 ;
215- else if (info -> csvn == 2 )
224+ else if (cpumf_ctr_info . csvn == 2 )
216225 ctrset_size = 48 ;
217- else if (info -> csvn >= 3 && info -> csvn <= 5 )
226+ else if (cpumf_ctr_info . csvn >= 3 && cpumf_ctr_info . csvn <= 5 )
218227 ctrset_size = 128 ;
219- else if (info -> csvn == 6 || info -> csvn == 7 )
228+ else if (cpumf_ctr_info . csvn == 6 || cpumf_ctr_info . csvn == 7 )
220229 ctrset_size = 160 ;
221230 break ;
222231 case CPUMF_CTR_SET_MT_DIAG :
223- if (info -> csvn > 3 )
232+ if (cpumf_ctr_info . csvn > 3 )
224233 ctrset_size = 48 ;
225234 break ;
226235 case CPUMF_CTR_SET_MAX :
227236 break ;
228237 }
238+ cpumf_ctr_setsizes [ctrset ] = ctrset_size ;
239+ }
229240
230- return ctrset_size ;
241+ /*
242+ * Return the maximum possible counter set size (in number of 8 byte counters)
243+ * depending on type and model number.
244+ */
245+ static size_t cpum_cf_read_setsize (enum cpumf_ctr_set ctrset )
246+ {
247+ return cpumf_ctr_setsizes [ctrset ];
231248}
232249
233250/* Read a counter set. The counter set number determines the counter set and
@@ -248,14 +265,13 @@ static size_t cpum_cf_ctrset_size(enum cpumf_ctr_set ctrset,
248265static size_t cfdiag_getctrset (struct cf_ctrset_entry * ctrdata , int ctrset ,
249266 size_t room , bool error_ok )
250267{
251- struct cpu_cf_events * cpuhw = this_cpu_ptr (& cpu_cf_events );
252268 size_t ctrset_size , need = 0 ;
253269 int rc = 3 ; /* Assume write failure */
254270
255271 ctrdata -> def = CF_DIAG_CTRSET_DEF ;
256272 ctrdata -> set = ctrset ;
257273 ctrdata -> res1 = 0 ;
258- ctrset_size = cpum_cf_ctrset_size (ctrset , & cpuhw -> info );
274+ ctrset_size = cpum_cf_read_setsize (ctrset );
259275
260276 if (ctrset_size ) { /* Save data */
261277 need = ctrset_size * sizeof (u64 ) + sizeof (* ctrdata );
@@ -269,10 +285,6 @@ static size_t cfdiag_getctrset(struct cf_ctrset_entry *ctrdata, int ctrset,
269285 need = 0 ;
270286 }
271287
272- debug_sprintf_event (cf_dbg , 3 ,
273- "%s ctrset %d ctrset_size %zu cfvn %d csvn %d"
274- " need %zd rc %d\n" , __func__ , ctrset , ctrset_size ,
275- cpuhw -> info .cfvn , cpuhw -> info .csvn , need , rc );
276288 return need ;
277289}
278290
@@ -380,37 +392,34 @@ static enum cpumf_ctr_set get_counter_set(u64 event)
380392static int validate_ctr_version (const struct hw_perf_event * hwc ,
381393 enum cpumf_ctr_set set )
382394{
383- struct cpu_cf_events * cpuhw ;
384- int err = 0 ;
385395 u16 mtdiag_ctl ;
386-
387- cpuhw = & get_cpu_var (cpu_cf_events );
396+ int err = 0 ;
388397
389398 /* check required version for counter sets */
390399 switch (set ) {
391400 case CPUMF_CTR_SET_BASIC :
392401 case CPUMF_CTR_SET_USER :
393- if (cpuhw -> info .cfvn < 1 )
402+ if (cpumf_ctr_info .cfvn < 1 )
394403 err = - EOPNOTSUPP ;
395404 break ;
396405 case CPUMF_CTR_SET_CRYPTO :
397- if ((cpuhw -> info .csvn >= 1 && cpuhw -> info .csvn <= 5 &&
406+ if ((cpumf_ctr_info .csvn >= 1 && cpumf_ctr_info .csvn <= 5 &&
398407 hwc -> config > 79 ) ||
399- (cpuhw -> info .csvn >= 6 && hwc -> config > 83 ))
408+ (cpumf_ctr_info .csvn >= 6 && hwc -> config > 83 ))
400409 err = - EOPNOTSUPP ;
401410 break ;
402411 case CPUMF_CTR_SET_EXT :
403- if (cpuhw -> info .csvn < 1 )
412+ if (cpumf_ctr_info .csvn < 1 )
404413 err = - EOPNOTSUPP ;
405- if ((cpuhw -> info .csvn == 1 && hwc -> config > 159 ) ||
406- (cpuhw -> info .csvn == 2 && hwc -> config > 175 ) ||
407- (cpuhw -> info .csvn >= 3 && cpuhw -> info .csvn <= 5
414+ if ((cpumf_ctr_info .csvn == 1 && hwc -> config > 159 ) ||
415+ (cpumf_ctr_info .csvn == 2 && hwc -> config > 175 ) ||
416+ (cpumf_ctr_info .csvn >= 3 && cpumf_ctr_info .csvn <= 5
408417 && hwc -> config > 255 ) ||
409- (cpuhw -> info .csvn >= 6 && hwc -> config > 287 ))
418+ (cpumf_ctr_info .csvn >= 6 && hwc -> config > 287 ))
410419 err = - EOPNOTSUPP ;
411420 break ;
412421 case CPUMF_CTR_SET_MT_DIAG :
413- if (cpuhw -> info .csvn <= 3 )
422+ if (cpumf_ctr_info .csvn <= 3 )
414423 err = - EOPNOTSUPP ;
415424 /*
416425 * MT-diagnostic counters are read-only. The counter set
@@ -425,35 +434,30 @@ static int validate_ctr_version(const struct hw_perf_event *hwc,
425434 * counter set is enabled and active.
426435 */
427436 mtdiag_ctl = cpumf_ctr_ctl [CPUMF_CTR_SET_MT_DIAG ];
428- if (!((cpuhw -> info .auth_ctl & mtdiag_ctl ) &&
429- (cpuhw -> info .enable_ctl & mtdiag_ctl ) &&
430- (cpuhw -> info .act_ctl & mtdiag_ctl )))
437+ if (!((cpumf_ctr_info .auth_ctl & mtdiag_ctl ) &&
438+ (cpumf_ctr_info .enable_ctl & mtdiag_ctl ) &&
439+ (cpumf_ctr_info .act_ctl & mtdiag_ctl )))
431440 err = - EOPNOTSUPP ;
432441 break ;
433442 case CPUMF_CTR_SET_MAX :
434443 err = - EOPNOTSUPP ;
435444 }
436445
437- put_cpu_var (cpu_cf_events );
438446 return err ;
439447}
440448
441449static int validate_ctr_auth (const struct hw_perf_event * hwc )
442450{
443- struct cpu_cf_events * cpuhw ;
444- int err = 0 ;
445-
446- cpuhw = & get_cpu_var (cpu_cf_events );
451+ int err = - ENOENT ;
447452
448453 /* Check authorization for cpu counter sets.
449454 * If the particular CPU counter set is not authorized,
450455 * return with -ENOENT in order to fall back to other
451456 * PMUs that might suffice the event request.
452457 */
453- if (! (hwc -> config_base & cpuhw -> info .auth_ctl ))
454- err = - ENOENT ;
458+ if ((hwc -> config_base & cpumf_ctr_info .auth_ctl ))
459+ err = 0 ;
455460
456- put_cpu_var (cpu_cf_events );
457461 return err ;
458462}
459463
@@ -509,8 +513,6 @@ static void cpum_cf_setup_cpu(void *flags)
509513
510514 switch ((unsigned long )flags ) {
511515 case PMC_INIT :
512- memset (& cpuhw -> info , 0 , sizeof (cpuhw -> info ));
513- qctri (& cpuhw -> info );
514516 cpuhw -> flags |= PMU_F_RESERVED ;
515517 break ;
516518
@@ -977,7 +979,7 @@ static void cpumf_measurement_alert(struct ext_code ext_code,
977979
978980 /* counter authorization change alert */
979981 if (alert & CPU_MF_INT_CF_CACA )
980- qctri (& cpuhw -> info );
982+ qctri (& cpumf_ctr_info );
981983
982984 /* loss of counter data alert */
983985 if (alert & CPU_MF_INT_CF_LCDA )
@@ -994,9 +996,14 @@ static int __init cpumf_pmu_init(void)
994996{
995997 int rc ;
996998
997- if (!cpum_cf_avail ())
999+ /* Extract counter measurement facility information */
1000+ if (!cpum_cf_avail () || qctri (& cpumf_ctr_info ))
9981001 return - ENODEV ;
9991002
1003+ /* Determine and store counter set sizes for later reference */
1004+ for (rc = CPUMF_CTR_SET_BASIC ; rc < CPUMF_CTR_SET_MAX ; ++ rc )
1005+ cpum_cf_make_setsize (rc );
1006+
10001007 /*
10011008 * Clear bit 15 of cr0 to unauthorize problem-state to
10021009 * extract measurement counters
@@ -1263,21 +1270,19 @@ static int cfset_all_start(struct cfset_request *req)
12631270 */
12641271static size_t cfset_needspace (unsigned int sets )
12651272{
1266- struct cpu_cf_events * cpuhw = get_cpu_ptr (& cpu_cf_events );
12671273 size_t bytes = 0 ;
12681274 int i ;
12691275
12701276 for (i = CPUMF_CTR_SET_BASIC ; i < CPUMF_CTR_SET_MAX ; ++ i ) {
12711277 if (!(sets & cpumf_ctr_ctl [i ]))
12721278 continue ;
1273- bytes += cpum_cf_ctrset_size ( i , & cpuhw -> info ) * sizeof (u64 ) +
1279+ bytes += cpum_cf_read_setsize ( i ) * sizeof (u64 ) +
12741280 sizeof (((struct s390_ctrset_setdata * )0 )-> set ) +
12751281 sizeof (((struct s390_ctrset_setdata * )0 )-> no_cnts );
12761282 }
12771283 bytes = sizeof (((struct s390_ctrset_read * )0 )-> no_cpus ) + nr_cpu_ids *
12781284 (bytes + sizeof (((struct s390_ctrset_cpudata * )0 )-> cpu_nr ) +
12791285 sizeof (((struct s390_ctrset_cpudata * )0 )-> no_sets ));
1280- put_cpu_ptr (& cpu_cf_events );
12811286 return bytes ;
12821287}
12831288
@@ -1351,7 +1356,7 @@ static void cfset_cpu_read(void *parm)
13511356
13521357 if (!(p -> sets & cpumf_ctr_ctl [set ]))
13531358 continue ; /* Counter set not in list */
1354- set_size = cpum_cf_ctrset_size (set , & cpuhw -> info );
1359+ set_size = cpum_cf_read_setsize (set );
13551360 space = sizeof (cpuhw -> data ) - cpuhw -> used ;
13561361 space = cfset_cpuset_read (sp , set , set_size , space );
13571362 if (space ) {
@@ -1562,16 +1567,13 @@ static void cfdiag_read(struct perf_event *event)
15621567
15631568static int get_authctrsets (void )
15641569{
1565- struct cpu_cf_events * cpuhw ;
15661570 unsigned long auth = 0 ;
15671571 enum cpumf_ctr_set i ;
15681572
1569- cpuhw = & get_cpu_var (cpu_cf_events );
15701573 for (i = CPUMF_CTR_SET_BASIC ; i < CPUMF_CTR_SET_MAX ; ++ i ) {
1571- if (cpuhw -> info .auth_ctl & cpumf_ctr_ctl [i ])
1574+ if (cpumf_ctr_info .auth_ctl & cpumf_ctr_ctl [i ])
15721575 auth |= cpumf_ctr_ctl [i ];
15731576 }
1574- put_cpu_var (cpu_cf_events );
15751577 return auth ;
15761578}
15771579
@@ -1709,7 +1711,7 @@ static size_t cfdiag_maxsize(struct cpumf_ctr_info *info)
17091711 enum cpumf_ctr_set i ;
17101712
17111713 for (i = CPUMF_CTR_SET_BASIC ; i < CPUMF_CTR_SET_MAX ; ++ i ) {
1712- size_t size = cpum_cf_ctrset_size ( i , info );
1714+ size_t size = cpum_cf_read_setsize ( i );
17131715
17141716 if (size )
17151717 max_size += size * sizeof (u64 ) +
@@ -1743,16 +1745,12 @@ static void cfdiag_get_cpu_speed(void)
17431745
17441746static int cfset_init (void )
17451747{
1746- struct cpumf_ctr_info info ;
17471748 size_t need ;
17481749 int rc ;
17491750
1750- if (qctri (& info ))
1751- return - ENODEV ;
1752-
17531751 cfdiag_get_cpu_speed ();
17541752 /* Make sure the counter set data fits into predefined buffer. */
1755- need = cfdiag_maxsize (& info );
1753+ need = cfdiag_maxsize (& cpumf_ctr_info );
17561754 if (need > sizeof (((struct cpu_cf_events * )0 )-> start )) {
17571755 pr_err ("Insufficient memory for PMU(cpum_cf_diag) need=%zu\n" ,
17581756 need );
0 commit comments