aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/perf.h3
-rw-r--r--tools/perf/util/auxtrace.c85
-rw-r--r--tools/perf/util/auxtrace.h41
3 files changed, 119 insertions, 10 deletions
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 5042093d5213..aa79fb8a16d4 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -55,6 +55,7 @@ struct record_opts {
55 bool sample_intr_regs; 55 bool sample_intr_regs;
56 bool running_time; 56 bool running_time;
57 bool full_auxtrace; 57 bool full_auxtrace;
58 bool auxtrace_snapshot_mode;
58 unsigned int freq; 59 unsigned int freq;
59 unsigned int mmap_pages; 60 unsigned int mmap_pages;
60 unsigned int auxtrace_mmap_pages; 61 unsigned int auxtrace_mmap_pages;
@@ -62,6 +63,8 @@ struct record_opts {
62 u64 branch_stack; 63 u64 branch_stack;
63 u64 default_interval; 64 u64 default_interval;
64 u64 user_interval; 65 u64 user_interval;
66 size_t auxtrace_snapshot_size;
67 const char *auxtrace_snapshot_opts;
65 bool sample_transaction; 68 bool sample_transaction;
66 unsigned initial_delay; 69 unsigned initial_delay;
67 bool use_clockid; 70 bool use_clockid;
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 129371048fc1..df66966cfde7 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -504,6 +504,29 @@ void auxtrace_record__free(struct auxtrace_record *itr)
504 itr->free(itr); 504 itr->free(itr);
505} 505}
506 506
507int auxtrace_record__snapshot_start(struct auxtrace_record *itr)
508{
509 if (itr && itr->snapshot_start)
510 return itr->snapshot_start(itr);
511 return 0;
512}
513
514int auxtrace_record__snapshot_finish(struct auxtrace_record *itr)
515{
516 if (itr && itr->snapshot_finish)
517 return itr->snapshot_finish(itr);
518 return 0;
519}
520
521int auxtrace_record__find_snapshot(struct auxtrace_record *itr, int idx,
522 struct auxtrace_mmap *mm,
523 unsigned char *data, u64 *head, u64 *old)
524{
525 if (itr && itr->find_snapshot)
526 return itr->find_snapshot(itr, idx, mm, data, head, old);
527 return 0;
528}
529
507int auxtrace_record__options(struct auxtrace_record *itr, 530int auxtrace_record__options(struct auxtrace_record *itr,
508 struct perf_evlist *evlist, 531 struct perf_evlist *evlist,
509 struct record_opts *opts) 532 struct record_opts *opts)
@@ -520,6 +543,19 @@ u64 auxtrace_record__reference(struct auxtrace_record *itr)
520 return 0; 543 return 0;
521} 544}
522 545
546int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
547 struct record_opts *opts, const char *str)
548{
549 if (!str)
550 return 0;
551
552 if (itr)
553 return itr->parse_snapshot_options(itr, opts, str);
554
555 pr_err("No AUX area tracing to snapshot\n");
556 return -EINVAL;
557}
558
523struct auxtrace_record *__weak 559struct auxtrace_record *__weak
524auxtrace_record__init(struct perf_evlist *evlist __maybe_unused, int *err) 560auxtrace_record__init(struct perf_evlist *evlist __maybe_unused, int *err)
525{ 561{
@@ -1077,16 +1113,26 @@ int perf_event__process_auxtrace_error(struct perf_tool *tool __maybe_unused,
1077 return 0; 1113 return 0;
1078} 1114}
1079 1115
1080int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr, 1116static int __auxtrace_mmap__read(struct auxtrace_mmap *mm,
1081 struct perf_tool *tool, process_auxtrace_t fn) 1117 struct auxtrace_record *itr,
1118 struct perf_tool *tool, process_auxtrace_t fn,
1119 bool snapshot, size_t snapshot_size)
1082{ 1120{
1083 u64 head = auxtrace_mmap__read_head(mm); 1121 u64 head, old = mm->prev, offset, ref;
1084 u64 old = mm->prev, offset, ref;
1085 unsigned char *data = mm->base; 1122 unsigned char *data = mm->base;
1086 size_t size, head_off, old_off, len1, len2, padding; 1123 size_t size, head_off, old_off, len1, len2, padding;
1087 union perf_event ev; 1124 union perf_event ev;
1088 void *data1, *data2; 1125 void *data1, *data2;
1089 1126
1127 if (snapshot) {
1128 head = auxtrace_mmap__read_snapshot_head(mm);
1129 if (auxtrace_record__find_snapshot(itr, mm->idx, mm, data,
1130 &head, &old))
1131 return -1;
1132 } else {
1133 head = auxtrace_mmap__read_head(mm);
1134 }
1135
1090 if (old == head) 1136 if (old == head)
1091 return 0; 1137 return 0;
1092 1138
@@ -1106,6 +1152,9 @@ int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
1106 else 1152 else
1107 size = mm->len - (old_off - head_off); 1153 size = mm->len - (old_off - head_off);
1108 1154
1155 if (snapshot && size > snapshot_size)
1156 size = snapshot_size;
1157
1109 ref = auxtrace_record__reference(itr); 1158 ref = auxtrace_record__reference(itr);
1110 1159
1111 if (head > old || size <= head || mm->mask) { 1160 if (head > old || size <= head || mm->mask) {
@@ -1153,18 +1202,34 @@ int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
1153 1202
1154 mm->prev = head; 1203 mm->prev = head;
1155 1204
1156 auxtrace_mmap__write_tail(mm, head); 1205 if (!snapshot) {
1157 if (itr->read_finish) { 1206 auxtrace_mmap__write_tail(mm, head);
1158 int err; 1207 if (itr->read_finish) {
1208 int err;
1159 1209
1160 err = itr->read_finish(itr, mm->idx); 1210 err = itr->read_finish(itr, mm->idx);
1161 if (err < 0) 1211 if (err < 0)
1162 return err; 1212 return err;
1213 }
1163 } 1214 }
1164 1215
1165 return 1; 1216 return 1;
1166} 1217}
1167 1218
1219int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
1220 struct perf_tool *tool, process_auxtrace_t fn)
1221{
1222 return __auxtrace_mmap__read(mm, itr, tool, fn, false, 0);
1223}
1224
1225int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm,
1226 struct auxtrace_record *itr,
1227 struct perf_tool *tool, process_auxtrace_t fn,
1228 size_t snapshot_size)
1229{
1230 return __auxtrace_mmap__read(mm, itr, tool, fn, true, snapshot_size);
1231}
1232
1168/** 1233/**
1169 * struct auxtrace_cache - hash table to implement a cache 1234 * struct auxtrace_cache - hash table to implement a cache
1170 * @hashtable: the hashtable 1235 * @hashtable: the hashtable
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 8c6cbb123fe5..c2c677e62733 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -276,6 +276,10 @@ struct auxtrace_mmap_params {
276 * @info_priv_size: return the size of the private data in auxtrace_info_event 276 * @info_priv_size: return the size of the private data in auxtrace_info_event
277 * @info_fill: fill-in the private data in auxtrace_info_event 277 * @info_fill: fill-in the private data in auxtrace_info_event
278 * @free: free this auxtrace record structure 278 * @free: free this auxtrace record structure
279 * @snapshot_start: starting a snapshot
280 * @snapshot_finish: finishing a snapshot
281 * @find_snapshot: find data to snapshot within auxtrace mmap
282 * @parse_snapshot_options: parse snapshot options
279 * @reference: provide a 64-bit reference number for auxtrace_event 283 * @reference: provide a 64-bit reference number for auxtrace_event
280 * @read_finish: called after reading from an auxtrace mmap 284 * @read_finish: called after reading from an auxtrace mmap
281 */ 285 */
@@ -289,12 +293,36 @@ struct auxtrace_record {
289 struct auxtrace_info_event *auxtrace_info, 293 struct auxtrace_info_event *auxtrace_info,
290 size_t priv_size); 294 size_t priv_size);
291 void (*free)(struct auxtrace_record *itr); 295 void (*free)(struct auxtrace_record *itr);
296 int (*snapshot_start)(struct auxtrace_record *itr);
297 int (*snapshot_finish)(struct auxtrace_record *itr);
298 int (*find_snapshot)(struct auxtrace_record *itr, int idx,
299 struct auxtrace_mmap *mm, unsigned char *data,
300 u64 *head, u64 *old);
301 int (*parse_snapshot_options)(struct auxtrace_record *itr,
302 struct record_opts *opts,
303 const char *str);
292 u64 (*reference)(struct auxtrace_record *itr); 304 u64 (*reference)(struct auxtrace_record *itr);
293 int (*read_finish)(struct auxtrace_record *itr, int idx); 305 int (*read_finish)(struct auxtrace_record *itr, int idx);
294}; 306};
295 307
296#ifdef HAVE_AUXTRACE_SUPPORT 308#ifdef HAVE_AUXTRACE_SUPPORT
297 309
310/*
311 * In snapshot mode the mmapped page is read-only which makes using
312 * __sync_val_compare_and_swap() problematic. However, snapshot mode expects
313 * the buffer is not updated while the snapshot is made (e.g. Intel PT disables
314 * the event) so there is not a race anyway.
315 */
316static inline u64 auxtrace_mmap__read_snapshot_head(struct auxtrace_mmap *mm)
317{
318 struct perf_event_mmap_page *pc = mm->userpg;
319 u64 head = ACCESS_ONCE(pc->aux_head);
320
321 /* Ensure all reads are done after we read the head */
322 rmb();
323 return head;
324}
325
298static inline u64 auxtrace_mmap__read_head(struct auxtrace_mmap *mm) 326static inline u64 auxtrace_mmap__read_head(struct auxtrace_mmap *mm)
299{ 327{
300 struct perf_event_mmap_page *pc = mm->userpg; 328 struct perf_event_mmap_page *pc = mm->userpg;
@@ -346,6 +374,11 @@ typedef int (*process_auxtrace_t)(struct perf_tool *tool,
346int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr, 374int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
347 struct perf_tool *tool, process_auxtrace_t fn); 375 struct perf_tool *tool, process_auxtrace_t fn);
348 376
377int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm,
378 struct auxtrace_record *itr,
379 struct perf_tool *tool, process_auxtrace_t fn,
380 size_t snapshot_size);
381
349int auxtrace_queues__init(struct auxtrace_queues *queues); 382int auxtrace_queues__init(struct auxtrace_queues *queues);
350int auxtrace_queues__add_event(struct auxtrace_queues *queues, 383int auxtrace_queues__add_event(struct auxtrace_queues *queues,
351 struct perf_session *session, 384 struct perf_session *session,
@@ -383,6 +416,9 @@ void *auxtrace_cache__lookup(struct auxtrace_cache *c, u32 key);
383struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist, 416struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist,
384 int *err); 417 int *err);
385 418
419int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
420 struct record_opts *opts,
421 const char *str);
386int auxtrace_record__options(struct auxtrace_record *itr, 422int auxtrace_record__options(struct auxtrace_record *itr,
387 struct perf_evlist *evlist, 423 struct perf_evlist *evlist,
388 struct record_opts *opts); 424 struct record_opts *opts);
@@ -392,6 +428,11 @@ int auxtrace_record__info_fill(struct auxtrace_record *itr,
392 struct auxtrace_info_event *auxtrace_info, 428 struct auxtrace_info_event *auxtrace_info,
393 size_t priv_size); 429 size_t priv_size);
394void auxtrace_record__free(struct auxtrace_record *itr); 430void auxtrace_record__free(struct auxtrace_record *itr);
431int auxtrace_record__snapshot_start(struct auxtrace_record *itr);
432int auxtrace_record__snapshot_finish(struct auxtrace_record *itr);
433int auxtrace_record__find_snapshot(struct auxtrace_record *itr, int idx,
434 struct auxtrace_mmap *mm,
435 unsigned char *data, u64 *head, u64 *old);
395u64 auxtrace_record__reference(struct auxtrace_record *itr); 436u64 auxtrace_record__reference(struct auxtrace_record *itr);
396 437
397int auxtrace_index__auxtrace_event(struct list_head *head, union perf_event *event, 438int auxtrace_index__auxtrace_event(struct list_head *head, union perf_event *event,