1*4882a593Smuzhiyun #include <stdbool.h>
2*4882a593Smuzhiyun #include <stdlib.h>
3*4882a593Smuzhiyun #include <linux/kernel.h>
4*4882a593Smuzhiyun #include <linux/types.h>
5*4882a593Smuzhiyun #include <linux/bitops.h>
6*4882a593Smuzhiyun #include <linux/log2.h>
7*4882a593Smuzhiyun #include <linux/zalloc.h>
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include "../../util/evlist.h"
10*4882a593Smuzhiyun #include "../../util/auxtrace.h"
11*4882a593Smuzhiyun #include "../../util/evsel.h"
12*4882a593Smuzhiyun #include "../../util/record.h"
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #define PERF_EVENT_CPUM_SF 0xB0000 /* Event: Basic-sampling */
15*4882a593Smuzhiyun #define PERF_EVENT_CPUM_SF_DIAG 0xBD000 /* Event: Combined-sampling */
16*4882a593Smuzhiyun #define DEFAULT_AUX_PAGES 128
17*4882a593Smuzhiyun #define DEFAULT_FREQ 4000
18*4882a593Smuzhiyun
cpumsf_free(struct auxtrace_record * itr)19*4882a593Smuzhiyun static void cpumsf_free(struct auxtrace_record *itr)
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun free(itr);
22*4882a593Smuzhiyun }
23*4882a593Smuzhiyun
cpumsf_info_priv_size(struct auxtrace_record * itr __maybe_unused,struct evlist * evlist __maybe_unused)24*4882a593Smuzhiyun static size_t cpumsf_info_priv_size(struct auxtrace_record *itr __maybe_unused,
25*4882a593Smuzhiyun struct evlist *evlist __maybe_unused)
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun return 0;
28*4882a593Smuzhiyun }
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun static int
cpumsf_info_fill(struct auxtrace_record * itr __maybe_unused,struct perf_session * session __maybe_unused,struct perf_record_auxtrace_info * auxtrace_info __maybe_unused,size_t priv_size __maybe_unused)31*4882a593Smuzhiyun cpumsf_info_fill(struct auxtrace_record *itr __maybe_unused,
32*4882a593Smuzhiyun struct perf_session *session __maybe_unused,
33*4882a593Smuzhiyun struct perf_record_auxtrace_info *auxtrace_info __maybe_unused,
34*4882a593Smuzhiyun size_t priv_size __maybe_unused)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun auxtrace_info->type = PERF_AUXTRACE_S390_CPUMSF;
37*4882a593Smuzhiyun return 0;
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun static unsigned long
cpumsf_reference(struct auxtrace_record * itr __maybe_unused)41*4882a593Smuzhiyun cpumsf_reference(struct auxtrace_record *itr __maybe_unused)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun return 0;
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun static int
cpumsf_recording_options(struct auxtrace_record * ar __maybe_unused,struct evlist * evlist __maybe_unused,struct record_opts * opts)47*4882a593Smuzhiyun cpumsf_recording_options(struct auxtrace_record *ar __maybe_unused,
48*4882a593Smuzhiyun struct evlist *evlist __maybe_unused,
49*4882a593Smuzhiyun struct record_opts *opts)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun unsigned int factor = 1;
52*4882a593Smuzhiyun unsigned int pages;
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun opts->full_auxtrace = true;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /*
57*4882a593Smuzhiyun * The AUX buffer size should be set properly to avoid
58*4882a593Smuzhiyun * overflow of samples if it is not set explicitly.
59*4882a593Smuzhiyun * DEFAULT_AUX_PAGES is an proper size when sampling frequency
60*4882a593Smuzhiyun * is DEFAULT_FREQ. It is expected to hold about 1/2 second
61*4882a593Smuzhiyun * of sampling data. The size used for AUX buffer will scale
62*4882a593Smuzhiyun * according to the specified frequency and DEFAULT_FREQ.
63*4882a593Smuzhiyun */
64*4882a593Smuzhiyun if (!opts->auxtrace_mmap_pages) {
65*4882a593Smuzhiyun if (opts->user_freq != UINT_MAX)
66*4882a593Smuzhiyun factor = (opts->user_freq + DEFAULT_FREQ
67*4882a593Smuzhiyun - 1) / DEFAULT_FREQ;
68*4882a593Smuzhiyun pages = DEFAULT_AUX_PAGES * factor;
69*4882a593Smuzhiyun opts->auxtrace_mmap_pages = roundup_pow_of_two(pages);
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun return 0;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun static int
cpumsf_parse_snapshot_options(struct auxtrace_record * itr __maybe_unused,struct record_opts * opts __maybe_unused,const char * str __maybe_unused)76*4882a593Smuzhiyun cpumsf_parse_snapshot_options(struct auxtrace_record *itr __maybe_unused,
77*4882a593Smuzhiyun struct record_opts *opts __maybe_unused,
78*4882a593Smuzhiyun const char *str __maybe_unused)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun return 0;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun /*
84*4882a593Smuzhiyun * auxtrace_record__init is called when perf record
85*4882a593Smuzhiyun * check if the event really need auxtrace
86*4882a593Smuzhiyun */
auxtrace_record__init(struct evlist * evlist,int * err)87*4882a593Smuzhiyun struct auxtrace_record *auxtrace_record__init(struct evlist *evlist,
88*4882a593Smuzhiyun int *err)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun struct auxtrace_record *aux;
91*4882a593Smuzhiyun struct evsel *pos;
92*4882a593Smuzhiyun int diagnose = 0;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun *err = 0;
95*4882a593Smuzhiyun if (evlist->core.nr_entries == 0)
96*4882a593Smuzhiyun return NULL;
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun evlist__for_each_entry(evlist, pos) {
99*4882a593Smuzhiyun if (pos->core.attr.config == PERF_EVENT_CPUM_SF_DIAG) {
100*4882a593Smuzhiyun diagnose = 1;
101*4882a593Smuzhiyun break;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun if (!diagnose)
106*4882a593Smuzhiyun return NULL;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun /* sampling in diagnose mode. alloc aux buffer */
109*4882a593Smuzhiyun aux = zalloc(sizeof(*aux));
110*4882a593Smuzhiyun if (aux == NULL) {
111*4882a593Smuzhiyun *err = -ENOMEM;
112*4882a593Smuzhiyun return NULL;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun aux->parse_snapshot_options = cpumsf_parse_snapshot_options;
116*4882a593Smuzhiyun aux->recording_options = cpumsf_recording_options;
117*4882a593Smuzhiyun aux->info_priv_size = cpumsf_info_priv_size;
118*4882a593Smuzhiyun aux->info_fill = cpumsf_info_fill;
119*4882a593Smuzhiyun aux->free = cpumsf_free;
120*4882a593Smuzhiyun aux->reference = cpumsf_reference;
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun return aux;
123*4882a593Smuzhiyun }
124