Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf tools: Add AUX area tracing Snapshot Mode

Add support for making snapshots of AUX area tracing data.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1430404667-10593-9-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Adrian Hunter and committed by
Arnaldo Carvalho de Melo
d20031bb 0ad21f68

+119 -10
+3
tools/perf/perf.h
··· 55 55 bool sample_intr_regs; 56 56 bool running_time; 57 57 bool full_auxtrace; 58 + bool auxtrace_snapshot_mode; 58 59 unsigned int freq; 59 60 unsigned int mmap_pages; 60 61 unsigned int auxtrace_mmap_pages; ··· 63 62 u64 branch_stack; 64 63 u64 default_interval; 65 64 u64 user_interval; 65 + size_t auxtrace_snapshot_size; 66 + const char *auxtrace_snapshot_opts; 66 67 bool sample_transaction; 67 68 unsigned initial_delay; 68 69 bool use_clockid;
+75 -10
tools/perf/util/auxtrace.c
··· 504 504 itr->free(itr); 505 505 } 506 506 507 + int 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 + 514 + int 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 + 521 + int 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 + 507 530 int auxtrace_record__options(struct auxtrace_record *itr, 508 531 struct perf_evlist *evlist, 509 532 struct record_opts *opts) ··· 541 518 if (itr) 542 519 return itr->reference(itr); 543 520 return 0; 521 + } 522 + 523 + int auxtrace_parse_snapshot_options(struct auxtrace_record *itr, 524 + struct record_opts *opts, const char *str) 525 + { 526 + if (!str) 527 + return 0; 528 + 529 + if (itr) 530 + return itr->parse_snapshot_options(itr, opts, str); 531 + 532 + pr_err("No AUX area tracing to snapshot\n"); 533 + return -EINVAL; 544 534 } 545 535 546 536 struct auxtrace_record *__weak ··· 1113 1077 return 0; 1114 1078 } 1115 1079 1116 - int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr, 1117 - struct perf_tool *tool, process_auxtrace_t fn) 1080 + static int __auxtrace_mmap__read(struct auxtrace_mmap *mm, 1081 + struct auxtrace_record *itr, 1082 + struct perf_tool *tool, process_auxtrace_t fn, 1083 + bool snapshot, size_t snapshot_size) 1118 1084 { 1119 - u64 head = auxtrace_mmap__read_head(mm); 1120 - u64 old = mm->prev, offset, ref; 1085 + u64 head, old = mm->prev, offset, ref; 1121 1086 unsigned char *data = mm->base; 1122 1087 size_t size, head_off, old_off, len1, len2, padding; 1123 1088 union perf_event ev; 1124 1089 void *data1, *data2; 1090 + 1091 + if (snapshot) { 1092 + head = auxtrace_mmap__read_snapshot_head(mm); 1093 + if (auxtrace_record__find_snapshot(itr, mm->idx, mm, data, 1094 + &head, &old)) 1095 + return -1; 1096 + } else { 1097 + head = auxtrace_mmap__read_head(mm); 1098 + } 1125 1099 1126 1100 if (old == head) 1127 1101 return 0; ··· 1151 1105 size = head_off - old_off; 1152 1106 else 1153 1107 size = mm->len - (old_off - head_off); 1108 + 1109 + if (snapshot && size > snapshot_size) 1110 + size = snapshot_size; 1154 1111 1155 1112 ref = auxtrace_record__reference(itr); 1156 1113 ··· 1202 1153 1203 1154 mm->prev = head; 1204 1155 1205 - auxtrace_mmap__write_tail(mm, head); 1206 - if (itr->read_finish) { 1207 - int err; 1156 + if (!snapshot) { 1157 + auxtrace_mmap__write_tail(mm, head); 1158 + if (itr->read_finish) { 1159 + int err; 1208 1160 1209 - err = itr->read_finish(itr, mm->idx); 1210 - if (err < 0) 1211 - return err; 1161 + err = itr->read_finish(itr, mm->idx); 1162 + if (err < 0) 1163 + return err; 1164 + } 1212 1165 } 1213 1166 1214 1167 return 1; 1168 + } 1169 + 1170 + int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr, 1171 + struct perf_tool *tool, process_auxtrace_t fn) 1172 + { 1173 + return __auxtrace_mmap__read(mm, itr, tool, fn, false, 0); 1174 + } 1175 + 1176 + int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm, 1177 + struct auxtrace_record *itr, 1178 + struct perf_tool *tool, process_auxtrace_t fn, 1179 + size_t snapshot_size) 1180 + { 1181 + return __auxtrace_mmap__read(mm, itr, tool, fn, true, snapshot_size); 1215 1182 } 1216 1183 1217 1184 /**
+41
tools/perf/util/auxtrace.h
··· 276 276 * @info_priv_size: return the size of the private data in auxtrace_info_event 277 277 * @info_fill: fill-in the private data in auxtrace_info_event 278 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 283 * @reference: provide a 64-bit reference number for auxtrace_event 280 284 * @read_finish: called after reading from an auxtrace mmap 281 285 */ ··· 293 289 struct auxtrace_info_event *auxtrace_info, 294 290 size_t priv_size); 295 291 void (*free)(struct auxtrace_record *itr); 292 + int (*snapshot_start)(struct auxtrace_record *itr); 293 + int (*snapshot_finish)(struct auxtrace_record *itr); 294 + int (*find_snapshot)(struct auxtrace_record *itr, int idx, 295 + struct auxtrace_mmap *mm, unsigned char *data, 296 + u64 *head, u64 *old); 297 + int (*parse_snapshot_options)(struct auxtrace_record *itr, 298 + struct record_opts *opts, 299 + const char *str); 296 300 u64 (*reference)(struct auxtrace_record *itr); 297 301 int (*read_finish)(struct auxtrace_record *itr, int idx); 298 302 }; 299 303 300 304 #ifdef HAVE_AUXTRACE_SUPPORT 305 + 306 + /* 307 + * In snapshot mode the mmapped page is read-only which makes using 308 + * __sync_val_compare_and_swap() problematic. However, snapshot mode expects 309 + * the buffer is not updated while the snapshot is made (e.g. Intel PT disables 310 + * the event) so there is not a race anyway. 311 + */ 312 + static inline u64 auxtrace_mmap__read_snapshot_head(struct auxtrace_mmap *mm) 313 + { 314 + struct perf_event_mmap_page *pc = mm->userpg; 315 + u64 head = ACCESS_ONCE(pc->aux_head); 316 + 317 + /* Ensure all reads are done after we read the head */ 318 + rmb(); 319 + return head; 320 + } 301 321 302 322 static inline u64 auxtrace_mmap__read_head(struct auxtrace_mmap *mm) 303 323 { ··· 374 346 int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr, 375 347 struct perf_tool *tool, process_auxtrace_t fn); 376 348 349 + int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm, 350 + struct auxtrace_record *itr, 351 + struct perf_tool *tool, process_auxtrace_t fn, 352 + size_t snapshot_size); 353 + 377 354 int auxtrace_queues__init(struct auxtrace_queues *queues); 378 355 int auxtrace_queues__add_event(struct auxtrace_queues *queues, 379 356 struct perf_session *session, ··· 416 383 struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist, 417 384 int *err); 418 385 386 + int auxtrace_parse_snapshot_options(struct auxtrace_record *itr, 387 + struct record_opts *opts, 388 + const char *str); 419 389 int auxtrace_record__options(struct auxtrace_record *itr, 420 390 struct perf_evlist *evlist, 421 391 struct record_opts *opts); ··· 428 392 struct auxtrace_info_event *auxtrace_info, 429 393 size_t priv_size); 430 394 void auxtrace_record__free(struct auxtrace_record *itr); 395 + int auxtrace_record__snapshot_start(struct auxtrace_record *itr); 396 + int auxtrace_record__snapshot_finish(struct auxtrace_record *itr); 397 + int auxtrace_record__find_snapshot(struct auxtrace_record *itr, int idx, 398 + struct auxtrace_mmap *mm, 399 + unsigned char *data, u64 *head, u64 *old); 431 400 u64 auxtrace_record__reference(struct auxtrace_record *itr); 432 401 433 402 int auxtrace_index__auxtrace_event(struct list_head *head, union perf_event *event,