1
2
3
4
5
6
7
8
9#define KMSG_COMPONENT "cpum_cf"
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/miscdevice.h>
19
20#include <asm/cpu_mcf.h>
21#include <asm/hwctrset.h>
22#include <asm/debug.h>
23
24static unsigned int cfdiag_cpu_speed;
25static debug_info_t *cf_dbg;
26
27#define CF_DIAG_CTRSET_DEF 0xfeef
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54struct cf_ctrset_entry {
55 unsigned int def:16;
56 unsigned int set:16;
57 unsigned int ctr:16;
58 unsigned int res1:16;
59};
60
61struct cf_trailer_entry {
62
63 union {
64 struct {
65 unsigned int clock_base:1;
66 unsigned int speed:1;
67
68 unsigned int mtda:1;
69 unsigned int caca:1;
70 unsigned int lcda:1;
71 };
72 unsigned long flags;
73 };
74
75 unsigned int cfvn:16;
76 unsigned int csvn:16;
77 unsigned int cpu_speed:32;
78
79 unsigned long timestamp;
80
81 union {
82 struct {
83 unsigned long progusage1;
84 unsigned long progusage2;
85 unsigned long progusage3;
86 unsigned long tod_base;
87 };
88 unsigned long progusage[4];
89 };
90
91 unsigned int mach_type:16;
92 unsigned int res1:16;
93 unsigned int res2:32;
94};
95
96
97static void cfdiag_trailer(struct cf_trailer_entry *te)
98{
99 struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
100 struct cpuid cpuid;
101
102 te->cfvn = cpuhw->info.cfvn;
103 te->csvn = cpuhw->info.csvn;
104
105 get_cpu_id(&cpuid);
106 te->mach_type = cpuid.machine;
107 te->cpu_speed = cfdiag_cpu_speed;
108 if (te->cpu_speed)
109 te->speed = 1;
110 te->clock_base = 1;
111 te->tod_base = tod_clock_base.tod;
112 te->timestamp = get_tod_clock_fast();
113}
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130static size_t cfdiag_getctrset(struct cf_ctrset_entry *ctrdata, int ctrset,
131 size_t room, bool error_ok)
132{
133 struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
134 size_t ctrset_size, need = 0;
135 int rc = 3;
136
137 ctrdata->def = CF_DIAG_CTRSET_DEF;
138 ctrdata->set = ctrset;
139 ctrdata->res1 = 0;
140 ctrset_size = cpum_cf_ctrset_size(ctrset, &cpuhw->info);
141
142 if (ctrset_size) {
143 need = ctrset_size * sizeof(u64) + sizeof(*ctrdata);
144 if (need <= room) {
145 rc = ctr_stcctm(ctrset, ctrset_size,
146 (u64 *)(ctrdata + 1));
147 }
148 if (rc != 3 || error_ok)
149 ctrdata->ctr = ctrset_size;
150 else
151 need = 0;
152 }
153
154 debug_sprintf_event(cf_dbg, 3,
155 "%s ctrset %d ctrset_size %zu cfvn %d csvn %d"
156 " need %zd rc %d\n", __func__, ctrset, ctrset_size,
157 cpuhw->info.cfvn, cpuhw->info.csvn, need, rc);
158 return need;
159}
160
161
162
163
164static size_t cfdiag_getctr(void *data, size_t sz, unsigned long auth,
165 bool error_ok)
166{
167 struct cf_trailer_entry *trailer;
168 size_t offset = 0, done;
169 int i;
170
171 memset(data, 0, sz);
172 sz -= sizeof(*trailer);
173 for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
174 struct cf_ctrset_entry *ctrdata = data + offset;
175
176 if (!(auth & cpumf_ctr_ctl[i]))
177 continue;
178
179 done = cfdiag_getctrset(ctrdata, i, sz - offset, error_ok);
180 offset += done;
181 }
182 trailer = data + offset;
183 cfdiag_trailer(trailer);
184 return offset + sizeof(*trailer);
185}
186
187
188static void cfdiag_diffctrset(u64 *pstart, u64 *pstop, int counters)
189{
190 for (; --counters >= 0; ++pstart, ++pstop)
191 if (*pstop >= *pstart)
192 *pstop -= *pstart;
193 else
194 *pstop = *pstart - *pstop + 1;
195}
196
197
198
199
200
201
202
203static int cfdiag_diffctr(struct cpu_cf_events *cpuhw, unsigned long auth)
204{
205 struct cf_trailer_entry *trailer_start, *trailer_stop;
206 struct cf_ctrset_entry *ctrstart, *ctrstop;
207 size_t offset = 0;
208
209 auth &= (1 << CPUMF_LCCTL_ENABLE_SHIFT) - 1;
210 do {
211 ctrstart = (struct cf_ctrset_entry *)(cpuhw->start + offset);
212 ctrstop = (struct cf_ctrset_entry *)(cpuhw->stop + offset);
213
214 if (memcmp(ctrstop, ctrstart, sizeof(*ctrstop))) {
215 pr_err_once("cpum_cf_diag counter set compare error "
216 "in set %i\n", ctrstart->set);
217 return 0;
218 }
219 auth &= ~cpumf_ctr_ctl[ctrstart->set];
220 if (ctrstart->def == CF_DIAG_CTRSET_DEF) {
221 cfdiag_diffctrset((u64 *)(ctrstart + 1),
222 (u64 *)(ctrstop + 1), ctrstart->ctr);
223 offset += ctrstart->ctr * sizeof(u64) +
224 sizeof(*ctrstart);
225 }
226 } while (ctrstart->def && auth);
227
228
229 trailer_start = (struct cf_trailer_entry *)(cpuhw->start + offset);
230 trailer_stop = (struct cf_trailer_entry *)(cpuhw->stop + offset);
231 trailer_stop->progusage[0] = trailer_start->timestamp;
232
233 return 1;
234}
235
236static enum cpumf_ctr_set get_counter_set(u64 event)
237{
238 int set = CPUMF_CTR_SET_MAX;
239
240 if (event < 32)
241 set = CPUMF_CTR_SET_BASIC;
242 else if (event < 64)
243 set = CPUMF_CTR_SET_USER;
244 else if (event < 128)
245 set = CPUMF_CTR_SET_CRYPTO;
246 else if (event < 288)
247 set = CPUMF_CTR_SET_EXT;
248 else if (event >= 448 && event < 496)
249 set = CPUMF_CTR_SET_MT_DIAG;
250
251 return set;
252}
253
254static int validate_ctr_version(const struct hw_perf_event *hwc,
255 enum cpumf_ctr_set set)
256{
257 struct cpu_cf_events *cpuhw;
258 int err = 0;
259 u16 mtdiag_ctl;
260
261 cpuhw = &get_cpu_var(cpu_cf_events);
262
263
264 switch (set) {
265 case CPUMF_CTR_SET_BASIC:
266 case CPUMF_CTR_SET_USER:
267 if (cpuhw->info.cfvn < 1)
268 err = -EOPNOTSUPP;
269 break;
270 case CPUMF_CTR_SET_CRYPTO:
271 if ((cpuhw->info.csvn >= 1 && cpuhw->info.csvn <= 5 &&
272 hwc->config > 79) ||
273 (cpuhw->info.csvn >= 6 && hwc->config > 83))
274 err = -EOPNOTSUPP;
275 break;
276 case CPUMF_CTR_SET_EXT:
277 if (cpuhw->info.csvn < 1)
278 err = -EOPNOTSUPP;
279 if ((cpuhw->info.csvn == 1 && hwc->config > 159) ||
280 (cpuhw->info.csvn == 2 && hwc->config > 175) ||
281 (cpuhw->info.csvn >= 3 && cpuhw->info.csvn <= 5
282 && hwc->config > 255) ||
283 (cpuhw->info.csvn >= 6 && hwc->config > 287))
284 err = -EOPNOTSUPP;
285 break;
286 case CPUMF_CTR_SET_MT_DIAG:
287 if (cpuhw->info.csvn <= 3)
288 err = -EOPNOTSUPP;
289
290
291
292
293
294
295
296
297
298
299
300
301 mtdiag_ctl = cpumf_ctr_ctl[CPUMF_CTR_SET_MT_DIAG];
302 if (!((cpuhw->info.auth_ctl & mtdiag_ctl) &&
303 (cpuhw->info.enable_ctl & mtdiag_ctl) &&
304 (cpuhw->info.act_ctl & mtdiag_ctl)))
305 err = -EOPNOTSUPP;
306 break;
307 case CPUMF_CTR_SET_MAX:
308 err = -EOPNOTSUPP;
309 }
310
311 put_cpu_var(cpu_cf_events);
312 return err;
313}
314
315static int validate_ctr_auth(const struct hw_perf_event *hwc)
316{
317 struct cpu_cf_events *cpuhw;
318 int err = 0;
319
320 cpuhw = &get_cpu_var(cpu_cf_events);
321
322
323
324
325
326
327 if (!(hwc->config_base & cpuhw->info.auth_ctl))
328 err = -ENOENT;
329
330 put_cpu_var(cpu_cf_events);
331 return err;
332}
333
334
335
336
337
338
339static void cpumf_pmu_enable(struct pmu *pmu)
340{
341 struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
342 int err;
343
344 if (cpuhw->flags & PMU_F_ENABLED)
345 return;
346
347 err = lcctl(cpuhw->state | cpuhw->dev_state);
348 if (err) {
349 pr_err("Enabling the performance measuring unit "
350 "failed with rc=%x\n", err);
351 return;
352 }
353
354 cpuhw->flags |= PMU_F_ENABLED;
355}
356
357
358
359
360
361
362static void cpumf_pmu_disable(struct pmu *pmu)
363{
364 struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
365 int err;
366 u64 inactive;
367
368 if (!(cpuhw->flags & PMU_F_ENABLED))
369 return;
370
371 inactive = cpuhw->state & ~((1 << CPUMF_LCCTL_ENABLE_SHIFT) - 1);
372 inactive |= cpuhw->dev_state;
373 err = lcctl(inactive);
374 if (err) {
375 pr_err("Disabling the performance measuring unit "
376 "failed with rc=%x\n", err);
377 return;
378 }
379
380 cpuhw->flags &= ~PMU_F_ENABLED;
381}
382
383
384
385static atomic_t num_events = ATOMIC_INIT(0);
386
387static DEFINE_MUTEX(pmc_reserve_mutex);
388
389
390static void hw_perf_event_destroy(struct perf_event *event)
391{
392 if (!atomic_add_unless(&num_events, -1, 1)) {
393 mutex_lock(&pmc_reserve_mutex);
394 if (atomic_dec_return(&num_events) == 0)
395 __kernel_cpumcf_end();
396 mutex_unlock(&pmc_reserve_mutex);
397 }
398}
399
400
401static const int cpumf_generic_events_basic[] = {
402 [PERF_COUNT_HW_CPU_CYCLES] = 0,
403 [PERF_COUNT_HW_INSTRUCTIONS] = 1,
404 [PERF_COUNT_HW_CACHE_REFERENCES] = -1,
405 [PERF_COUNT_HW_CACHE_MISSES] = -1,
406 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = -1,
407 [PERF_COUNT_HW_BRANCH_MISSES] = -1,
408 [PERF_COUNT_HW_BUS_CYCLES] = -1,
409};
410
411static const int cpumf_generic_events_user[] = {
412 [PERF_COUNT_HW_CPU_CYCLES] = 32,
413 [PERF_COUNT_HW_INSTRUCTIONS] = 33,
414 [PERF_COUNT_HW_CACHE_REFERENCES] = -1,
415 [PERF_COUNT_HW_CACHE_MISSES] = -1,
416 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = -1,
417 [PERF_COUNT_HW_BRANCH_MISSES] = -1,
418 [PERF_COUNT_HW_BUS_CYCLES] = -1,
419};
420
421static void cpumf_hw_inuse(void)
422{
423 mutex_lock(&pmc_reserve_mutex);
424 if (atomic_inc_return(&num_events) == 1)
425 __kernel_cpumcf_begin();
426 mutex_unlock(&pmc_reserve_mutex);
427}
428
429static int __hw_perf_event_init(struct perf_event *event, unsigned int type)
430{
431 struct perf_event_attr *attr = &event->attr;
432 struct hw_perf_event *hwc = &event->hw;
433 enum cpumf_ctr_set set;
434 int err = 0;
435 u64 ev;
436
437 switch (type) {
438 case PERF_TYPE_RAW:
439
440
441 if (attr->exclude_kernel || attr->exclude_user ||
442 attr->exclude_hv)
443 return -EOPNOTSUPP;
444 ev = attr->config;
445 break;
446
447 case PERF_TYPE_HARDWARE:
448 if (is_sampling_event(event))
449 return -ENOENT;
450 ev = attr->config;
451
452 if (!attr->exclude_user && attr->exclude_kernel) {
453 if (ev >= ARRAY_SIZE(cpumf_generic_events_user))
454 return -EOPNOTSUPP;
455 ev = cpumf_generic_events_user[ev];
456
457
458 } else if (!attr->exclude_kernel && attr->exclude_user) {
459 return -EOPNOTSUPP;
460 } else {
461 if (ev >= ARRAY_SIZE(cpumf_generic_events_basic))
462 return -EOPNOTSUPP;
463 ev = cpumf_generic_events_basic[ev];
464 }
465 break;
466
467 default:
468 return -ENOENT;
469 }
470
471 if (ev == -1)
472 return -ENOENT;
473
474 if (ev > PERF_CPUM_CF_MAX_CTR)
475 return -ENOENT;
476
477
478 set = get_counter_set(ev);
479 switch (set) {
480 case CPUMF_CTR_SET_BASIC:
481 case CPUMF_CTR_SET_USER:
482 case CPUMF_CTR_SET_CRYPTO:
483 case CPUMF_CTR_SET_EXT:
484 case CPUMF_CTR_SET_MT_DIAG:
485
486
487
488
489
490
491 hwc->config = ev;
492 hwc->config_base = cpumf_ctr_ctl[set];
493 break;
494 case CPUMF_CTR_SET_MAX:
495
496 return -EINVAL;
497 }
498
499
500 cpumf_hw_inuse();
501 event->destroy = hw_perf_event_destroy;
502
503
504 err = validate_ctr_auth(hwc);
505 if (!err)
506 err = validate_ctr_version(hwc, set);
507
508 return err;
509}
510
511static int cpumf_pmu_event_init(struct perf_event *event)
512{
513 unsigned int type = event->attr.type;
514 int err;
515
516 if (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_RAW)
517 err = __hw_perf_event_init(event, type);
518 else if (event->pmu->type == type)
519
520 err = __hw_perf_event_init(event, PERF_TYPE_RAW);
521 else
522 return -ENOENT;
523
524 if (unlikely(err) && event->destroy)
525 event->destroy(event);
526
527 return err;
528}
529
530static int hw_perf_event_reset(struct perf_event *event)
531{
532 u64 prev, new;
533 int err;
534
535 do {
536 prev = local64_read(&event->hw.prev_count);
537 err = ecctr(event->hw.config, &new);
538 if (err) {
539 if (err != 3)
540 break;
541
542
543
544
545
546 new = 0;
547 }
548 } while (local64_cmpxchg(&event->hw.prev_count, prev, new) != prev);
549
550 return err;
551}
552
553static void hw_perf_event_update(struct perf_event *event)
554{
555 u64 prev, new, delta;
556 int err;
557
558 do {
559 prev = local64_read(&event->hw.prev_count);
560 err = ecctr(event->hw.config, &new);
561 if (err)
562 return;
563 } while (local64_cmpxchg(&event->hw.prev_count, prev, new) != prev);
564
565 delta = (prev <= new) ? new - prev
566 : (-1ULL - prev) + new + 1;
567 local64_add(delta, &event->count);
568}
569
570static void cpumf_pmu_read(struct perf_event *event)
571{
572 if (event->hw.state & PERF_HES_STOPPED)
573 return;
574
575 hw_perf_event_update(event);
576}
577
578static void cpumf_pmu_start(struct perf_event *event, int flags)
579{
580 struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
581 struct hw_perf_event *hwc = &event->hw;
582 int i;
583
584 if (!(hwc->state & PERF_HES_STOPPED))
585 return;
586
587 hwc->state = 0;
588
589
590 ctr_set_enable(&cpuhw->state, hwc->config_base);
591 ctr_set_start(&cpuhw->state, hwc->config_base);
592
593
594
595
596
597
598 if (hwc->config == PERF_EVENT_CPUM_CF_DIAG) {
599 cpuhw->usedss = cfdiag_getctr(cpuhw->start,
600 sizeof(cpuhw->start),
601 hwc->config_base, true);
602 } else {
603 hw_perf_event_reset(event);
604 }
605
606
607 for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i)
608 if ((hwc->config_base & cpumf_ctr_ctl[i]))
609 atomic_inc(&cpuhw->ctr_set[i]);
610}
611
612
613
614
615
616
617
618
619static int cfdiag_push_sample(struct perf_event *event,
620 struct cpu_cf_events *cpuhw)
621{
622 struct perf_sample_data data;
623 struct perf_raw_record raw;
624 struct pt_regs regs;
625 int overflow;
626
627
628 perf_sample_data_init(&data, 0, event->hw.last_period);
629 memset(®s, 0, sizeof(regs));
630 memset(&raw, 0, sizeof(raw));
631
632 if (event->attr.sample_type & PERF_SAMPLE_CPU)
633 data.cpu_entry.cpu = event->cpu;
634 if (event->attr.sample_type & PERF_SAMPLE_RAW) {
635 raw.frag.size = cpuhw->usedss;
636 raw.frag.data = cpuhw->stop;
637 raw.size = raw.frag.size;
638 data.raw = &raw;
639 }
640
641 overflow = perf_event_overflow(event, &data, ®s);
642 debug_sprintf_event(cf_dbg, 3,
643 "%s event %#llx sample_type %#llx raw %d ov %d\n",
644 __func__, event->hw.config,
645 event->attr.sample_type, raw.size, overflow);
646 if (overflow)
647 event->pmu->stop(event, 0);
648
649 perf_event_update_userpage(event);
650 return overflow;
651}
652
653static void cpumf_pmu_stop(struct perf_event *event, int flags)
654{
655 struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
656 struct hw_perf_event *hwc = &event->hw;
657 int i;
658
659 if (!(hwc->state & PERF_HES_STOPPED)) {
660
661
662
663
664 for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
665 if (!(hwc->config_base & cpumf_ctr_ctl[i]))
666 continue;
667 if (!atomic_dec_return(&cpuhw->ctr_set[i]))
668 ctr_set_stop(&cpuhw->state, cpumf_ctr_ctl[i]);
669 }
670 hwc->state |= PERF_HES_STOPPED;
671 }
672
673 if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
674 if (hwc->config == PERF_EVENT_CPUM_CF_DIAG) {
675 local64_inc(&event->count);
676 cpuhw->usedss = cfdiag_getctr(cpuhw->stop,
677 sizeof(cpuhw->stop),
678 event->hw.config_base,
679 false);
680 if (cfdiag_diffctr(cpuhw, event->hw.config_base))
681 cfdiag_push_sample(event, cpuhw);
682 } else
683 hw_perf_event_update(event);
684 hwc->state |= PERF_HES_UPTODATE;
685 }
686}
687
688static int cpumf_pmu_add(struct perf_event *event, int flags)
689{
690 struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
691
692 ctr_set_enable(&cpuhw->state, event->hw.config_base);
693 event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
694
695 if (flags & PERF_EF_START)
696 cpumf_pmu_start(event, PERF_EF_RELOAD);
697
698 return 0;
699}
700
701static void cpumf_pmu_del(struct perf_event *event, int flags)
702{
703 struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
704 int i;
705
706 cpumf_pmu_stop(event, PERF_EF_UPDATE);
707
708
709
710
711
712
713
714
715
716 for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i)
717 if (!atomic_read(&cpuhw->ctr_set[i]))
718 ctr_set_disable(&cpuhw->state, cpumf_ctr_ctl[i]);
719}
720
721
722static struct pmu cpumf_pmu = {
723 .task_ctx_nr = perf_sw_context,
724 .capabilities = PERF_PMU_CAP_NO_INTERRUPT,
725 .pmu_enable = cpumf_pmu_enable,
726 .pmu_disable = cpumf_pmu_disable,
727 .event_init = cpumf_pmu_event_init,
728 .add = cpumf_pmu_add,
729 .del = cpumf_pmu_del,
730 .start = cpumf_pmu_start,
731 .stop = cpumf_pmu_stop,
732 .read = cpumf_pmu_read,
733};
734
735static int cfset_init(void);
736static int __init cpumf_pmu_init(void)
737{
738 int rc;
739
740 if (!kernel_cpumcf_avail())
741 return -ENODEV;
742
743
744 cf_dbg = debug_register(KMSG_COMPONENT, 2, 1, 128);
745 if (!cf_dbg) {
746 pr_err("Registration of s390dbf(cpum_cf) failed\n");
747 return -ENOMEM;
748 }
749 debug_register_view(cf_dbg, &debug_sprintf_view);
750
751 cpumf_pmu.attr_groups = cpumf_cf_event_group();
752 rc = perf_pmu_register(&cpumf_pmu, "cpum_cf", -1);
753 if (rc) {
754 debug_unregister_view(cf_dbg, &debug_sprintf_view);
755 debug_unregister(cf_dbg);
756 pr_err("Registering the cpum_cf PMU failed with rc=%i\n", rc);
757 } else if (stccm_avail()) {
758 cfset_init();
759 }
760 return rc;
761}
762
763
764
765
766
767
768static atomic_t cfset_opencnt = ATOMIC_INIT(0);
769static DEFINE_MUTEX(cfset_ctrset_mutex);
770struct cfset_call_on_cpu_parm {
771 unsigned int sets;
772 atomic_t cpus_ack;
773};
774
775static struct cfset_request {
776 unsigned long ctrset;
777 cpumask_t mask;
778} cfset_request;
779
780static void cfset_ctrset_clear(void)
781{
782 cpumask_clear(&cfset_request.mask);
783 cfset_request.ctrset = 0;
784}
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816static void cfset_ioctl_off(void *parm)
817{
818 struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
819 struct cfset_call_on_cpu_parm *p = parm;
820 int rc;
821
822 cpuhw->dev_state = 0;
823 for (rc = CPUMF_CTR_SET_BASIC; rc < CPUMF_CTR_SET_MAX; ++rc)
824 if ((p->sets & cpumf_ctr_ctl[rc]))
825 atomic_dec(&cpuhw->ctr_set[rc]);
826 rc = lcctl(cpuhw->state);
827 if (rc)
828 pr_err("Counter set stop %#llx of /dev/%s failed rc=%i\n",
829 cpuhw->state, S390_HWCTR_DEVICE, rc);
830 cpuhw->flags &= ~PMU_F_IN_USE;
831 debug_sprintf_event(cf_dbg, 4, "%s rc %d state %#llx dev_state %#llx\n",
832 __func__, rc, cpuhw->state, cpuhw->dev_state);
833}
834
835
836static void cfset_ioctl_on(void *parm)
837{
838 struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
839 struct cfset_call_on_cpu_parm *p = parm;
840 int rc;
841
842 cpuhw->flags |= PMU_F_IN_USE;
843 ctr_set_enable(&cpuhw->dev_state, p->sets);
844 ctr_set_start(&cpuhw->dev_state, p->sets);
845 for (rc = CPUMF_CTR_SET_BASIC; rc < CPUMF_CTR_SET_MAX; ++rc)
846 if ((p->sets & cpumf_ctr_ctl[rc]))
847 atomic_inc(&cpuhw->ctr_set[rc]);
848 rc = lcctl(cpuhw->dev_state | cpuhw->state);
849 if (!rc)
850 atomic_inc(&p->cpus_ack);
851 else
852 pr_err("Counter set start %#llx of /dev/%s failed rc=%i\n",
853 cpuhw->dev_state | cpuhw->state, S390_HWCTR_DEVICE, rc);
854 debug_sprintf_event(cf_dbg, 4, "%s rc %d state %#llx dev_state %#llx\n",
855 __func__, rc, cpuhw->state, cpuhw->dev_state);
856}
857
858static void cfset_release_cpu(void *p)
859{
860 struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
861 int rc;
862
863 debug_sprintf_event(cf_dbg, 4, "%s state %#llx dev_state %#llx\n",
864 __func__, cpuhw->state, cpuhw->dev_state);
865 rc = lcctl(cpuhw->state);
866 if (rc)
867 pr_err("Counter set release %#llx of /dev/%s failed rc=%i\n",
868 cpuhw->state, S390_HWCTR_DEVICE, rc);
869 cpuhw->dev_state = 0;
870}
871
872
873
874
875static int cfset_release(struct inode *inode, struct file *file)
876{
877 on_each_cpu(cfset_release_cpu, NULL, 1);
878 hw_perf_event_destroy(NULL);
879 cfset_ctrset_clear();
880 atomic_set(&cfset_opencnt, 0);
881 return 0;
882}
883
884static int cfset_open(struct inode *inode, struct file *file)
885{
886 if (!capable(CAP_SYS_ADMIN))
887 return -EPERM;
888
889 if (atomic_xchg(&cfset_opencnt, 1))
890 return -EBUSY;
891
892 cpumf_hw_inuse();
893 file->private_data = NULL;
894
895 return nonseekable_open(inode, file);
896}
897
898static int cfset_all_stop(void)
899{
900 struct cfset_call_on_cpu_parm p = {
901 .sets = cfset_request.ctrset,
902 };
903 cpumask_var_t mask;
904
905 if (!alloc_cpumask_var(&mask, GFP_KERNEL))
906 return -ENOMEM;
907 cpumask_and(mask, &cfset_request.mask, cpu_online_mask);
908 on_each_cpu_mask(mask, cfset_ioctl_off, &p, 1);
909 free_cpumask_var(mask);
910 return 0;
911}
912
913static int cfset_all_start(void)
914{
915 struct cfset_call_on_cpu_parm p = {
916 .sets = cfset_request.ctrset,
917 .cpus_ack = ATOMIC_INIT(0),
918 };
919 cpumask_var_t mask;
920 int rc = 0;
921
922 if (!alloc_cpumask_var(&mask, GFP_KERNEL))
923 return -ENOMEM;
924 cpumask_and(mask, &cfset_request.mask, cpu_online_mask);
925 on_each_cpu_mask(mask, cfset_ioctl_on, &p, 1);
926 if (atomic_read(&p.cpus_ack) != cpumask_weight(mask)) {
927 on_each_cpu_mask(mask, cfset_ioctl_off, &p, 1);
928 rc = -EIO;
929 debug_sprintf_event(cf_dbg, 4, "%s CPUs missing", __func__);
930 }
931 free_cpumask_var(mask);
932 return rc;
933}
934
935
936
937
938
939
940
941static size_t cfset_needspace(unsigned int sets)
942{
943 struct cpu_cf_events *cpuhw = get_cpu_ptr(&cpu_cf_events);
944 size_t bytes = 0;
945 int i;
946
947 for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
948 if (!(sets & cpumf_ctr_ctl[i]))
949 continue;
950 bytes += cpum_cf_ctrset_size(i, &cpuhw->info) * sizeof(u64) +
951 sizeof(((struct s390_ctrset_setdata *)0)->set) +
952 sizeof(((struct s390_ctrset_setdata *)0)->no_cnts);
953 }
954 bytes = sizeof(((struct s390_ctrset_read *)0)->no_cpus) + nr_cpu_ids *
955 (bytes + sizeof(((struct s390_ctrset_cpudata *)0)->cpu_nr) +
956 sizeof(((struct s390_ctrset_cpudata *)0)->no_sets));
957 put_cpu_ptr(&cpu_cf_events);
958 return bytes;
959}
960
961static int cfset_all_copy(unsigned long arg, cpumask_t *mask)
962{
963 struct s390_ctrset_read __user *ctrset_read;
964 unsigned int cpu, cpus, rc;
965 void __user *uptr;
966
967 ctrset_read = (struct s390_ctrset_read __user *)arg;
968 uptr = ctrset_read->data;
969 for_each_cpu(cpu, mask) {
970 struct cpu_cf_events *cpuhw = per_cpu_ptr(&cpu_cf_events, cpu);
971 struct s390_ctrset_cpudata __user *ctrset_cpudata;
972
973 ctrset_cpudata = uptr;
974 rc = put_user(cpu, &ctrset_cpudata->cpu_nr);
975 rc |= put_user(cpuhw->sets, &ctrset_cpudata->no_sets);
976 rc |= copy_to_user(ctrset_cpudata->data, cpuhw->data,
977 cpuhw->used);
978 if (rc)
979 return -EFAULT;
980 uptr += sizeof(struct s390_ctrset_cpudata) + cpuhw->used;
981 cond_resched();
982 }
983 cpus = cpumask_weight(mask);
984 if (put_user(cpus, &ctrset_read->no_cpus))
985 return -EFAULT;
986 debug_sprintf_event(cf_dbg, 4, "%s copied %ld\n", __func__,
987 uptr - (void __user *)ctrset_read->data);
988 return 0;
989}
990
991static size_t cfset_cpuset_read(struct s390_ctrset_setdata *p, int ctrset,
992 int ctrset_size, size_t room)
993{
994 size_t need = 0;
995 int rc = -1;
996
997 need = sizeof(*p) + sizeof(u64) * ctrset_size;
998 if (need <= room) {
999 p->set = cpumf_ctr_ctl[ctrset];
1000 p->no_cnts = ctrset_size;
1001 rc = ctr_stcctm(ctrset, ctrset_size, (u64 *)p->cv);
1002 if (rc == 3)
1003 need = 0;
1004 }
1005 return need;
1006}
1007
1008
1009static void cfset_cpu_read(void *parm)
1010{
1011 struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
1012 struct cfset_call_on_cpu_parm *p = parm;
1013 int set, set_size;
1014 size_t space;
1015
1016
1017 cpuhw->used = 0;
1018 cpuhw->sets = 0;
1019 memset(cpuhw->data, 0, sizeof(cpuhw->data));
1020
1021
1022 for (set = CPUMF_CTR_SET_BASIC; set < CPUMF_CTR_SET_MAX; ++set) {
1023 struct s390_ctrset_setdata *sp = (void *)cpuhw->data +
1024 cpuhw->used;
1025
1026 if (!(p->sets & cpumf_ctr_ctl[set]))
1027 continue;
1028 set_size = cpum_cf_ctrset_size(set, &cpuhw->info);
1029 space = sizeof(cpuhw->data) - cpuhw->used;
1030 space = cfset_cpuset_read(sp, set, set_size, space);
1031 if (space) {
1032 cpuhw->used += space;
1033 cpuhw->sets += 1;
1034 }
1035 }
1036 debug_sprintf_event(cf_dbg, 4, "%s sets %d used %zd\n", __func__,
1037 cpuhw->sets, cpuhw->used);
1038}
1039
1040static int cfset_all_read(unsigned long arg)
1041{
1042 struct cfset_call_on_cpu_parm p;
1043 cpumask_var_t mask;
1044 int rc;
1045
1046 if (!alloc_cpumask_var(&mask, GFP_KERNEL))
1047 return -ENOMEM;
1048
1049 p.sets = cfset_request.ctrset;
1050 cpumask_and(mask, &cfset_request.mask, cpu_online_mask);
1051 on_each_cpu_mask(mask, cfset_cpu_read, &p, 1);
1052 rc = cfset_all_copy(arg, mask);
1053 free_cpumask_var(mask);
1054 return rc;
1055}
1056
1057static long cfset_ioctl_read(unsigned long arg)
1058{
1059 struct s390_ctrset_read read;
1060 int ret = 0;
1061
1062 if (copy_from_user(&read, (char __user *)arg, sizeof(read)))
1063 return -EFAULT;
1064 ret = cfset_all_read(arg);
1065 return ret;
1066}
1067
1068static long cfset_ioctl_stop(void)
1069{
1070 int ret = ENXIO;
1071
1072 if (cfset_request.ctrset) {
1073 ret = cfset_all_stop();
1074 cfset_ctrset_clear();
1075 }
1076 return ret;
1077}
1078
1079static long cfset_ioctl_start(unsigned long arg)
1080{
1081 struct s390_ctrset_start __user *ustart;
1082 struct s390_ctrset_start start;
1083 void __user *umask;
1084 unsigned int len;
1085 int ret = 0;
1086 size_t need;
1087
1088 if (cfset_request.ctrset)
1089 return -EBUSY;
1090 ustart = (struct s390_ctrset_start __user *)arg;
1091 if (copy_from_user(&start, ustart, sizeof(start)))
1092 return -EFAULT;
1093 if (start.version != S390_HWCTR_START_VERSION)
1094 return -EINVAL;
1095 if (start.counter_sets & ~(cpumf_ctr_ctl[CPUMF_CTR_SET_BASIC] |
1096 cpumf_ctr_ctl[CPUMF_CTR_SET_USER] |
1097 cpumf_ctr_ctl[CPUMF_CTR_SET_CRYPTO] |
1098 cpumf_ctr_ctl[CPUMF_CTR_SET_EXT] |
1099 cpumf_ctr_ctl[CPUMF_CTR_SET_MT_DIAG]))
1100 return -EINVAL;
1101 if (!start.counter_sets)
1102 return -EINVAL;
1103 cpumask_clear(&cfset_request.mask);
1104 len = min_t(u64, start.cpumask_len, cpumask_size());
1105 umask = (void __user *)start.cpumask;
1106 if (copy_from_user(&cfset_request.mask, umask, len))
1107 return -EFAULT;
1108 if (cpumask_empty(&cfset_request.mask))
1109 return -EINVAL;
1110 need = cfset_needspace(start.counter_sets);
1111 if (put_user(need, &ustart->data_bytes))
1112 ret = -EFAULT;
1113 if (ret)
1114 goto out;
1115 cfset_request.ctrset = start.counter_sets;
1116 ret = cfset_all_start();
1117out:
1118 if (ret)
1119 cfset_ctrset_clear();
1120 debug_sprintf_event(cf_dbg, 4, "%s sets %#lx need %ld ret %d\n",
1121 __func__, cfset_request.ctrset, need, ret);
1122 return ret;
1123}
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137static long cfset_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1138{
1139 int ret;
1140
1141 get_online_cpus();
1142 mutex_lock(&cfset_ctrset_mutex);
1143 switch (cmd) {
1144 case S390_HWCTR_START:
1145 ret = cfset_ioctl_start(arg);
1146 break;
1147 case S390_HWCTR_STOP:
1148 ret = cfset_ioctl_stop();
1149 break;
1150 case S390_HWCTR_READ:
1151 ret = cfset_ioctl_read(arg);
1152 break;
1153 default:
1154 ret = -ENOTTY;
1155 break;
1156 }
1157 mutex_unlock(&cfset_ctrset_mutex);
1158 put_online_cpus();
1159 return ret;
1160}
1161
1162static const struct file_operations cfset_fops = {
1163 .owner = THIS_MODULE,
1164 .open = cfset_open,
1165 .release = cfset_release,
1166 .unlocked_ioctl = cfset_ioctl,
1167 .compat_ioctl = cfset_ioctl,
1168 .llseek = no_llseek
1169};
1170
1171static struct miscdevice cfset_dev = {
1172 .name = S390_HWCTR_DEVICE,
1173 .minor = MISC_DYNAMIC_MINOR,
1174 .fops = &cfset_fops,
1175};
1176
1177int cfset_online_cpu(unsigned int cpu)
1178{
1179 struct cfset_call_on_cpu_parm p;
1180
1181 mutex_lock(&cfset_ctrset_mutex);
1182 if (cfset_request.ctrset) {
1183 p.sets = cfset_request.ctrset;
1184 cfset_ioctl_on(&p);
1185 cpumask_set_cpu(cpu, &cfset_request.mask);
1186 }
1187 mutex_unlock(&cfset_ctrset_mutex);
1188 return 0;
1189}
1190
1191int cfset_offline_cpu(unsigned int cpu)
1192{
1193 struct cfset_call_on_cpu_parm p;
1194
1195 mutex_lock(&cfset_ctrset_mutex);
1196 if (cfset_request.ctrset) {
1197 p.sets = cfset_request.ctrset;
1198 cfset_ioctl_off(&p);
1199 cpumask_clear_cpu(cpu, &cfset_request.mask);
1200 }
1201 mutex_unlock(&cfset_ctrset_mutex);
1202 return 0;
1203}
1204
1205static void cfdiag_read(struct perf_event *event)
1206{
1207 debug_sprintf_event(cf_dbg, 3, "%s event %#llx count %ld\n", __func__,
1208 event->attr.config, local64_read(&event->count));
1209}
1210
1211static int get_authctrsets(void)
1212{
1213 struct cpu_cf_events *cpuhw;
1214 unsigned long auth = 0;
1215 enum cpumf_ctr_set i;
1216
1217 cpuhw = &get_cpu_var(cpu_cf_events);
1218 for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
1219 if (cpuhw->info.auth_ctl & cpumf_ctr_ctl[i])
1220 auth |= cpumf_ctr_ctl[i];
1221 }
1222 put_cpu_var(cpu_cf_events);
1223 return auth;
1224}
1225
1226
1227
1228
1229
1230static int cfdiag_event_init2(struct perf_event *event)
1231{
1232 struct perf_event_attr *attr = &event->attr;
1233 int err = 0;
1234
1235
1236 event->hw.config = attr->config;
1237 event->hw.sample_period = attr->sample_period;
1238 local64_set(&event->hw.period_left, event->hw.sample_period);
1239 local64_set(&event->count, 0);
1240 event->hw.last_period = event->hw.sample_period;
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250 event->hw.config_base = get_authctrsets();
1251
1252
1253 if (!event->hw.config_base)
1254 err = -EINVAL;
1255
1256 debug_sprintf_event(cf_dbg, 5, "%s err %d config_base %#lx\n",
1257 __func__, err, event->hw.config_base);
1258 return err;
1259}
1260
1261static int cfdiag_event_init(struct perf_event *event)
1262{
1263 struct perf_event_attr *attr = &event->attr;
1264 int err = -ENOENT;
1265
1266 if (event->attr.config != PERF_EVENT_CPUM_CF_DIAG ||
1267 event->attr.type != event->pmu->type)
1268 goto out;
1269
1270
1271
1272
1273
1274
1275 if (attr->exclude_kernel || attr->exclude_user || attr->exclude_hv ||
1276 !(attr->sample_type & (PERF_SAMPLE_CPU | PERF_SAMPLE_RAW))) {
1277 err = -EOPNOTSUPP;
1278 goto out;
1279 }
1280
1281
1282 cpumf_hw_inuse();
1283 event->destroy = hw_perf_event_destroy;
1284
1285 err = cfdiag_event_init2(event);
1286 if (unlikely(err))
1287 event->destroy(event);
1288out:
1289 return err;
1290}
1291
1292
1293
1294
1295
1296
1297
1298
1299CPUMF_EVENT_ATTR(CF_DIAG, CF_DIAG, PERF_EVENT_CPUM_CF_DIAG);
1300
1301static struct attribute *cfdiag_events_attr[] = {
1302 CPUMF_EVENT_PTR(CF_DIAG, CF_DIAG),
1303 NULL,
1304};
1305
1306PMU_FORMAT_ATTR(event, "config:0-63");
1307
1308static struct attribute *cfdiag_format_attr[] = {
1309 &format_attr_event.attr,
1310 NULL,
1311};
1312
1313static struct attribute_group cfdiag_events_group = {
1314 .name = "events",
1315 .attrs = cfdiag_events_attr,
1316};
1317static struct attribute_group cfdiag_format_group = {
1318 .name = "format",
1319 .attrs = cfdiag_format_attr,
1320};
1321static const struct attribute_group *cfdiag_attr_groups[] = {
1322 &cfdiag_events_group,
1323 &cfdiag_format_group,
1324 NULL,
1325};
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336static struct pmu cf_diag = {
1337 .task_ctx_nr = perf_sw_context,
1338 .event_init = cfdiag_event_init,
1339 .pmu_enable = cpumf_pmu_enable,
1340 .pmu_disable = cpumf_pmu_disable,
1341 .add = cpumf_pmu_add,
1342 .del = cpumf_pmu_del,
1343 .start = cpumf_pmu_start,
1344 .stop = cpumf_pmu_stop,
1345 .read = cfdiag_read,
1346
1347 .attr_groups = cfdiag_attr_groups
1348};
1349
1350
1351
1352
1353
1354static size_t cfdiag_maxsize(struct cpumf_ctr_info *info)
1355{
1356 size_t max_size = sizeof(struct cf_trailer_entry);
1357 enum cpumf_ctr_set i;
1358
1359 for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
1360 size_t size = cpum_cf_ctrset_size(i, info);
1361
1362 if (size)
1363 max_size += size * sizeof(u64) +
1364 sizeof(struct cf_ctrset_entry);
1365 }
1366 return max_size;
1367}
1368
1369
1370static void cfdiag_get_cpu_speed(void)
1371{
1372 if (cpum_sf_avail()) {
1373 struct hws_qsi_info_block si;
1374
1375 memset(&si, 0, sizeof(si));
1376 if (!qsi(&si)) {
1377 cfdiag_cpu_speed = si.cpu_speed;
1378 return;
1379 }
1380 }
1381
1382
1383
1384
1385 if (test_facility(34)) {
1386 unsigned long mhz = __ecag(ECAG_CPU_ATTRIBUTE, 0);
1387
1388 if (mhz != -1UL)
1389 cfdiag_cpu_speed = mhz & 0xffffffff;
1390 }
1391}
1392
1393static int cfset_init(void)
1394{
1395 struct cpumf_ctr_info info;
1396 size_t need;
1397 int rc;
1398
1399 if (qctri(&info))
1400 return -ENODEV;
1401
1402 cfdiag_get_cpu_speed();
1403
1404 need = cfdiag_maxsize(&info);
1405 if (need > sizeof(((struct cpu_cf_events *)0)->start)) {
1406 pr_err("Insufficient memory for PMU(cpum_cf_diag) need=%zu\n",
1407 need);
1408 return -ENOMEM;
1409 }
1410
1411 rc = misc_register(&cfset_dev);
1412 if (rc) {
1413 pr_err("Registration of /dev/%s failed rc=%i\n",
1414 cfset_dev.name, rc);
1415 goto out;
1416 }
1417
1418 rc = perf_pmu_register(&cf_diag, "cpum_cf_diag", -1);
1419 if (rc) {
1420 misc_deregister(&cfset_dev);
1421 pr_err("Registration of PMU(cpum_cf_diag) failed with rc=%i\n",
1422 rc);
1423 }
1424out:
1425 return rc;
1426}
1427
1428device_initcall(cpumf_pmu_init);
1429