xref: /openbmc/linux/tools/perf/util/auxtrace.h (revision 53c76b0e)
1 /*
2  * auxtrace.h: AUX area trace support
3  * Copyright (c) 2013-2015, Intel Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  */
15 
16 #ifndef __PERF_AUXTRACE_H
17 #define __PERF_AUXTRACE_H
18 
19 #include <sys/types.h>
20 #include <stdbool.h>
21 #include <stddef.h>
22 #include <linux/list.h>
23 #include <linux/perf_event.h>
24 #include <linux/types.h>
25 
26 #include "../perf.h"
27 #include "event.h"
28 #include "session.h"
29 #include "debug.h"
30 
31 union perf_event;
32 struct perf_session;
33 struct perf_evlist;
34 struct perf_tool;
35 struct option;
36 struct record_opts;
37 struct auxtrace_info_event;
38 struct events_stats;
39 
40 enum auxtrace_type {
41 	PERF_AUXTRACE_UNKNOWN,
42 };
43 
44 enum itrace_period_type {
45 	PERF_ITRACE_PERIOD_INSTRUCTIONS,
46 	PERF_ITRACE_PERIOD_TICKS,
47 	PERF_ITRACE_PERIOD_NANOSECS,
48 };
49 
50 /**
51  * struct itrace_synth_opts - AUX area tracing synthesis options.
52  * @set: indicates whether or not options have been set
53  * @inject: indicates the event (not just the sample) must be fully synthesized
54  *          because 'perf inject' will write it out
55  * @instructions: whether to synthesize 'instructions' events
56  * @branches: whether to synthesize 'branches' events
57  * @transactions: whether to synthesize events for transactions
58  * @errors: whether to synthesize decoder error events
59  * @dont_decode: whether to skip decoding entirely
60  * @log: write a decoding log
61  * @calls: limit branch samples to calls (can be combined with @returns)
62  * @returns: limit branch samples to returns (can be combined with @calls)
63  * @callchain: add callchain to 'instructions' events
64  * @callchain_sz: maximum callchain size
65  * @period: 'instructions' events period
66  * @period_type: 'instructions' events period type
67  */
68 struct itrace_synth_opts {
69 	bool			set;
70 	bool			inject;
71 	bool			instructions;
72 	bool			branches;
73 	bool			transactions;
74 	bool			errors;
75 	bool			dont_decode;
76 	bool			log;
77 	bool			calls;
78 	bool			returns;
79 	bool			callchain;
80 	unsigned int		callchain_sz;
81 	unsigned long long	period;
82 	enum itrace_period_type	period_type;
83 };
84 
85 /**
86  * struct auxtrace_index_entry - indexes a AUX area tracing event within a
87  *                               perf.data file.
88  * @file_offset: offset within the perf.data file
89  * @sz: size of the event
90  */
91 struct auxtrace_index_entry {
92 	u64			file_offset;
93 	u64			sz;
94 };
95 
96 #define PERF_AUXTRACE_INDEX_ENTRY_COUNT 256
97 
98 /**
99  * struct auxtrace_index - index of AUX area tracing events within a perf.data
100  *                         file.
101  * @list: linking a number of arrays of entries
102  * @nr: number of entries
103  * @entries: array of entries
104  */
105 struct auxtrace_index {
106 	struct list_head	list;
107 	size_t			nr;
108 	struct auxtrace_index_entry entries[PERF_AUXTRACE_INDEX_ENTRY_COUNT];
109 };
110 
111 /**
112  * struct auxtrace - session callbacks to allow AUX area data decoding.
113  * @process_event: lets the decoder see all session events
114  * @flush_events: process any remaining data
115  * @free_events: free resources associated with event processing
116  * @free: free resources associated with the session
117  */
118 struct auxtrace {
119 	int (*process_event)(struct perf_session *session,
120 			     union perf_event *event,
121 			     struct perf_sample *sample,
122 			     struct perf_tool *tool);
123 	int (*process_auxtrace_event)(struct perf_session *session,
124 				      union perf_event *event,
125 				      struct perf_tool *tool);
126 	int (*flush_events)(struct perf_session *session,
127 			    struct perf_tool *tool);
128 	void (*free_events)(struct perf_session *session);
129 	void (*free)(struct perf_session *session);
130 };
131 
132 /**
133  * struct auxtrace_buffer - a buffer containing AUX area tracing data.
134  * @list: buffers are queued in a list held by struct auxtrace_queue
135  * @size: size of the buffer in bytes
136  * @pid: in per-thread mode, the pid this buffer is associated with
137  * @tid: in per-thread mode, the tid this buffer is associated with
138  * @cpu: in per-cpu mode, the cpu this buffer is associated with
139  * @data: actual buffer data (can be null if the data has not been loaded)
140  * @data_offset: file offset at which the buffer can be read
141  * @mmap_addr: mmap address at which the buffer can be read
142  * @mmap_size: size of the mmap at @mmap_addr
143  * @data_needs_freeing: @data was malloc'd so free it when it is no longer
144  *                      needed
145  * @consecutive: the original data was split up and this buffer is consecutive
146  *               to the previous buffer
147  * @offset: offset as determined by aux_head / aux_tail members of struct
148  *          perf_event_mmap_page
149  * @reference: an implementation-specific reference determined when the data is
150  *             recorded
151  * @buffer_nr: used to number each buffer
152  * @use_size: implementation actually only uses this number of bytes
153  * @use_data: implementation actually only uses data starting at this address
154  */
155 struct auxtrace_buffer {
156 	struct list_head	list;
157 	size_t			size;
158 	pid_t			pid;
159 	pid_t			tid;
160 	int			cpu;
161 	void			*data;
162 	off_t			data_offset;
163 	void			*mmap_addr;
164 	size_t			mmap_size;
165 	bool			data_needs_freeing;
166 	bool			consecutive;
167 	u64			offset;
168 	u64			reference;
169 	u64			buffer_nr;
170 	size_t			use_size;
171 	void			*use_data;
172 };
173 
174 /**
175  * struct auxtrace_queue - a queue of AUX area tracing data buffers.
176  * @head: head of buffer list
177  * @tid: in per-thread mode, the tid this queue is associated with
178  * @cpu: in per-cpu mode, the cpu this queue is associated with
179  * @set: %true once this queue has been dedicated to a specific thread or cpu
180  * @priv: implementation-specific data
181  */
182 struct auxtrace_queue {
183 	struct list_head	head;
184 	pid_t			tid;
185 	int			cpu;
186 	bool			set;
187 	void			*priv;
188 };
189 
190 /**
191  * struct auxtrace_queues - an array of AUX area tracing queues.
192  * @queue_array: array of queues
193  * @nr_queues: number of queues
194  * @new_data: set whenever new data is queued
195  * @populated: queues have been fully populated using the auxtrace_index
196  * @next_buffer_nr: used to number each buffer
197  */
198 struct auxtrace_queues {
199 	struct auxtrace_queue	*queue_array;
200 	unsigned int		nr_queues;
201 	bool			new_data;
202 	bool			populated;
203 	u64			next_buffer_nr;
204 };
205 
206 /**
207  * struct auxtrace_heap_item - element of struct auxtrace_heap.
208  * @queue_nr: queue number
209  * @ordinal: value used for sorting (lowest ordinal is top of the heap) expected
210  *           to be a timestamp
211  */
212 struct auxtrace_heap_item {
213 	unsigned int		queue_nr;
214 	u64			ordinal;
215 };
216 
217 /**
218  * struct auxtrace_heap - a heap suitable for sorting AUX area tracing queues.
219  * @heap_array: the heap
220  * @heap_cnt: the number of elements in the heap
221  * @heap_sz: maximum number of elements (grows as needed)
222  */
223 struct auxtrace_heap {
224 	struct auxtrace_heap_item	*heap_array;
225 	unsigned int		heap_cnt;
226 	unsigned int		heap_sz;
227 };
228 
229 /**
230  * struct auxtrace_mmap - records an mmap of the auxtrace buffer.
231  * @base: address of mapped area
232  * @userpg: pointer to buffer's perf_event_mmap_page
233  * @mask: %0 if @len is not a power of two, otherwise (@len - %1)
234  * @len: size of mapped area
235  * @prev: previous aux_head
236  * @idx: index of this mmap
237  * @tid: tid for a per-thread mmap (also set if there is only 1 tid on a per-cpu
238  *       mmap) otherwise %0
239  * @cpu: cpu number for a per-cpu mmap otherwise %-1
240  */
241 struct auxtrace_mmap {
242 	void		*base;
243 	void		*userpg;
244 	size_t		mask;
245 	size_t		len;
246 	u64		prev;
247 	int		idx;
248 	pid_t		tid;
249 	int		cpu;
250 };
251 
252 /**
253  * struct auxtrace_mmap_params - parameters to set up struct auxtrace_mmap.
254  * @mask: %0 if @len is not a power of two, otherwise (@len - %1)
255  * @offset: file offset of mapped area
256  * @len: size of mapped area
257  * @prot: mmap memory protection
258  * @idx: index of this mmap
259  * @tid: tid for a per-thread mmap (also set if there is only 1 tid on a per-cpu
260  *       mmap) otherwise %0
261  * @cpu: cpu number for a per-cpu mmap otherwise %-1
262  */
263 struct auxtrace_mmap_params {
264 	size_t		mask;
265 	off_t		offset;
266 	size_t		len;
267 	int		prot;
268 	int		idx;
269 	pid_t		tid;
270 	int		cpu;
271 };
272 
273 /**
274  * struct auxtrace_record - callbacks for recording AUX area data.
275  * @recording_options: validate and process recording options
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
278  * @free: free this auxtrace record structure
279  * @reference: provide a 64-bit reference number for auxtrace_event
280  * @read_finish: called after reading from an auxtrace mmap
281  */
282 struct auxtrace_record {
283 	int (*recording_options)(struct auxtrace_record *itr,
284 				 struct perf_evlist *evlist,
285 				 struct record_opts *opts);
286 	size_t (*info_priv_size)(struct auxtrace_record *itr);
287 	int (*info_fill)(struct auxtrace_record *itr,
288 			 struct perf_session *session,
289 			 struct auxtrace_info_event *auxtrace_info,
290 			 size_t priv_size);
291 	void (*free)(struct auxtrace_record *itr);
292 	u64 (*reference)(struct auxtrace_record *itr);
293 	int (*read_finish)(struct auxtrace_record *itr, int idx);
294 };
295 
296 #ifdef HAVE_AUXTRACE_SUPPORT
297 
298 static inline u64 auxtrace_mmap__read_head(struct auxtrace_mmap *mm)
299 {
300 	struct perf_event_mmap_page *pc = mm->userpg;
301 #if BITS_PER_LONG == 64 || !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT)
302 	u64 head = ACCESS_ONCE(pc->aux_head);
303 #else
304 	u64 head = __sync_val_compare_and_swap(&pc->aux_head, 0, 0);
305 #endif
306 
307 	/* Ensure all reads are done after we read the head */
308 	rmb();
309 	return head;
310 }
311 
312 static inline void auxtrace_mmap__write_tail(struct auxtrace_mmap *mm, u64 tail)
313 {
314 	struct perf_event_mmap_page *pc = mm->userpg;
315 #if BITS_PER_LONG != 64 && defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT)
316 	u64 old_tail;
317 #endif
318 
319 	/* Ensure all reads are done before we write the tail out */
320 	mb();
321 #if BITS_PER_LONG == 64 || !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT)
322 	pc->aux_tail = tail;
323 #else
324 	do {
325 		old_tail = __sync_val_compare_and_swap(&pc->aux_tail, 0, 0);
326 	} while (!__sync_bool_compare_and_swap(&pc->aux_tail, old_tail, tail));
327 #endif
328 }
329 
330 int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
331 			struct auxtrace_mmap_params *mp,
332 			void *userpg, int fd);
333 void auxtrace_mmap__munmap(struct auxtrace_mmap *mm);
334 void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp,
335 				off_t auxtrace_offset,
336 				unsigned int auxtrace_pages,
337 				bool auxtrace_overwrite);
338 void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
339 				   struct perf_evlist *evlist, int idx,
340 				   bool per_cpu);
341 
342 typedef int (*process_auxtrace_t)(struct perf_tool *tool,
343 				  union perf_event *event, void *data1,
344 				  size_t len1, void *data2, size_t len2);
345 
346 int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
347 			struct perf_tool *tool, process_auxtrace_t fn);
348 
349 int auxtrace_queues__init(struct auxtrace_queues *queues);
350 int auxtrace_queues__add_event(struct auxtrace_queues *queues,
351 			       struct perf_session *session,
352 			       union perf_event *event, off_t data_offset,
353 			       struct auxtrace_buffer **buffer_ptr);
354 void auxtrace_queues__free(struct auxtrace_queues *queues);
355 int auxtrace_queues__process_index(struct auxtrace_queues *queues,
356 				   struct perf_session *session);
357 struct auxtrace_buffer *auxtrace_buffer__next(struct auxtrace_queue *queue,
358 					      struct auxtrace_buffer *buffer);
359 void *auxtrace_buffer__get_data(struct auxtrace_buffer *buffer, int fd);
360 void auxtrace_buffer__put_data(struct auxtrace_buffer *buffer);
361 void auxtrace_buffer__drop_data(struct auxtrace_buffer *buffer);
362 void auxtrace_buffer__free(struct auxtrace_buffer *buffer);
363 
364 int auxtrace_heap__add(struct auxtrace_heap *heap, unsigned int queue_nr,
365 		       u64 ordinal);
366 void auxtrace_heap__pop(struct auxtrace_heap *heap);
367 void auxtrace_heap__free(struct auxtrace_heap *heap);
368 
369 struct auxtrace_cache_entry {
370 	struct hlist_node hash;
371 	u32 key;
372 };
373 
374 struct auxtrace_cache *auxtrace_cache__new(unsigned int bits, size_t entry_size,
375 					   unsigned int limit_percent);
376 void auxtrace_cache__free(struct auxtrace_cache *auxtrace_cache);
377 void *auxtrace_cache__alloc_entry(struct auxtrace_cache *c);
378 void auxtrace_cache__free_entry(struct auxtrace_cache *c, void *entry);
379 int auxtrace_cache__add(struct auxtrace_cache *c, u32 key,
380 			struct auxtrace_cache_entry *entry);
381 void *auxtrace_cache__lookup(struct auxtrace_cache *c, u32 key);
382 
383 struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist,
384 					      int *err);
385 
386 int auxtrace_record__options(struct auxtrace_record *itr,
387 			     struct perf_evlist *evlist,
388 			     struct record_opts *opts);
389 size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr);
390 int auxtrace_record__info_fill(struct auxtrace_record *itr,
391 			       struct perf_session *session,
392 			       struct auxtrace_info_event *auxtrace_info,
393 			       size_t priv_size);
394 void auxtrace_record__free(struct auxtrace_record *itr);
395 u64 auxtrace_record__reference(struct auxtrace_record *itr);
396 
397 int auxtrace_index__auxtrace_event(struct list_head *head, union perf_event *event,
398 				   off_t file_offset);
399 int auxtrace_index__write(int fd, struct list_head *head);
400 int auxtrace_index__process(int fd, u64 size, struct perf_session *session,
401 			    bool needs_swap);
402 void auxtrace_index__free(struct list_head *head);
403 
404 void auxtrace_synth_error(struct auxtrace_error_event *auxtrace_error, int type,
405 			  int code, int cpu, pid_t pid, pid_t tid, u64 ip,
406 			  const char *msg);
407 
408 int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
409 					 struct perf_tool *tool,
410 					 struct perf_session *session,
411 					 perf_event__handler_t process);
412 int perf_event__process_auxtrace_info(struct perf_tool *tool,
413 				      union perf_event *event,
414 				      struct perf_session *session);
415 s64 perf_event__process_auxtrace(struct perf_tool *tool,
416 				 union perf_event *event,
417 				 struct perf_session *session);
418 int perf_event__process_auxtrace_error(struct perf_tool *tool,
419 				       union perf_event *event,
420 				       struct perf_session *session);
421 int itrace_parse_synth_opts(const struct option *opt, const char *str,
422 			    int unset);
423 void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts);
424 
425 size_t perf_event__fprintf_auxtrace_error(union perf_event *event, FILE *fp);
426 void perf_session__auxtrace_error_inc(struct perf_session *session,
427 				      union perf_event *event);
428 void events_stats__auxtrace_error_warn(const struct events_stats *stats);
429 
430 static inline int auxtrace__process_event(struct perf_session *session,
431 					  union perf_event *event,
432 					  struct perf_sample *sample,
433 					  struct perf_tool *tool)
434 {
435 	if (!session->auxtrace)
436 		return 0;
437 
438 	return session->auxtrace->process_event(session, event, sample, tool);
439 }
440 
441 static inline int auxtrace__flush_events(struct perf_session *session,
442 					 struct perf_tool *tool)
443 {
444 	if (!session->auxtrace)
445 		return 0;
446 
447 	return session->auxtrace->flush_events(session, tool);
448 }
449 
450 static inline void auxtrace__free_events(struct perf_session *session)
451 {
452 	if (!session->auxtrace)
453 		return;
454 
455 	return session->auxtrace->free_events(session);
456 }
457 
458 static inline void auxtrace__free(struct perf_session *session)
459 {
460 	if (!session->auxtrace)
461 		return;
462 
463 	return session->auxtrace->free(session);
464 }
465 
466 #else
467 
468 static inline struct auxtrace_record *
469 auxtrace_record__init(struct perf_evlist *evlist __maybe_unused,
470 		      int *err __maybe_unused)
471 {
472 	*err = 0;
473 	return NULL;
474 }
475 
476 static inline
477 void auxtrace_record__free(struct auxtrace_record *itr __maybe_unused)
478 {
479 }
480 
481 static inline int
482 perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr __maybe_unused,
483 				     struct perf_tool *tool __maybe_unused,
484 				     struct perf_session *session __maybe_unused,
485 				     perf_event__handler_t process __maybe_unused)
486 {
487 	return -EINVAL;
488 }
489 
490 static inline
491 int auxtrace_record__options(struct auxtrace_record *itr __maybe_unused,
492 			     struct perf_evlist *evlist __maybe_unused,
493 			     struct record_opts *opts __maybe_unused)
494 {
495 	return 0;
496 }
497 
498 #define perf_event__process_auxtrace_info		0
499 #define perf_event__process_auxtrace			0
500 #define perf_event__process_auxtrace_error		0
501 
502 static inline
503 void perf_session__auxtrace_error_inc(struct perf_session *session
504 				      __maybe_unused,
505 				      union perf_event *event
506 				      __maybe_unused)
507 {
508 }
509 
510 static inline
511 void events_stats__auxtrace_error_warn(const struct events_stats *stats
512 				       __maybe_unused)
513 {
514 }
515 
516 static inline
517 int itrace_parse_synth_opts(const struct option *opt __maybe_unused,
518 			    const char *str __maybe_unused,
519 			    int unset __maybe_unused)
520 {
521 	pr_err("AUX area tracing not supported\n");
522 	return -EINVAL;
523 }
524 
525 static inline
526 int auxtrace__process_event(struct perf_session *session __maybe_unused,
527 			    union perf_event *event __maybe_unused,
528 			    struct perf_sample *sample __maybe_unused,
529 			    struct perf_tool *tool __maybe_unused)
530 {
531 	return 0;
532 }
533 
534 static inline
535 int auxtrace__flush_events(struct perf_session *session __maybe_unused,
536 			   struct perf_tool *tool __maybe_unused)
537 {
538 	return 0;
539 }
540 
541 static inline
542 void auxtrace__free_events(struct perf_session *session __maybe_unused)
543 {
544 }
545 
546 static inline
547 void auxtrace_cache__free(struct auxtrace_cache *auxtrace_cache __maybe_unused)
548 {
549 }
550 
551 static inline
552 void auxtrace__free(struct perf_session *session __maybe_unused)
553 {
554 }
555 
556 static inline
557 int auxtrace_index__write(int fd __maybe_unused,
558 			  struct list_head *head __maybe_unused)
559 {
560 	return -EINVAL;
561 }
562 
563 static inline
564 int auxtrace_index__process(int fd __maybe_unused,
565 			    u64 size __maybe_unused,
566 			    struct perf_session *session __maybe_unused,
567 			    bool needs_swap __maybe_unused)
568 {
569 	return -EINVAL;
570 }
571 
572 static inline
573 void auxtrace_index__free(struct list_head *head __maybe_unused)
574 {
575 }
576 
577 int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
578 			struct auxtrace_mmap_params *mp,
579 			void *userpg, int fd);
580 void auxtrace_mmap__munmap(struct auxtrace_mmap *mm);
581 void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp,
582 				off_t auxtrace_offset,
583 				unsigned int auxtrace_pages,
584 				bool auxtrace_overwrite);
585 void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
586 				   struct perf_evlist *evlist, int idx,
587 				   bool per_cpu);
588 
589 #endif
590 
591 #endif
592