blob: 6355315a91fbbc5cde444935e1086c163c321348 [file] [log] [blame]
Adrian Hunter718c6022015-04-09 18:53:42 +03001/*
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>
Adrian Hunter9e0cc4f2015-04-09 18:53:44 +030021#include <stddef.h>
Adrian Hunter718c6022015-04-09 18:53:42 +030022#include <linux/perf_event.h>
23#include <linux/types.h>
24
25#include "../perf.h"
Adrian Hunterc4468702015-04-09 18:53:48 +030026#include "session.h"
Adrian Hunter718c6022015-04-09 18:53:42 +030027
Adrian Hunter9e0cc4f2015-04-09 18:53:44 +030028union perf_event;
29struct perf_session;
Adrian Hunter718c6022015-04-09 18:53:42 +030030struct perf_evlist;
Adrian Hunter9e0cc4f2015-04-09 18:53:44 +030031struct perf_tool;
Adrian Hunterf6986c952015-04-09 18:53:49 +030032struct option;
Adrian Hunter9e0cc4f2015-04-09 18:53:44 +030033struct record_opts;
34struct auxtrace_info_event;
Adrian Hunter718c6022015-04-09 18:53:42 +030035
Adrian Hunterf6986c952015-04-09 18:53:49 +030036enum itrace_period_type {
37 PERF_ITRACE_PERIOD_INSTRUCTIONS,
38 PERF_ITRACE_PERIOD_TICKS,
39 PERF_ITRACE_PERIOD_NANOSECS,
40};
41
42/**
43 * struct itrace_synth_opts - AUX area tracing synthesis options.
44 * @set: indicates whether or not options have been set
45 * @inject: indicates the event (not just the sample) must be fully synthesized
46 * because 'perf inject' will write it out
47 * @instructions: whether to synthesize 'instructions' events
48 * @branches: whether to synthesize 'branches' events
49 * @errors: whether to synthesize decoder error events
50 * @dont_decode: whether to skip decoding entirely
51 * @log: write a decoding log
52 * @calls: limit branch samples to calls (can be combined with @returns)
53 * @returns: limit branch samples to returns (can be combined with @calls)
54 * @callchain: add callchain to 'instructions' events
55 * @callchain_sz: maximum callchain size
56 * @period: 'instructions' events period
57 * @period_type: 'instructions' events period type
58 */
59struct itrace_synth_opts {
60 bool set;
61 bool inject;
62 bool instructions;
63 bool branches;
64 bool errors;
65 bool dont_decode;
66 bool log;
67 bool calls;
68 bool returns;
69 bool callchain;
70 unsigned int callchain_sz;
71 unsigned long long period;
72 enum itrace_period_type period_type;
73};
74
Adrian Hunter718c6022015-04-09 18:53:42 +030075/**
Adrian Hunterc4468702015-04-09 18:53:48 +030076 * struct auxtrace - session callbacks to allow AUX area data decoding.
77 * @process_event: lets the decoder see all session events
78 * @flush_events: process any remaining data
79 * @free_events: free resources associated with event processing
80 * @free: free resources associated with the session
81 */
82struct auxtrace {
83 int (*process_event)(struct perf_session *session,
84 union perf_event *event,
85 struct perf_sample *sample,
86 struct perf_tool *tool);
87 int (*flush_events)(struct perf_session *session,
88 struct perf_tool *tool);
89 void (*free_events)(struct perf_session *session);
90 void (*free)(struct perf_session *session);
91};
92
93/**
Adrian Hunter718c6022015-04-09 18:53:42 +030094 * struct auxtrace_mmap - records an mmap of the auxtrace buffer.
95 * @base: address of mapped area
96 * @userpg: pointer to buffer's perf_event_mmap_page
97 * @mask: %0 if @len is not a power of two, otherwise (@len - %1)
98 * @len: size of mapped area
99 * @prev: previous aux_head
100 * @idx: index of this mmap
101 * @tid: tid for a per-thread mmap (also set if there is only 1 tid on a per-cpu
102 * mmap) otherwise %0
103 * @cpu: cpu number for a per-cpu mmap otherwise %-1
104 */
105struct auxtrace_mmap {
106 void *base;
107 void *userpg;
108 size_t mask;
109 size_t len;
110 u64 prev;
111 int idx;
112 pid_t tid;
113 int cpu;
114};
115
116/**
117 * struct auxtrace_mmap_params - parameters to set up struct auxtrace_mmap.
118 * @mask: %0 if @len is not a power of two, otherwise (@len - %1)
119 * @offset: file offset of mapped area
120 * @len: size of mapped area
121 * @prot: mmap memory protection
122 * @idx: index of this mmap
123 * @tid: tid for a per-thread mmap (also set if there is only 1 tid on a per-cpu
124 * mmap) otherwise %0
125 * @cpu: cpu number for a per-cpu mmap otherwise %-1
126 */
127struct auxtrace_mmap_params {
128 size_t mask;
129 off_t offset;
130 size_t len;
131 int prot;
132 int idx;
133 pid_t tid;
134 int cpu;
135};
136
Adrian Hunter9e0cc4f2015-04-09 18:53:44 +0300137/**
138 * struct auxtrace_record - callbacks for recording AUX area data.
139 * @recording_options: validate and process recording options
140 * @info_priv_size: return the size of the private data in auxtrace_info_event
141 * @info_fill: fill-in the private data in auxtrace_info_event
142 * @free: free this auxtrace record structure
143 * @reference: provide a 64-bit reference number for auxtrace_event
144 * @read_finish: called after reading from an auxtrace mmap
145 */
146struct auxtrace_record {
147 int (*recording_options)(struct auxtrace_record *itr,
148 struct perf_evlist *evlist,
149 struct record_opts *opts);
150 size_t (*info_priv_size)(struct auxtrace_record *itr);
151 int (*info_fill)(struct auxtrace_record *itr,
152 struct perf_session *session,
153 struct auxtrace_info_event *auxtrace_info,
154 size_t priv_size);
155 void (*free)(struct auxtrace_record *itr);
156 u64 (*reference)(struct auxtrace_record *itr);
157 int (*read_finish)(struct auxtrace_record *itr, int idx);
158};
159
Adrian Hunter718c6022015-04-09 18:53:42 +0300160static inline u64 auxtrace_mmap__read_head(struct auxtrace_mmap *mm)
161{
162 struct perf_event_mmap_page *pc = mm->userpg;
163#if BITS_PER_LONG == 64 || !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT)
164 u64 head = ACCESS_ONCE(pc->aux_head);
165#else
166 u64 head = __sync_val_compare_and_swap(&pc->aux_head, 0, 0);
167#endif
168
169 /* Ensure all reads are done after we read the head */
170 rmb();
171 return head;
172}
173
174static inline void auxtrace_mmap__write_tail(struct auxtrace_mmap *mm, u64 tail)
175{
176 struct perf_event_mmap_page *pc = mm->userpg;
177#if BITS_PER_LONG != 64 && defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT)
178 u64 old_tail;
179#endif
180
181 /* Ensure all reads are done before we write the tail out */
182 mb();
183#if BITS_PER_LONG == 64 || !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT)
184 pc->aux_tail = tail;
185#else
186 do {
187 old_tail = __sync_val_compare_and_swap(&pc->aux_tail, 0, 0);
188 } while (!__sync_bool_compare_and_swap(&pc->aux_tail, old_tail, tail));
189#endif
190}
191
192int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
193 struct auxtrace_mmap_params *mp,
194 void *userpg, int fd);
195void auxtrace_mmap__munmap(struct auxtrace_mmap *mm);
196void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp,
197 off_t auxtrace_offset,
198 unsigned int auxtrace_pages,
199 bool auxtrace_overwrite);
200void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
201 struct perf_evlist *evlist, int idx,
202 bool per_cpu);
203
Adrian Hunter9e0cc4f2015-04-09 18:53:44 +0300204typedef int (*process_auxtrace_t)(struct perf_tool *tool,
205 union perf_event *event, void *data1,
206 size_t len1, void *data2, size_t len2);
207
208int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
209 struct perf_tool *tool, process_auxtrace_t fn);
210
211struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist,
212 int *err);
213
214int auxtrace_record__options(struct auxtrace_record *itr,
215 struct perf_evlist *evlist,
216 struct record_opts *opts);
217size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr);
218int auxtrace_record__info_fill(struct auxtrace_record *itr,
219 struct perf_session *session,
220 struct auxtrace_info_event *auxtrace_info,
221 size_t priv_size);
222void auxtrace_record__free(struct auxtrace_record *itr);
223u64 auxtrace_record__reference(struct auxtrace_record *itr);
224
225int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
226 struct perf_tool *tool,
227 struct perf_session *session,
228 perf_event__handler_t process);
Adrian Hunterf6986c952015-04-09 18:53:49 +0300229int itrace_parse_synth_opts(const struct option *opt, const char *str,
230 int unset);
231void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts);
Adrian Hunter9e0cc4f2015-04-09 18:53:44 +0300232
Adrian Hunterc4468702015-04-09 18:53:48 +0300233static inline int auxtrace__process_event(struct perf_session *session,
234 union perf_event *event,
235 struct perf_sample *sample,
236 struct perf_tool *tool)
237{
238 if (!session->auxtrace)
239 return 0;
240
241 return session->auxtrace->process_event(session, event, sample, tool);
242}
243
244static inline int auxtrace__flush_events(struct perf_session *session,
245 struct perf_tool *tool)
246{
247 if (!session->auxtrace)
248 return 0;
249
250 return session->auxtrace->flush_events(session, tool);
251}
252
253static inline void auxtrace__free_events(struct perf_session *session)
254{
255 if (!session->auxtrace)
256 return;
257
258 return session->auxtrace->free_events(session);
259}
260
261static inline void auxtrace__free(struct perf_session *session)
262{
263 if (!session->auxtrace)
264 return;
265
266 return session->auxtrace->free(session);
267}
268
Adrian Hunter718c6022015-04-09 18:53:42 +0300269#endif