xref: /freebsd/sys/sys/pmclog.h (revision aa0a1e58)
1 /*-
2  * Copyright (c) 2005-2007, Joseph Koshy
3  * Copyright (c) 2007 The FreeBSD Foundation
4  * All rights reserved.
5  *
6  * Portions of this software were developed by A. Joseph Koshy under
7  * sponsorship from the FreeBSD Foundation and Google, Inc.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32 
33 #ifndef	_SYS_PMCLOG_H_
34 #define	_SYS_PMCLOG_H_
35 
36 #include <sys/pmc.h>
37 
38 enum pmclog_type {
39 	/* V1 ABI */
40 	PMCLOG_TYPE_CLOSELOG,
41 	PMCLOG_TYPE_DROPNOTIFY,
42 	PMCLOG_TYPE_INITIALIZE,
43 	PMCLOG_TYPE_MAPPINGCHANGE, /* unused in v1 */
44 	PMCLOG_TYPE_PCSAMPLE,
45 	PMCLOG_TYPE_PMCALLOCATE,
46 	PMCLOG_TYPE_PMCATTACH,
47 	PMCLOG_TYPE_PMCDETACH,
48 	PMCLOG_TYPE_PROCCSW,
49 	PMCLOG_TYPE_PROCEXEC,
50 	PMCLOG_TYPE_PROCEXIT,
51 	PMCLOG_TYPE_PROCFORK,
52 	PMCLOG_TYPE_SYSEXIT,
53 	PMCLOG_TYPE_USERDATA,
54 	/*
55 	 * V2 ABI
56 	 *
57 	 * The MAP_{IN,OUT} event types obsolete the MAPPING_CHANGE
58 	 * event type.  The CALLCHAIN event type obsoletes the
59 	 * PCSAMPLE event type.
60 	 */
61 	PMCLOG_TYPE_MAP_IN,
62 	PMCLOG_TYPE_MAP_OUT,
63 	PMCLOG_TYPE_CALLCHAIN
64 };
65 
66 /*
67  * A log entry descriptor comprises of a 32 bit header and a 64 bit
68  * time stamp followed by as many 32 bit words are required to record
69  * the event.
70  *
71  * Header field format:
72  *
73  *  31           24           16                                   0
74  *   +------------+------------+-----------------------------------+
75  *   |    MAGIC   |    TYPE    |               LENGTH              |
76  *   +------------+------------+-----------------------------------+
77  *
78  * MAGIC 	is the constant PMCLOG_HEADER_MAGIC.
79  * TYPE  	contains a value of type enum pmclog_type.
80  * LENGTH	contains the length of the event record, in bytes.
81  */
82 
83 #define	PMCLOG_ENTRY_HEADER				\
84 	uint32_t		pl_header;		\
85 	uint32_t		pl_ts_sec;		\
86 	uint32_t		pl_ts_nsec;
87 
88 
89 /*
90  * The following structures are used to describe the size of each kind
91  * of log entry to sizeof().  To keep the compiler from adding
92  * padding, the fields of each structure are aligned to their natural
93  * boundaries, and the structures are marked as 'packed'.
94  *
95  * The actual reading and writing of the log file is always in terms
96  * of 4 byte quantities.
97  */
98 
99 struct pmclog_callchain {
100 	PMCLOG_ENTRY_HEADER
101 	uint32_t		pl_pid;
102 	uint32_t		pl_pmcid;
103 	uint32_t		pl_cpuflags;
104 	/* 8 byte aligned */
105 	uintptr_t		pl_pc[PMC_CALLCHAIN_DEPTH_MAX];
106 } __packed;
107 
108 #define	PMC_CALLCHAIN_CPUFLAGS_TO_CPU(CF)	(((CF) >> 16) & 0xFFFF)
109 #define	PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(CF)	((CF) & PMC_CC_F_USERSPACE)
110 #define	PMC_CALLCHAIN_TO_CPUFLAGS(CPU,FLAGS)	\
111 	(((CPU) << 16) | ((FLAGS) & 0xFFFF))
112 
113 struct pmclog_closelog {
114 	PMCLOG_ENTRY_HEADER
115 };
116 
117 struct pmclog_dropnotify {
118 	PMCLOG_ENTRY_HEADER
119 };
120 
121 struct pmclog_initialize {
122 	PMCLOG_ENTRY_HEADER
123 	uint32_t		pl_version;	/* driver version */
124 	uint32_t		pl_cpu;		/* enum pmc_cputype */
125 } __packed;
126 
127 struct pmclog_map_in {
128 	PMCLOG_ENTRY_HEADER
129 	uint32_t		pl_pid;
130 	uintfptr_t		pl_start;	/* 8 byte aligned */
131 	char			pl_pathname[PATH_MAX];
132 } __packed;
133 
134 struct pmclog_map_out {
135 	PMCLOG_ENTRY_HEADER
136 	uint32_t		pl_pid;
137 	uintfptr_t		pl_start;	/* 8 byte aligned */
138 	uintfptr_t		pl_end;
139 } __packed;
140 
141 struct pmclog_pcsample {
142 	PMCLOG_ENTRY_HEADER
143 	uint32_t		pl_pid;
144 	uintfptr_t		pl_pc;		/* 8 byte aligned */
145 	uint32_t		pl_pmcid;
146 	uint32_t		pl_usermode;
147 } __packed;
148 
149 struct pmclog_pmcallocate {
150 	PMCLOG_ENTRY_HEADER
151 	uint32_t		pl_pmcid;
152 	uint32_t		pl_event;
153 	uint32_t		pl_flags;
154 } __packed;
155 
156 struct pmclog_pmcattach {
157 	PMCLOG_ENTRY_HEADER
158 	uint32_t		pl_pmcid;
159 	uint32_t		pl_pid;
160 	char			pl_pathname[PATH_MAX];
161 } __packed;
162 
163 struct pmclog_pmcdetach {
164 	PMCLOG_ENTRY_HEADER
165 	uint32_t		pl_pmcid;
166 	uint32_t		pl_pid;
167 } __packed;
168 
169 struct pmclog_proccsw {
170 	PMCLOG_ENTRY_HEADER
171 	uint32_t		pl_pmcid;
172 	uint64_t		pl_value;	/* keep 8 byte aligned */
173 	uint32_t		pl_pid;
174 } __packed;
175 
176 struct pmclog_procexec {
177 	PMCLOG_ENTRY_HEADER
178 	uint32_t		pl_pid;
179 	uintfptr_t		pl_start;	/* keep 8 byte aligned */
180 	uint32_t		pl_pmcid;
181 	char			pl_pathname[PATH_MAX];
182 } __packed;
183 
184 struct pmclog_procexit {
185 	PMCLOG_ENTRY_HEADER
186 	uint32_t		pl_pmcid;
187 	uint64_t		pl_value;	/* keep 8 byte aligned */
188 	uint32_t		pl_pid;
189 } __packed;
190 
191 struct pmclog_procfork {
192 	PMCLOG_ENTRY_HEADER
193 	uint32_t		pl_oldpid;
194 	uint32_t		pl_newpid;
195 } __packed;
196 
197 struct pmclog_sysexit {
198 	PMCLOG_ENTRY_HEADER
199 	uint32_t		pl_pid;
200 } __packed;
201 
202 struct pmclog_userdata {
203 	PMCLOG_ENTRY_HEADER
204 	uint32_t		pl_userdata;
205 } __packed;
206 
207 union pmclog_entry {		/* only used to size scratch areas */
208 	struct pmclog_callchain		pl_cc;
209 	struct pmclog_closelog		pl_cl;
210 	struct pmclog_dropnotify	pl_dn;
211 	struct pmclog_initialize	pl_i;
212 	struct pmclog_map_in		pl_mi;
213 	struct pmclog_map_out		pl_mo;
214 	struct pmclog_pcsample		pl_s;
215 	struct pmclog_pmcallocate	pl_a;
216 	struct pmclog_pmcattach		pl_t;
217 	struct pmclog_pmcdetach		pl_d;
218 	struct pmclog_proccsw		pl_c;
219 	struct pmclog_procexec		pl_x;
220 	struct pmclog_procexit		pl_e;
221 	struct pmclog_procfork		pl_f;
222 	struct pmclog_sysexit		pl_se;
223 	struct pmclog_userdata		pl_u;
224 };
225 
226 #define	PMCLOG_HEADER_MAGIC					0xEEU
227 
228 #define	PMCLOG_HEADER_TO_LENGTH(H)				\
229 	((H) & 0x0000FFFF)
230 #define	PMCLOG_HEADER_TO_TYPE(H)				\
231 	(((H) & 0x00FF0000) >> 16)
232 #define	PMCLOG_HEADER_TO_MAGIC(H)				\
233 	(((H) & 0xFF000000) >> 24)
234 #define	PMCLOG_HEADER_CHECK_MAGIC(H)				\
235 	(PMCLOG_HEADER_TO_MAGIC(H) == PMCLOG_HEADER_MAGIC)
236 
237 #ifdef	_KERNEL
238 
239 /*
240  * Prototypes
241  */
242 int	pmclog_configure_log(struct pmc_mdep *_md, struct pmc_owner *_po,
243     int _logfd);
244 int	pmclog_deconfigure_log(struct pmc_owner *_po);
245 int	pmclog_flush(struct pmc_owner *_po);
246 void	pmclog_initialize(void);
247 void	pmclog_process_callchain(struct pmc *_pm, struct pmc_sample *_ps);
248 void	pmclog_process_closelog(struct pmc_owner *po);
249 void	pmclog_process_dropnotify(struct pmc_owner *po);
250 void	pmclog_process_map_in(struct pmc_owner *po, pid_t pid,
251     uintfptr_t start, const char *path);
252 void	pmclog_process_map_out(struct pmc_owner *po, pid_t pid,
253     uintfptr_t start, uintfptr_t end);
254 void	pmclog_process_pmcallocate(struct pmc *_pm);
255 void	pmclog_process_pmcattach(struct pmc *_pm, pid_t _pid, char *_path);
256 void	pmclog_process_pmcdetach(struct pmc *_pm, pid_t _pid);
257 void	pmclog_process_proccsw(struct pmc *_pm, struct pmc_process *_pp,
258     pmc_value_t _v);
259 void	pmclog_process_procexec(struct pmc_owner *_po, pmc_id_t _pmid, pid_t _pid,
260     uintfptr_t _startaddr, char *_path);
261 void	pmclog_process_procexit(struct pmc *_pm, struct pmc_process *_pp);
262 void	pmclog_process_procfork(struct pmc_owner *_po, pid_t _oldpid, pid_t _newpid);
263 void	pmclog_process_sysexit(struct pmc_owner *_po, pid_t _pid);
264 int	pmclog_process_userlog(struct pmc_owner *_po,
265     struct pmc_op_writelog *_wl);
266 void	pmclog_shutdown(void);
267 #endif	/* _KERNEL */
268 
269 #endif	/* _SYS_PMCLOG_H_ */
270