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