Skip to content

Commit 0901b56

Browse files
German Gomezacmel
authored andcommitted
perf arm-spe: Add snapshot mode support
This patch enables support for snapshot mode of arm_spe events, including the implementation of the necessary callbacks (excluding find_snapshot, which is to be included in a followup commit). Reviewed-by: James Clark <[email protected]> Reviewed-by: Leo Yan <[email protected]> Signed-off-by: German Gomez <[email protected]> Acked-by: Namhyung Kim <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: John Garry <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Mathieu Poirier <[email protected]> Cc: Will Deacon <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Tested-by: Leo Yan <[email protected]> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 9aba0ad commit 0901b56

File tree

1 file changed

+130
-0
lines changed

1 file changed

+130
-0
lines changed

tools/perf/arch/arm64/util/arm-spe.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,55 @@ static int arm_spe_info_fill(struct auxtrace_record *itr,
8484
return 0;
8585
}
8686

87+
static void
88+
arm_spe_snapshot_resolve_auxtrace_defaults(struct record_opts *opts,
89+
bool privileged)
90+
{
91+
/*
92+
* The default snapshot size is the auxtrace mmap size. If neither auxtrace mmap size nor
93+
* snapshot size is specified, then the default is 4MiB for privileged users, 128KiB for
94+
* unprivileged users.
95+
*
96+
* The default auxtrace mmap size is 4MiB/page_size for privileged users, 128KiB for
97+
* unprivileged users. If an unprivileged user does not specify mmap pages, the mmap pages
98+
* will be reduced from the default 512KiB/page_size to 256KiB/page_size, otherwise the
99+
* user is likely to get an error as they exceed their mlock limmit.
100+
*/
101+
102+
/*
103+
* No size were given to '-S' or '-m,', so go with the default
104+
*/
105+
if (!opts->auxtrace_snapshot_size && !opts->auxtrace_mmap_pages) {
106+
if (privileged) {
107+
opts->auxtrace_mmap_pages = MiB(4) / page_size;
108+
} else {
109+
opts->auxtrace_mmap_pages = KiB(128) / page_size;
110+
if (opts->mmap_pages == UINT_MAX)
111+
opts->mmap_pages = KiB(256) / page_size;
112+
}
113+
} else if (!opts->auxtrace_mmap_pages && !privileged && opts->mmap_pages == UINT_MAX) {
114+
opts->mmap_pages = KiB(256) / page_size;
115+
}
116+
117+
/*
118+
* '-m,xyz' was specified but no snapshot size, so make the snapshot size as big as the
119+
* auxtrace mmap area.
120+
*/
121+
if (!opts->auxtrace_snapshot_size)
122+
opts->auxtrace_snapshot_size = opts->auxtrace_mmap_pages * (size_t)page_size;
123+
124+
/*
125+
* '-Sxyz' was specified but no auxtrace mmap area, so make the auxtrace mmap area big
126+
* enough to fit the requested snapshot size.
127+
*/
128+
if (!opts->auxtrace_mmap_pages) {
129+
size_t sz = opts->auxtrace_snapshot_size;
130+
131+
sz = round_up(sz, page_size) / page_size;
132+
opts->auxtrace_mmap_pages = roundup_pow_of_two(sz);
133+
}
134+
}
135+
87136
static int arm_spe_recording_options(struct auxtrace_record *itr,
88137
struct evlist *evlist,
89138
struct record_opts *opts)
@@ -115,6 +164,36 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
115164
if (!opts->full_auxtrace)
116165
return 0;
117166

