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