Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Performance event support for s390x - CPU-measurement Counter Sets
  4 *
  5 *  Copyright IBM Corp. 2019
  6 *  Author(s): Hendrik Brueckner <brueckner@linux.ibm.com>
  7 *	       Thomas Richer <tmricht@linux.ibm.com>
  8 */
  9#define KMSG_COMPONENT	"cpum_cf_diag"
 10#define pr_fmt(fmt)	KMSG_COMPONENT ": " fmt
 11
 12#include <linux/kernel.h>
 13#include <linux/kernel_stat.h>
 14#include <linux/percpu.h>
 15#include <linux/notifier.h>
 16#include <linux/init.h>
 17#include <linux/export.h>
 18#include <linux/slab.h>
 19#include <linux/processor.h>
 20
 21#include <asm/ctl_reg.h>
 22#include <asm/irq.h>
 23#include <asm/cpu_mcf.h>
 24#include <asm/timex.h>
 25#include <asm/debug.h>
 26
 27#define	CF_DIAG_CTRSET_DEF		0xfeef	/* Counter set header mark */
 28
 29static unsigned int cf_diag_cpu_speed;
 30static debug_info_t *cf_diag_dbg;
 31
 32struct cf_diag_csd {		/* Counter set data per CPU */
 33	size_t used;			/* Bytes used in data/start */
 34	unsigned char start[PAGE_SIZE];	/* Counter set at event start */
 35	unsigned char data[PAGE_SIZE];	/* Counter set at event delete */
 36};
 37static DEFINE_PER_CPU(struct cf_diag_csd, cf_diag_csd);
 38
 39/* Counter sets are stored as data stream in a page sized memory buffer and
 40 * exported to user space via raw data attached to the event sample data.
 41 * Each counter set starts with an eight byte header consisting of:
 42 * - a two byte eye catcher (0xfeef)
 43 * - a one byte counter set number
 44 * - a two byte counter set size (indicates the number of counters in this set)
 45 * - a three byte reserved value (must be zero) to make the header the same
 46 *   size as a counter value.
 47 * All counter values are eight byte in size.
 48 *
 49 * All counter sets are followed by a 64 byte trailer.
 50 * The trailer consists of a:
 51 * - flag field indicating valid fields when corresponding bit set
 52 * - the counter facility first and second version number
 53 * - the CPU speed if nonzero
 54 * - the time stamp the counter sets have been collected
 55 * - the time of day (TOD) base value
 56 * - the machine type.
 57 *
 58 * The counter sets are saved when the process is prepared to be executed on a
 59 * CPU and saved again when the process is going to be removed from a CPU.
 60 * The difference of both counter sets are calculated and stored in the event
 61 * sample data area.
 62 */
 63
 64struct cf_ctrset_entry {	/* CPU-M CF counter set entry (8 byte) */
 65	unsigned int def:16;	/* 0-15  Data Entry Format */
 66	unsigned int set:16;	/* 16-31 Counter set identifier */
 67	unsigned int ctr:16;	/* 32-47 Number of stored counters */
 68	unsigned int res1:16;	/* 48-63 Reserved */
 69};
 70
 71struct cf_trailer_entry {	/* CPU-M CF_DIAG trailer (64 byte) */
 72	/* 0 - 7 */
 73	union {
 74		struct {
 75			unsigned int clock_base:1;	/* TOD clock base set */
 76			unsigned int speed:1;		/* CPU speed set */
 77			/* Measurement alerts */
 78			unsigned int mtda:1;	/* Loss of MT ctr. data alert */
 79			unsigned int caca:1;	/* Counter auth. change alert */
 80			unsigned int lcda:1;	/* Loss of counter data alert */
 81		};
 82		unsigned long flags;	/* 0-63    All indicators */
 83	};
 84	/* 8 - 15 */
 85	unsigned int cfvn:16;			/* 64-79   Ctr First Version */
 86	unsigned int csvn:16;			/* 80-95   Ctr Second Version */
 87	unsigned int cpu_speed:32;		/* 96-127  CPU speed */
 88	/* 16 - 23 */
 89	unsigned long timestamp;		/* 128-191 Timestamp (TOD) */
 90	/* 24 - 55 */
 91	union {
 92		struct {
 93			unsigned long progusage1;
 94			unsigned long progusage2;
 95			unsigned long progusage3;
 96			unsigned long tod_base;
 97		};
 98		unsigned long progusage[4];
 99	};
100	/* 56 - 63 */
101	unsigned int mach_type:16;		/* Machine type */
102	unsigned int res1:16;			/* Reserved */
103	unsigned int res2:32;			/* Reserved */
104};
105
106/* Create the trailer data at the end of a page. */
107static void cf_diag_trailer(struct cf_trailer_entry *te)
108{
109	struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
110	struct cpuid cpuid;
111
112	te->cfvn = cpuhw->info.cfvn;		/* Counter version numbers */
113	te->csvn = cpuhw->info.csvn;
114
115	get_cpu_id(&cpuid);			/* Machine type */
116	te->mach_type = cpuid.machine;
117	te->cpu_speed = cf_diag_cpu_speed;
118	if (te->cpu_speed)
119		te->speed = 1;
120	te->clock_base = 1;			/* Save clock base */
121	memcpy(&te->tod_base, &tod_clock_base[1], 8);
122	store_tod_clock((__u64 *)&te->timestamp);
123}
124
125/*
126 * Change the CPUMF state to active.
127 * Enable and activate the CPU-counter sets according
128 * to the per-cpu control state.
129 */
130static void cf_diag_enable(struct pmu *pmu)
131{
132	struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
133	int err;
134
135	debug_sprintf_event(cf_diag_dbg, 5,
136			    "%s pmu %p cpu %d flags %#x state %#llx\n",
137			    __func__, pmu, smp_processor_id(), cpuhw->flags,
138			    cpuhw->state);
139	if (cpuhw->flags & PMU_F_ENABLED)
140		return;
141
142	err = lcctl(cpuhw->state);
143	if (err) {
144		pr_err("Enabling the performance measuring unit "
145		       "failed with rc=%x\n", err);
146		return;
147	}
148	cpuhw->flags |= PMU_F_ENABLED;
149}
150
151/*
152 * Change the CPUMF state to inactive.
153 * Disable and enable (inactive) the CPU-counter sets according
154 * to the per-cpu control state.
155 */
156static void cf_diag_disable(struct pmu *pmu)
157{
158	struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
159	u64 inactive;
160	int err;
161
162	debug_sprintf_event(cf_diag_dbg, 5,
163			    "%s pmu %p cpu %d flags %#x state %#llx\n",
164			    __func__, pmu, smp_processor_id(), cpuhw->flags,
165			    cpuhw->state);
166	if (!(cpuhw->flags & PMU_F_ENABLED))
167		return;
168
169	inactive = cpuhw->state & ~((1 << CPUMF_LCCTL_ENABLE_SHIFT) - 1);
170	err = lcctl(inactive);
171	if (err) {
172		pr_err("Disabling the performance measuring unit "
173		       "failed with rc=%x\n", err);
174		return;
175	}
176	cpuhw->flags &= ~PMU_F_ENABLED;
177}
178
179/* Number of perf events counting hardware events */
180static atomic_t cf_diag_events = ATOMIC_INIT(0);
181
182/* Release the PMU if event is the last perf event */
183static void cf_diag_perf_event_destroy(struct perf_event *event)
184{
185	debug_sprintf_event(cf_diag_dbg, 5,
186			    "%s event %p cpu %d cf_diag_events %d\n",
187			    __func__, event, event->cpu,
188			    atomic_read(&cf_diag_events));
189	if (atomic_dec_return(&cf_diag_events) == 0)
190		__kernel_cpumcf_end();
191}
192
193/* Setup the event. Test for authorized counter sets and only include counter
194 * sets which are authorized at the time of the setup. Including unauthorized
195 * counter sets result in specification exception (and panic).
196 */
197static int __hw_perf_event_init(struct perf_event *event)
198{
199	struct perf_event_attr *attr = &event->attr;
200	struct cpu_cf_events *cpuhw;
201	enum cpumf_ctr_set i;
202	int err = 0;
203
204	debug_sprintf_event(cf_diag_dbg, 5, "%s event %p cpu %d\n", __func__,
205			    event, event->cpu);
206
207	event->hw.config = attr->config;
208	event->hw.config_base = 0;
209
210	/* Add all authorized counter sets to config_base. The
211	 * the hardware init function is either called per-cpu or just once
212	 * for all CPUS (event->cpu == -1).  This depends on the whether
213	 * counting is started for all CPUs or on a per workload base where
214	 * the perf event moves from one CPU to another CPU.
215	 * Checking the authorization on any CPU is fine as the hardware
216	 * applies the same authorization settings to all CPUs.
217	 */
218	cpuhw = &get_cpu_var(cpu_cf_events);
219	for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i)
220		if (cpuhw->info.auth_ctl & cpumf_ctr_ctl[i])
221			event->hw.config_base |= cpumf_ctr_ctl[i];
222	put_cpu_var(cpu_cf_events);
223
224	/* No authorized counter sets, nothing to count/sample */
225	if (!event->hw.config_base) {
226		err = -EINVAL;
227		goto out;
228	}
229
230	/* Set sample_period to indicate sampling */
231	event->hw.sample_period = attr->sample_period;
232	local64_set(&event->hw.period_left, event->hw.sample_period);
233	event->hw.last_period  = event->hw.sample_period;
234out:
235	debug_sprintf_event(cf_diag_dbg, 5, "%s err %d config_base %#lx\n",
236			    __func__, err, event->hw.config_base);
237	return err;
238}
239
240static int cf_diag_event_init(struct perf_event *event)
241{
242	struct perf_event_attr *attr = &event->attr;
243	int err = -ENOENT;
244
245	debug_sprintf_event(cf_diag_dbg, 5,
246			    "%s event %p cpu %d config %#llx "
247			    "sample_type %#llx cf_diag_events %d\n", __func__,
248			    event, event->cpu, attr->config, attr->sample_type,
249			    atomic_read(&cf_diag_events));
250
251	if (event->attr.config != PERF_EVENT_CPUM_CF_DIAG ||
252	    event->attr.type != PERF_TYPE_RAW)
253		goto out;
254
255	/* Raw events are used to access counters directly,
256	 * hence do not permit excludes.
257	 * This event is usesless without PERF_SAMPLE_RAW to return counter set
258	 * values as raw data.
259	 */
260	if (attr->exclude_kernel || attr->exclude_user || attr->exclude_hv ||
261	    !(attr->sample_type & (PERF_SAMPLE_CPU | PERF_SAMPLE_RAW))) {
262		err = -EOPNOTSUPP;
263		goto out;
264	}
265
266	/* Initialize for using the CPU-measurement counter facility */
267	if (atomic_inc_return(&cf_diag_events) == 1) {
268		if (__kernel_cpumcf_begin()) {
269			atomic_dec(&cf_diag_events);
270			err = -EBUSY;
271			goto out;
272		}
273	}
274	event->destroy = cf_diag_perf_event_destroy;
275
276	err = __hw_perf_event_init(event);
277	if (unlikely(err))
278		event->destroy(event);
279out:
280	debug_sprintf_event(cf_diag_dbg, 5, "%s err %d\n", __func__, err);
281	return err;
282}
283
284static void cf_diag_read(struct perf_event *event)
285{
286	debug_sprintf_event(cf_diag_dbg, 5, "%s event %p\n", __func__, event);
287}
288
289/* Return the maximum possible counter set size (in number of 8 byte counters)
290 * depending on type and model number.
291 */
292static size_t cf_diag_ctrset_size(enum cpumf_ctr_set ctrset,
293				 struct cpumf_ctr_info *info)
294{
295	size_t ctrset_size = 0;
296
297	switch (ctrset) {
298	case CPUMF_CTR_SET_BASIC:
299		if (info->cfvn >= 1)
300			ctrset_size = 6;
301		break;
302	case CPUMF_CTR_SET_USER:
303		if (info->cfvn == 1)
304			ctrset_size = 6;
305		else if (info->cfvn >= 3)
306			ctrset_size = 2;
307		break;
308	case CPUMF_CTR_SET_CRYPTO:
309		if (info->csvn >= 1 && info->csvn <= 5)
310			ctrset_size = 16;
311		else if (info->csvn == 6)
312			ctrset_size = 20;
313		break;
314	case CPUMF_CTR_SET_EXT:
315		if (info->csvn == 1)
316			ctrset_size = 32;
317		else if (info->csvn == 2)
318			ctrset_size = 48;
319		else if (info->csvn >= 3 && info->csvn <= 5)
320			ctrset_size = 128;
321		else if (info->csvn == 6)
322			ctrset_size = 160;
323		break;
324	case CPUMF_CTR_SET_MT_DIAG:
325		if (info->csvn > 3)
326			ctrset_size = 48;
327		break;
328	case CPUMF_CTR_SET_MAX:
329		break;
330	}
331
332	return ctrset_size;
333}
334
335/* Calculate memory needed to store all counter sets together with header and
336 * trailer data. This is independend of the counter set authorization which
337 * can vary depending on the configuration.
338 */
339static size_t cf_diag_ctrset_maxsize(struct cpumf_ctr_info *info)
340{
341	size_t max_size = sizeof(struct cf_trailer_entry);
342	enum cpumf_ctr_set i;
343
344	for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
345		size_t size = cf_diag_ctrset_size(i, info);
346
347		if (size)
348			max_size += size * sizeof(u64) +
349				    sizeof(struct cf_ctrset_entry);
350	}
351	debug_sprintf_event(cf_diag_dbg, 5, "%s max_size %zu\n", __func__,
352			    max_size);
353
354	return max_size;
355}
356
357/* Read a counter set. The counter set number determines which counter set and
358 * the CPUM-CF first and second version number determine the number of
359 * available counters in this counter set.
360 * Each counter set starts with header containing the counter set number and
361 * the number of 8 byte counters.
362 *
363 * The functions returns the number of bytes occupied by this counter set
364 * including the header.
365 * If there is no counter in the counter set, this counter set is useless and
366 * zero is returned on this case.
367 */
368static size_t cf_diag_getctrset(struct cf_ctrset_entry *ctrdata, int ctrset,
369				size_t room)
370{
371	struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
372	size_t ctrset_size, need = 0;
373	int rc = 3;				/* Assume write failure */
374
375	ctrdata->def = CF_DIAG_CTRSET_DEF;
376	ctrdata->set = ctrset;
377	ctrdata->res1 = 0;
378	ctrset_size = cf_diag_ctrset_size(ctrset, &cpuhw->info);
379
380	if (ctrset_size) {			/* Save data */
381		need = ctrset_size * sizeof(u64) + sizeof(*ctrdata);
382		if (need <= room)
383			rc = ctr_stcctm(ctrset, ctrset_size,
384					(u64 *)(ctrdata + 1));
385		if (rc != 3)
386			ctrdata->ctr = ctrset_size;
387		else
388			need = 0;
389	}
390
391	debug_sprintf_event(cf_diag_dbg, 6,
392			    "%s ctrset %d ctrset_size %zu cfvn %d csvn %d"
393			    " need %zd rc %d\n",
394			    __func__, ctrset, ctrset_size, cpuhw->info.cfvn,
395			    cpuhw->info.csvn, need, rc);
396	return need;
397}
398
399/* Read out all counter sets and save them in the provided data buffer.
400 * The last 64 byte host an artificial trailer entry.
401 */
402static size_t cf_diag_getctr(void *data, size_t sz, unsigned long auth)
403{
404	struct cf_trailer_entry *trailer;
405	size_t offset = 0, done;
406	int i;
407
408	memset(data, 0, sz);
409	sz -= sizeof(*trailer);			/* Always room for trailer */
410	for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
411		struct cf_ctrset_entry *ctrdata = data + offset;
412
413		if (!(auth & cpumf_ctr_ctl[i]))
414			continue;	/* Counter set not authorized */
415
416		done = cf_diag_getctrset(ctrdata, i, sz - offset);
417		offset += done;
418		debug_sprintf_event(cf_diag_dbg, 6,
419				    "%s ctrset %d offset %zu done %zu\n",
420				     __func__, i, offset, done);
421	}
422	trailer = data + offset;
423	cf_diag_trailer(trailer);
424	return offset + sizeof(*trailer);
425}
426
427/* Calculate the difference for each counter in a counter set. */
428static void cf_diag_diffctrset(u64 *pstart, u64 *pstop, int counters)
429{
430	for (; --counters >= 0; ++pstart, ++pstop)
431		if (*pstop >= *pstart)
432			*pstop -= *pstart;
433		else
434			*pstop = *pstart - *pstop;
435}
436
437/* Scan the counter sets and calculate the difference of each counter
438 * in each set. The result is the increment of each counter during the
439 * period the counter set has been activated.
440 *
441 * Return true on success.
442 */
443static int cf_diag_diffctr(struct cf_diag_csd *csd, unsigned long auth)
444{
445	struct cf_trailer_entry *trailer_start, *trailer_stop;
446	struct cf_ctrset_entry *ctrstart, *ctrstop;
447	size_t offset = 0;
448
449	auth &= (1 << CPUMF_LCCTL_ENABLE_SHIFT) - 1;
450	do {
451		ctrstart = (struct cf_ctrset_entry *)(csd->start + offset);
452		ctrstop = (struct cf_ctrset_entry *)(csd->data + offset);
453
454		if (memcmp(ctrstop, ctrstart, sizeof(*ctrstop))) {
455			pr_err("cpum_cf_diag counter set compare error "
456				"in set %i\n", ctrstart->set);
457			return 0;
458		}
459		auth &= ~cpumf_ctr_ctl[ctrstart->set];
460		if (ctrstart->def == CF_DIAG_CTRSET_DEF) {
461			cf_diag_diffctrset((u64 *)(ctrstart + 1),
462					  (u64 *)(ctrstop + 1), ctrstart->ctr);
463			offset += ctrstart->ctr * sizeof(u64) +
464				  sizeof(*ctrstart);
465		}
466		debug_sprintf_event(cf_diag_dbg, 6,
467				    "%s set %d ctr %d offset %zu auth %lx\n",
468				    __func__, ctrstart->set, ctrstart->ctr,
469				    offset, auth);
470	} while (ctrstart->def && auth);
471
472	/* Save time_stamp from start of event in stop's trailer */
473	trailer_start = (struct cf_trailer_entry *)(csd->start + offset);
474	trailer_stop = (struct cf_trailer_entry *)(csd->data + offset);
475	trailer_stop->progusage[0] = trailer_start->timestamp;
476
477	return 1;
478}
479
480/* Create perf event sample with the counter sets as raw data.	The sample
481 * is then pushed to the event subsystem and the function checks for
482 * possible event overflows. If an event overflow occurs, the PMU is
483 * stopped.
484 *
485 * Return non-zero if an event overflow occurred.
486 */
487static int cf_diag_push_sample(struct perf_event *event,
488			       struct cf_diag_csd *csd)
489{
490	struct perf_sample_data data;
491	struct perf_raw_record raw;
492	struct pt_regs regs;
493	int overflow;
494
495	/* Setup perf sample */
496	perf_sample_data_init(&data, 0, event->hw.last_period);
497	memset(&regs, 0, sizeof(regs));
498	memset(&raw, 0, sizeof(raw));
499
500	if (event->attr.sample_type & PERF_SAMPLE_CPU)
501		data.cpu_entry.cpu = event->cpu;
502	if (event->attr.sample_type & PERF_SAMPLE_RAW) {
503		raw.frag.size = csd->used;
504		raw.frag.data = csd->data;
505		raw.size = csd->used;
506		data.raw = &raw;
507	}
508
509	overflow = perf_event_overflow(event, &data, &regs);
510	debug_sprintf_event(cf_diag_dbg, 6,
511			    "%s event %p cpu %d sample_type %#llx raw %d "
512			    "ov %d\n", __func__, event, event->cpu,
513			    event->attr.sample_type, raw.size, overflow);
514	if (overflow)
515		event->pmu->stop(event, 0);
516
517	perf_event_update_userpage(event);
518	return overflow;
519}
520
521static void cf_diag_start(struct perf_event *event, int flags)
522{
523	struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
524	struct cf_diag_csd *csd = this_cpu_ptr(&cf_diag_csd);
525	struct hw_perf_event *hwc = &event->hw;
526
527	debug_sprintf_event(cf_diag_dbg, 5,
528			    "%s event %p cpu %d flags %#x hwc-state %#x\n",
529			    __func__, event, event->cpu, flags, hwc->state);
530	if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
531		return;
532
533	/* (Re-)enable and activate all counter sets */
534	lcctl(0);		/* Reset counter sets */
535	hwc->state = 0;
536	ctr_set_multiple_enable(&cpuhw->state, hwc->config_base);
537	lcctl(cpuhw->state);	/* Enable counter sets */
538	csd->used = cf_diag_getctr(csd->start, sizeof(csd->start),
539				   event->hw.config_base);
540	ctr_set_multiple_start(&cpuhw->state, hwc->config_base);
541	/* Function cf_diag_enable() starts the counter sets. */
542}
543
544static void cf_diag_stop(struct perf_event *event, int flags)
545{
546	struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
547	struct cf_diag_csd *csd = this_cpu_ptr(&cf_diag_csd);
548	struct hw_perf_event *hwc = &event->hw;
549
550	debug_sprintf_event(cf_diag_dbg, 5,
551			    "%s event %p cpu %d flags %#x hwc-state %#x\n",
552			    __func__, event, event->cpu, flags, hwc->state);
553
554	/* Deactivate all counter sets */
555	ctr_set_multiple_stop(&cpuhw->state, hwc->config_base);
556	local64_inc(&event->count);
557	csd->used = cf_diag_getctr(csd->data, sizeof(csd->data),
558				   event->hw.config_base);
559	if (cf_diag_diffctr(csd, event->hw.config_base))
560		cf_diag_push_sample(event, csd);
561	hwc->state |= PERF_HES_STOPPED;
562}
563
564static int cf_diag_add(struct perf_event *event, int flags)
565{
566	struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
567	int err = 0;
568
569	debug_sprintf_event(cf_diag_dbg, 5,
570			    "%s event %p cpu %d flags %#x cpuhw %p\n",
571			    __func__, event, event->cpu, flags, cpuhw);
572
573	if (cpuhw->flags & PMU_F_IN_USE) {
574		err = -EAGAIN;
575		goto out;
576	}
577
578	event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
579
580	cpuhw->flags |= PMU_F_IN_USE;
581	if (flags & PERF_EF_START)
582		cf_diag_start(event, PERF_EF_RELOAD);
583out:
584	debug_sprintf_event(cf_diag_dbg, 5, "%s err %d\n", __func__, err);
585	return err;
586}
587
588static void cf_diag_del(struct perf_event *event, int flags)
589{
590	struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
591
592	debug_sprintf_event(cf_diag_dbg, 5,
593			    "%s event %p cpu %d flags %#x\n",
594			   __func__, event, event->cpu, flags);
595
596	cf_diag_stop(event, PERF_EF_UPDATE);
597	ctr_set_multiple_stop(&cpuhw->state, event->hw.config_base);
598	ctr_set_multiple_disable(&cpuhw->state, event->hw.config_base);
599	cpuhw->flags &= ~PMU_F_IN_USE;
600}
601
602CPUMF_EVENT_ATTR(CF_DIAG, CF_DIAG, PERF_EVENT_CPUM_CF_DIAG);
603
604static struct attribute *cf_diag_events_attr[] = {
605	CPUMF_EVENT_PTR(CF_DIAG, CF_DIAG),
606	NULL,
607};
608
609PMU_FORMAT_ATTR(event, "config:0-63");
610
611static struct attribute *cf_diag_format_attr[] = {
612	&format_attr_event.attr,
613	NULL,
614};
615
616static struct attribute_group cf_diag_events_group = {
617	.name = "events",
618	.attrs = cf_diag_events_attr,
619};
620static struct attribute_group cf_diag_format_group = {
621	.name = "format",
622	.attrs = cf_diag_format_attr,
623};
624static const struct attribute_group *cf_diag_attr_groups[] = {
625	&cf_diag_events_group,
626	&cf_diag_format_group,
627	NULL,
628};
629
630/* Performance monitoring unit for s390x */
631static struct pmu cf_diag = {
632	.task_ctx_nr  = perf_sw_context,
633	.pmu_enable   = cf_diag_enable,
634	.pmu_disable  = cf_diag_disable,
635	.event_init   = cf_diag_event_init,
636	.add	      = cf_diag_add,
637	.del	      = cf_diag_del,
638	.start	      = cf_diag_start,
639	.stop	      = cf_diag_stop,
640	.read	      = cf_diag_read,
641
642	.attr_groups  = cf_diag_attr_groups
643};
644
645/* Get the CPU speed, try sampling facility first and CPU attributes second. */
646static void cf_diag_get_cpu_speed(void)
647{
648	if (cpum_sf_avail()) {			/* Sampling facility first */
649		struct hws_qsi_info_block si;
650
651		memset(&si, 0, sizeof(si));
652		if (!qsi(&si)) {
653			cf_diag_cpu_speed = si.cpu_speed;
654			return;
655		}
656	}
657
658	if (test_facility(34)) {		/* CPU speed extract static part */
659		unsigned long mhz = __ecag(ECAG_CPU_ATTRIBUTE, 0);
660
661		if (mhz != -1UL)
662			cf_diag_cpu_speed = mhz & 0xffffffff;
663	}
664}
665
666/* Initialize the counter set PMU to generate complete counter set data as
667 * event raw data. This relies on the CPU Measurement Counter Facility device
668 * already being loaded and initialized.
669 */
670static int __init cf_diag_init(void)
671{
672	struct cpumf_ctr_info info;
673	size_t need;
674	int rc;
675
676	if (!kernel_cpumcf_avail() || !stccm_avail() || qctri(&info))
677		return -ENODEV;
678	cf_diag_get_cpu_speed();
679
680	/* Make sure the counter set data fits into predefined buffer. */
681	need = cf_diag_ctrset_maxsize(&info);
682	if (need > sizeof(((struct cf_diag_csd *)0)->start)) {
683		pr_err("Insufficient memory for PMU(cpum_cf_diag) need=%zu\n",
684		       need);
685		return -ENOMEM;
686	}
687
688	/* Setup s390dbf facility */
689	cf_diag_dbg = debug_register(KMSG_COMPONENT, 2, 1, 128);
690	if (!cf_diag_dbg) {
691		pr_err("Registration of s390dbf(cpum_cf_diag) failed\n");
692		return -ENOMEM;
693	}
694	debug_register_view(cf_diag_dbg, &debug_sprintf_view);
695
696	rc = perf_pmu_register(&cf_diag, "cpum_cf_diag", PERF_TYPE_RAW);
697	if (rc) {
698		debug_unregister_view(cf_diag_dbg, &debug_sprintf_view);
699		debug_unregister(cf_diag_dbg);
700		pr_err("Registration of PMU(cpum_cf_diag) failed with rc=%i\n",
701		       rc);
702	}
703	return rc;
704}
705arch_initcall(cf_diag_init);