167+
/*
168+
* we are in snapshot mode.
169+
*/
170+
if (opts->auxtrace_snapshot_mode) {
171+
/*
172+
* Command arguments '-Sxyz' and/or '-m,xyz' are missing, so fill those in with
173+
* default values.
174+
*/
175+
if (!opts->auxtrace_snapshot_size || !opts->auxtrace_mmap_pages)
176+
arm_spe_snapshot_resolve_auxtrace_defaults(opts, privileged);
177+
178+
/*
179+
* Snapshot size can't be bigger than the auxtrace area.
180+
*/
181+
if (opts->auxtrace_snapshot_size > opts->auxtrace_mmap_pages * (size_t)page_size) {
182+
pr_err("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n",
183+
opts->auxtrace_snapshot_size,
184+
opts->auxtrace_mmap_pages * (size_t)page_size);
185+
return -EINVAL;
186+
}
187+
188+
/*
189+
* Something went wrong somewhere - this shouldn't happen.
190+
*/
191+
if (!opts->auxtrace_snapshot_size || !opts->auxtrace_mmap_pages) {
192+
pr_err("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n");
193+
return -EINVAL;
194+
}
195+
}
196+
118197
/* We are in full trace mode but '-m,xyz' wasn't specified */
119198
if (!opts->auxtrace_mmap_pages) {
120199
if (privileged) {
@@ -138,6 +217,9 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
138217
}
139218
}
140219

220+
if (opts->auxtrace_snapshot_mode)
221+
pr_debug2("%sx snapshot size: %zu\n", ARM_SPE_PMU_NAME,
222+
opts->auxtrace_snapshot_size);
141223

142224
/*
143225
* To obtain the auxtrace buffer file descriptor, the auxtrace event
@@ -172,6 +254,51 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
172254
return 0;
173255
}
174256

257+
static int arm_spe_parse_snapshot_options(struct auxtrace_record *itr __maybe_unused,
258+
struct record_opts *opts,
259+
const char *str)
260+
{
261+
unsigned long long snapshot_size = 0;
262+
char *endptr;
263+
264+
if (str) {
265+
snapshot_size = strtoull(str, &endptr, 0);
266+
if (*endptr || snapshot_size > SIZE_MAX)
267+
return -1;
268+
}
269+
270+
opts->auxtrace_snapshot_mode = true;
271+
opts->auxtrace_snapshot_size = snapshot_size;
272+
273+
return 0;
274+
}
275+
276+
static int arm_spe_snapshot_start(struct auxtrace_record *itr)
277+
{
278+
struct arm_spe_recording *ptr =
279+
container_of(itr, struct arm_spe_recording, itr);
280+
struct evsel *evsel;
281+
282+
evlist__for_each_entry(ptr->evlist, evsel) {
283+
if (evsel->core.attr.type == ptr->arm_spe_pmu->type)
284+
return evsel__disable(evsel);
285+
}
286+
return -EINVAL;
287+
}
288+
289+
static int arm_spe_snapshot_finish(struct auxtrace_record *itr)
290+
{
291+
struct arm_spe_recording *ptr =
292+
container_of(itr, struct arm_spe_recording, itr);
293+
struct evsel *evsel;
294+
295+
evlist__for_each_entry(ptr->evlist, evsel) {
296+
if (evsel->core.attr.type == ptr->arm_spe_pmu->type)
297+
return evsel__enable(evsel);
298+
}
299+
return -EINVAL;
300+
}
301+
175302
static u64 arm_spe_reference(struct auxtrace_record *itr __maybe_unused)
176303
{
177304
struct timespec ts;
@@ -207,6 +334,9 @@ struct auxtrace_record *arm_spe_recording_init(int *err,
207334

208335
sper->arm_spe_pmu = arm_spe_pmu;
209336
sper->itr.pmu = arm_spe_pmu;
337+
sper->itr.snapshot_start = arm_spe_snapshot_start;
338+
sper->itr.snapshot_finish = arm_spe_snapshot_finish;
339+
sper->itr.parse_snapshot_options = arm_spe_parse_snapshot_options;
210340
sper->itr.recording_options = arm_spe_recording_options;
211341
sper->itr.info_priv_size = arm_spe_info_priv_size;
212342
sper->itr.info_fill = arm_spe_info_fill;

0 commit comments

Comments
 (0)