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: stable/11/sys/sys/pmclog.h 325551 2017-11-08 12:13:25Z kib $
31 */
32
33#ifndef	_SYS_PMCLOG_H_
34#define	_SYS_PMCLOG_H_
35
36#include <sys/pmc.h>
37
38enum 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	 * V3 ABI
66	 *
67	 * New variant of PMCLOG_TYPE_PMCALLOCATE for dynamic event.
68	 */
69	PMCLOG_TYPE_PMCALLOCATEDYN
70};
71
72/*
73 * A log entry descriptor comprises of a 32 bit header and a 64 bit
74 * time stamp followed by as many 32 bit words are required to record
75 * the event.
76 *
77 * Header field format:
78 *
79 *  31           24           16                                   0
80 *   +------------+------------+-----------------------------------+
81 *   |    MAGIC   |    TYPE    |               LENGTH              |
82 *   +------------+------------+-----------------------------------+
83 *
84 * MAGIC 	is the constant PMCLOG_HEADER_MAGIC.
85 * TYPE  	contains a value of type enum pmclog_type.
86 * LENGTH	contains the length of the event record, in bytes.
87 */
88
89#define	PMCLOG_ENTRY_HEADER				\
90	uint32_t		pl_header;		\
91	uint32_t		pl_ts_sec;		\
92	uint32_t		pl_ts_nsec;
93
94
95/*
96 * The following structures are used to describe the size of each kind
97 * of log entry to sizeof().  To keep the compiler from adding
98 * padding, the fields of each structure are aligned to their natural
99 * boundaries, and the structures are marked as 'packed'.
100 *
101 * The actual reading and writing of the log file is always in terms
102 * of 4 byte quantities.
103 */
104
105struct pmclog_callchain {
106	PMCLOG_ENTRY_HEADER
107	uint32_t		pl_pid;
108	uint32_t		pl_pmcid;
109	uint32_t		pl_cpuflags;
110	/* 8 byte aligned */
111	uintptr_t		pl_pc[PMC_CALLCHAIN_DEPTH_MAX];
112} __packed;
113
114#define	PMC_CALLCHAIN_CPUFLAGS_TO_CPU(CF)	(((CF) >> 16) & 0xFFFF)
115#define	PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(CF)	((CF) & PMC_CC_F_USERSPACE)
116#define	PMC_CALLCHAIN_TO_CPUFLAGS(CPU,FLAGS)	\
117	(((CPU) << 16) | ((FLAGS) & 0xFFFF))
118
119struct pmclog_closelog {
120	PMCLOG_ENTRY_HEADER
121};
122
123struct pmclog_dropnotify {
124	PMCLOG_ENTRY_HEADER
125};
126
127struct pmclog_initialize {
128	PMCLOG_ENTRY_HEADER
129	uint32_t		pl_version;	/* driver version */
130	uint32_t		pl_cpu;		/* enum pmc_cputype */
131} __packed;
132
133struct pmclog_map_in {
134	PMCLOG_ENTRY_HEADER
135	uint32_t		pl_pid;
136	uintfptr_t		pl_start;	/* 8 byte aligned */
137	char			pl_pathname[PATH_MAX];
138} __packed;
139
140struct pmclog_map_out {
141	PMCLOG_ENTRY_HEADER
142	uint32_t		pl_pid;
143	uintfptr_t		pl_start;	/* 8 byte aligned */
144	uintfptr_t		pl_end;
145} __packed;
146
147struct pmclog_pcsample {
148	PMCLOG_ENTRY_HEADER
149	uint32_t		pl_pid;
150	uintfptr_t		pl_pc;		/* 8 byte aligned */
151	uint32_t		pl_pmcid;
152	uint32_t		pl_usermode;
153} __packed;
154
155struct pmclog_pmcallocate {
156	PMCLOG_ENTRY_HEADER
157	uint32_t		pl_pmcid;
158	uint32_t		pl_event;
159	uint32_t		pl_flags;
160} __packed;
161
162struct pmclog_pmcattach {
163	PMCLOG_ENTRY_HEADER
164	uint32_t		pl_pmcid;
165	uint32_t		pl_pid;
166	char			pl_pathname[PATH_MAX];
167} __packed;
168
169struct pmclog_pmcdetach {
170	PMCLOG_ENTRY_HEADER
171	uint32_t		pl_pmcid;
172	uint32_t		pl_pid;
173} __packed;
174
175struct pmclog_proccsw {
176	PMCLOG_ENTRY_HEADER
177	uint32_t		pl_pmcid;
178	uint64_t		pl_value;	/* keep 8 byte aligned */
179	uint32_t		pl_pid;
180} __packed;
181
182struct pmclog_procexec {
183	PMCLOG_ENTRY_HEADER
184	uint32_t		pl_pid;
185	uintfptr_t		pl_start;	/* keep 8 byte aligned */
186	uint32_t		pl_pmcid;
187	char			pl_pathname[PATH_MAX];
188} __packed;
189
190struct pmclog_procexit {
191	PMCLOG_ENTRY_HEADER
192	uint32_t		pl_pmcid;
193	uint64_t		pl_value;	/* keep 8 byte aligned */
194	uint32_t		pl_pid;
195} __packed;
196
197struct pmclog_procfork {
198	PMCLOG_ENTRY_HEADER
199	uint32_t		pl_oldpid;
200	uint32_t		pl_newpid;
201} __packed;
202
203struct pmclog_sysexit {
204	PMCLOG_ENTRY_HEADER
205	uint32_t		pl_pid;
206} __packed;
207
208struct pmclog_userdata {
209	PMCLOG_ENTRY_HEADER
210	uint32_t		pl_userdata;
211} __packed;
212
213struct pmclog_pmcallocatedyn {
214	PMCLOG_ENTRY_HEADER
215	uint32_t		pl_pmcid;
216	uint32_t		pl_event;
217	uint32_t		pl_flags;
218	char			pl_evname[PMC_NAME_MAX];
219} __packed;
220
221union pmclog_entry {		/* only used to size scratch areas */
222	struct pmclog_callchain		pl_cc;
223	struct pmclog_closelog		pl_cl;
224	struct pmclog_dropnotify	pl_dn;
225	struct pmclog_initialize	pl_i;
226	struct pmclog_map_in		pl_mi;
227	struct pmclog_map_out		pl_mo;
228	struct pmclog_pcsample		pl_s;
229	struct pmclog_pmcallocate	pl_a;
230	struct pmclog_pmcallocatedyn	pl_ad;
231	struct pmclog_pmcattach		pl_t;
232	struct pmclog_pmcdetach		pl_d;
233	struct pmclog_proccsw		pl_c;
234	struct pmclog_procexec		pl_x;
235	struct pmclog_procexit		pl_e;
236	struct pmclog_procfork		pl_f;
237	struct pmclog_sysexit		pl_se;
238	struct pmclog_userdata		pl_u;
239};
240
241#define	PMCLOG_HEADER_MAGIC					0xEEU
242
243#define	PMCLOG_HEADER_TO_LENGTH(H)				\
244	((H) & 0x0000FFFF)
245#define	PMCLOG_HEADER_TO_TYPE(H)				\
246	(((H) & 0x00FF0000) >> 16)
247#define	PMCLOG_HEADER_TO_MAGIC(H)				\
248	(((H) & 0xFF000000) >> 24)
249#define	PMCLOG_HEADER_CHECK_MAGIC(H)				\
250	(PMCLOG_HEADER_TO_MAGIC(H) == PMCLOG_HEADER_MAGIC)
251
252#ifdef	_KERNEL
253
254/*
255 * Prototypes
256 */
257int	pmclog_configure_log(struct pmc_mdep *_md, struct pmc_owner *_po,
258    int _logfd);
259int	pmclog_deconfigure_log(struct pmc_owner *_po);
260int	pmclog_flush(struct pmc_owner *_po);
261int	pmclog_close(struct pmc_owner *_po);
262void	pmclog_initialize(void);
263int	pmclog_proc_create(struct thread *td, void **handlep);
264void	pmclog_proc_ignite(void *handle, struct pmc_owner *po);
265void	pmclog_process_callchain(struct pmc *_pm, struct pmc_sample *_ps);
266void	pmclog_process_closelog(struct pmc_owner *po);
267void	pmclog_process_dropnotify(struct pmc_owner *po);
268void	pmclog_process_map_in(struct pmc_owner *po, pid_t pid,
269    uintfptr_t start, const char *path);
270void	pmclog_process_map_out(struct pmc_owner *po, pid_t pid,
271    uintfptr_t start, uintfptr_t end);
272void	pmclog_process_pmcallocate(struct pmc *_pm);
273void	pmclog_process_pmcattach(struct pmc *_pm, pid_t _pid, char *_path);
274void	pmclog_process_pmcdetach(struct pmc *_pm, pid_t _pid);
275void	pmclog_process_proccsw(struct pmc *_pm, struct pmc_process *_pp,
276    pmc_value_t _v);
277void	pmclog_process_procexec(struct pmc_owner *_po, pmc_id_t _pmid, pid_t _pid,
278    uintfptr_t _startaddr, char *_path);
279void	pmclog_process_procexit(struct pmc *_pm, struct pmc_process *_pp);
280void	pmclog_process_procfork(struct pmc_owner *_po, pid_t _oldpid, pid_t _newpid);
281void	pmclog_process_sysexit(struct pmc_owner *_po, pid_t _pid);
282int	pmclog_process_userlog(struct pmc_owner *_po,
283    struct pmc_op_writelog *_wl);
284void	pmclog_shutdown(void);
285#endif	/* _KERNEL */
286
287#endif	/* _SYS_PMCLOG_H_ */
288