1299781Sjmcneill/*-
2299781Sjmcneill * Copyright (c) 2005-2007, Joseph Koshy
3299781Sjmcneill * Copyright (c) 2007 The FreeBSD Foundation
4299781Sjmcneill * All rights reserved.
5299781Sjmcneill *
6299781Sjmcneill * Portions of this software were developed by A. Joseph Koshy under
7299781Sjmcneill * sponsorship from the FreeBSD Foundation and Google, Inc.
8299781Sjmcneill *
9299781Sjmcneill * Redistribution and use in source and binary forms, with or without
10299781Sjmcneill * modification, are permitted provided that the following conditions
11299781Sjmcneill * are met:
12299781Sjmcneill * 1. Redistributions of source code must retain the above copyright
13299781Sjmcneill *    notice, this list of conditions and the following disclaimer.
14299781Sjmcneill * 2. Redistributions in binary form must reproduce the above copyright
15299781Sjmcneill *    notice, this list of conditions and the following disclaimer in the
16299781Sjmcneill *    documentation and/or other materials provided with the distribution.
17299781Sjmcneill *
18299781Sjmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19299781Sjmcneill * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20299781Sjmcneill * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21299781Sjmcneill * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22299781Sjmcneill * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23299781Sjmcneill * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24299781Sjmcneill * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25299781Sjmcneill * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26299781Sjmcneill * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27299781Sjmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28299781Sjmcneill * SUCH DAMAGE.
29299781Sjmcneill *
30299781Sjmcneill * $FreeBSD$
31299781Sjmcneill */
32299781Sjmcneill
33299781Sjmcneill#ifndef	_SYS_PMCLOG_H_
34299781Sjmcneill#define	_SYS_PMCLOG_H_
35299781Sjmcneill
36299781Sjmcneill#include <sys/pmc.h>
37299781Sjmcneill
38299781Sjmcneillenum pmclog_type {
39299781Sjmcneill	/* V1 ABI */
40299781Sjmcneill	PMCLOG_TYPE_CLOSELOG,
41299781Sjmcneill	PMCLOG_TYPE_DROPNOTIFY,
42299781Sjmcneill	PMCLOG_TYPE_INITIALIZE,
43299781Sjmcneill	PMCLOG_TYPE_MAPPINGCHANGE, /* unused in v1 */
44299781Sjmcneill	PMCLOG_TYPE_PCSAMPLE,
45299781Sjmcneill	PMCLOG_TYPE_PMCALLOCATE,
46299781Sjmcneill	PMCLOG_TYPE_PMCATTACH,
47299781Sjmcneill	PMCLOG_TYPE_PMCDETACH,
48299781Sjmcneill	PMCLOG_TYPE_PROCCSW,
49299781Sjmcneill	PMCLOG_TYPE_PROCEXEC,
50299781Sjmcneill	PMCLOG_TYPE_PROCEXIT,
51299781Sjmcneill	PMCLOG_TYPE_PROCFORK,
52299781Sjmcneill	PMCLOG_TYPE_SYSEXIT,
53299781Sjmcneill	PMCLOG_TYPE_USERDATA,
54299781Sjmcneill	/*
55299781Sjmcneill	 * V2 ABI
56299781Sjmcneill	 *
57299781Sjmcneill	 * The MAP_{IN,OUT} event types obsolete the MAPPING_CHANGE
58299781Sjmcneill	 * event type.  The CALLCHAIN event type obsoletes the
59299781Sjmcneill	 * PCSAMPLE event type.
60299781Sjmcneill	 */
61299781Sjmcneill	PMCLOG_TYPE_MAP_IN,
62299781Sjmcneill	PMCLOG_TYPE_MAP_OUT,
63299781Sjmcneill	PMCLOG_TYPE_CALLCHAIN,
64299781Sjmcneill	/*
65299781Sjmcneill	 * V3 ABI
66299781Sjmcneill	 *
67299781Sjmcneill	 * New variant of PMCLOG_TYPE_PMCALLOCATE for dynamic event.
68299781Sjmcneill	 */
69299781Sjmcneill	PMCLOG_TYPE_PMCALLOCATEDYN
70299781Sjmcneill};
71299781Sjmcneill
72299781Sjmcneill/*
73299781Sjmcneill * A log entry descriptor comprises of a 32 bit header and a 64 bit
74299781Sjmcneill * time stamp followed by as many 32 bit words are required to record
75299781Sjmcneill * the event.
76299781Sjmcneill *
77299781Sjmcneill * Header field format:
78299781Sjmcneill *
79299781Sjmcneill *  31           24           16                                   0
80299781Sjmcneill *   +------------+------------+-----------------------------------+
81299781Sjmcneill *   |    MAGIC   |    TYPE    |               LENGTH              |
82299781Sjmcneill *   +------------+------------+-----------------------------------+
83299781Sjmcneill *
84299781Sjmcneill * MAGIC 	is the constant PMCLOG_HEADER_MAGIC.
85299781Sjmcneill * TYPE  	contains a value of type enum pmclog_type.
86299781Sjmcneill * LENGTH	contains the length of the event record, in bytes.
87299781Sjmcneill */
88299781Sjmcneill
89299781Sjmcneill#define	PMCLOG_ENTRY_HEADER				\
90299781Sjmcneill	uint32_t		pl_header;		\
91299781Sjmcneill	uint32_t		pl_ts_sec;		\
92299781Sjmcneill	uint32_t		pl_ts_nsec;
93299781Sjmcneill
94299781Sjmcneill
95299781Sjmcneill/*
96299781Sjmcneill * The following structures are used to describe the size of each kind
97299781Sjmcneill * of log entry to sizeof().  To keep the compiler from adding
98299781Sjmcneill * padding, the fields of each structure are aligned to their natural
99299781Sjmcneill * boundaries, and the structures are marked as 'packed'.
100299781Sjmcneill *
101299781Sjmcneill * The actual reading and writing of the log file is always in terms
102299781Sjmcneill * of 4 byte quantities.
103299781Sjmcneill */
104299781Sjmcneill
105299781Sjmcneillstruct pmclog_callchain {
106299781Sjmcneill	PMCLOG_ENTRY_HEADER
107299781Sjmcneill	uint32_t		pl_pid;
108299781Sjmcneill	uint32_t		pl_pmcid;
109299781Sjmcneill	uint32_t		pl_cpuflags;
110299781Sjmcneill	/* 8 byte aligned */
111299781Sjmcneill	uintptr_t		pl_pc[PMC_CALLCHAIN_DEPTH_MAX];
112299781Sjmcneill} __packed;
113299781Sjmcneill
114299781Sjmcneill#define	PMC_CALLCHAIN_CPUFLAGS_TO_CPU(CF)	(((CF) >> 16) & 0xFFFF)
115299781Sjmcneill#define	PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(CF)	((CF) & PMC_CC_F_USERSPACE)
116299781Sjmcneill#define	PMC_CALLCHAIN_TO_CPUFLAGS(CPU,FLAGS)	\
117299781Sjmcneill	(((CPU) << 16) | ((FLAGS) & 0xFFFF))
118299781Sjmcneill
119299781Sjmcneillstruct pmclog_closelog {
120299781Sjmcneill	PMCLOG_ENTRY_HEADER
121299781Sjmcneill};
122299781Sjmcneill
123299781Sjmcneillstruct pmclog_dropnotify {
124299781Sjmcneill	PMCLOG_ENTRY_HEADER
125299781Sjmcneill};
126299862Sjmcneill
127299781Sjmcneillstruct pmclog_initialize {
128299781Sjmcneill	PMCLOG_ENTRY_HEADER
129299781Sjmcneill	uint32_t		pl_version;	/* driver version */
130299781Sjmcneill	uint32_t		pl_cpu;		/* enum pmc_cputype */
131299781Sjmcneill} __packed;
132299781Sjmcneill
133299781Sjmcneillstruct pmclog_map_in {
134299781Sjmcneill	PMCLOG_ENTRY_HEADER
135299781Sjmcneill	uint32_t		pl_pid;
136299781Sjmcneill	uintfptr_t		pl_start;	/* 8 byte aligned */
137299781Sjmcneill	char			pl_pathname[PATH_MAX];
138299781Sjmcneill} __packed;
139299781Sjmcneill
140299781Sjmcneillstruct pmclog_map_out {
141299862Sjmcneill	PMCLOG_ENTRY_HEADER
142299862Sjmcneill	uint32_t		pl_pid;
143299781Sjmcneill	uintfptr_t		pl_start;	/* 8 byte aligned */
144299781Sjmcneill	uintfptr_t		pl_end;
145299781Sjmcneill} __packed;
146299781Sjmcneill
147299781Sjmcneillstruct pmclog_pcsample {
148299781Sjmcneill	PMCLOG_ENTRY_HEADER
149299781Sjmcneill	uint32_t		pl_pid;
150299781Sjmcneill	uintfptr_t		pl_pc;		/* 8 byte aligned */
151299781Sjmcneill	uint32_t		pl_pmcid;
152299781Sjmcneill	uint32_t		pl_usermode;
153299781Sjmcneill} __packed;
154299781Sjmcneill
155299781Sjmcneillstruct pmclog_pmcallocate {
156299781Sjmcneill	PMCLOG_ENTRY_HEADER
157299781Sjmcneill	uint32_t		pl_pmcid;
158299781Sjmcneill	uint32_t		pl_event;
159299781Sjmcneill	uint32_t		pl_flags;
160299781Sjmcneill} __packed;
161299781Sjmcneill
162299781Sjmcneillstruct pmclog_pmcattach {
163299781Sjmcneill	PMCLOG_ENTRY_HEADER
164299781Sjmcneill	uint32_t		pl_pmcid;
165299781Sjmcneill	uint32_t		pl_pid;
166299781Sjmcneill	char			pl_pathname[PATH_MAX];
167299781Sjmcneill} __packed;
168299781Sjmcneill
169299781Sjmcneillstruct pmclog_pmcdetach {
170299781Sjmcneill	PMCLOG_ENTRY_HEADER
171299781Sjmcneill	uint32_t		pl_pmcid;
172299781Sjmcneill	uint32_t		pl_pid;
173299781Sjmcneill} __packed;
174299781Sjmcneill
175299781Sjmcneillstruct pmclog_proccsw {
176299781Sjmcneill	PMCLOG_ENTRY_HEADER
177299781Sjmcneill	uint32_t		pl_pmcid;
178299781Sjmcneill	uint64_t		pl_value;	/* keep 8 byte aligned */
179299781Sjmcneill	uint32_t		pl_pid;
180299781Sjmcneill} __packed;
181299781Sjmcneill
182299781Sjmcneillstruct pmclog_procexec {
183299781Sjmcneill	PMCLOG_ENTRY_HEADER
184299781Sjmcneill	uint32_t		pl_pid;
185299781Sjmcneill	uintfptr_t		pl_start;	/* keep 8 byte aligned */
186299781Sjmcneill	uint32_t		pl_pmcid;
187299781Sjmcneill	char			pl_pathname[PATH_MAX];
188299781Sjmcneill} __packed;
189299781Sjmcneill
190299781Sjmcneillstruct pmclog_procexit {
191299781Sjmcneill	PMCLOG_ENTRY_HEADER
192299781Sjmcneill	uint32_t		pl_pmcid;
193299781Sjmcneill	uint64_t		pl_value;	/* keep 8 byte aligned */
194299781Sjmcneill	uint32_t		pl_pid;
195299781Sjmcneill} __packed;
196299781Sjmcneill
197299781Sjmcneillstruct pmclog_procfork {
198299781Sjmcneill	PMCLOG_ENTRY_HEADER
199299781Sjmcneill	uint32_t		pl_oldpid;
200299781Sjmcneill	uint32_t		pl_newpid;
201299781Sjmcneill} __packed;
202299862Sjmcneill
203299781Sjmcneillstruct pmclog_sysexit {
204299781Sjmcneill	PMCLOG_ENTRY_HEADER
205299781Sjmcneill	uint32_t		pl_pid;
206299781Sjmcneill} __packed;
207299781Sjmcneill
208299781Sjmcneillstruct pmclog_userdata {
209299781Sjmcneill	PMCLOG_ENTRY_HEADER
210299781Sjmcneill	uint32_t		pl_userdata;
211299781Sjmcneill} __packed;
212299862Sjmcneill
213299862Sjmcneillstruct pmclog_pmcallocatedyn {
214299862Sjmcneill	PMCLOG_ENTRY_HEADER
215299862Sjmcneill	uint32_t		pl_pmcid;
216299862Sjmcneill	uint32_t		pl_event;
217299862Sjmcneill	uint32_t		pl_flags;
218299781Sjmcneill	char			pl_evname[PMC_NAME_MAX];
219299862Sjmcneill} __packed;
220299781Sjmcneill
221299781Sjmcneillunion pmclog_entry {		/* only used to size scratch areas */
222299781Sjmcneill	struct pmclog_callchain		pl_cc;
223299781Sjmcneill	struct pmclog_closelog		pl_cl;
224299781Sjmcneill	struct pmclog_dropnotify	pl_dn;
225299781Sjmcneill	struct pmclog_initialize	pl_i;
226299781Sjmcneill	struct pmclog_map_in		pl_mi;
227299781Sjmcneill	struct pmclog_map_out		pl_mo;
228299781Sjmcneill	struct pmclog_pcsample		pl_s;
229299781Sjmcneill	struct pmclog_pmcallocate	pl_a;
230299781Sjmcneill	struct pmclog_pmcallocatedyn	pl_ad;
231299781Sjmcneill	struct pmclog_pmcattach		pl_t;
232299781Sjmcneill	struct pmclog_pmcdetach		pl_d;
233299781Sjmcneill	struct pmclog_proccsw		pl_c;
234299781Sjmcneill	struct pmclog_procexec		pl_x;
235299781Sjmcneill	struct pmclog_procexit		pl_e;
236299781Sjmcneill	struct pmclog_procfork		pl_f;
237299781Sjmcneill	struct pmclog_sysexit		pl_se;
238299781Sjmcneill	struct pmclog_userdata		pl_u;
239299781Sjmcneill};
240299781Sjmcneill
241299781Sjmcneill#define	PMCLOG_HEADER_MAGIC					0xEEU
242299781Sjmcneill
243299781Sjmcneill#define	PMCLOG_HEADER_TO_LENGTH(H)				\
244299781Sjmcneill	((H) & 0x0000FFFF)
245299781Sjmcneill#define	PMCLOG_HEADER_TO_TYPE(H)				\
246299781Sjmcneill	(((H) & 0x00FF0000) >> 16)
247299781Sjmcneill#define	PMCLOG_HEADER_TO_MAGIC(H)				\
248299781Sjmcneill	(((H) & 0xFF000000) >> 24)
249299781Sjmcneill#define	PMCLOG_HEADER_CHECK_MAGIC(H)				\
250299781Sjmcneill	(PMCLOG_HEADER_TO_MAGIC(H) == PMCLOG_HEADER_MAGIC)
251299781Sjmcneill
252299781Sjmcneill#ifdef	_KERNEL
253299781Sjmcneill
254299781Sjmcneill/*
255299781Sjmcneill * Prototypes
256299781Sjmcneill */
257299781Sjmcneillint	pmclog_configure_log(struct pmc_mdep *_md, struct pmc_owner *_po,
258299781Sjmcneill    int _logfd);
259299781Sjmcneillint	pmclog_deconfigure_log(struct pmc_owner *_po);
260299781Sjmcneillint	pmclog_flush(struct pmc_owner *_po);
261299781Sjmcneillint	pmclog_close(struct pmc_owner *_po);
262299781Sjmcneillvoid	pmclog_initialize(void);
263299781Sjmcneillvoid	pmclog_process_callchain(struct pmc *_pm, struct pmc_sample *_ps);
264299781Sjmcneillvoid	pmclog_process_closelog(struct pmc_owner *po);
265299781Sjmcneillvoid	pmclog_process_dropnotify(struct pmc_owner *po);
266299781Sjmcneillvoid	pmclog_process_map_in(struct pmc_owner *po, pid_t pid,
267299781Sjmcneill    uintfptr_t start, const char *path);
268299781Sjmcneillvoid	pmclog_process_map_out(struct pmc_owner *po, pid_t pid,
269299781Sjmcneill    uintfptr_t start, uintfptr_t end);
270299781Sjmcneillvoid	pmclog_process_pmcallocate(struct pmc *_pm);
271299781Sjmcneillvoid	pmclog_process_pmcattach(struct pmc *_pm, pid_t _pid, char *_path);
272299781Sjmcneillvoid	pmclog_process_pmcdetach(struct pmc *_pm, pid_t _pid);
273299781Sjmcneillvoid	pmclog_process_proccsw(struct pmc *_pm, struct pmc_process *_pp,
274299781Sjmcneill    pmc_value_t _v);
275299781Sjmcneillvoid	pmclog_process_procexec(struct pmc_owner *_po, pmc_id_t _pmid, pid_t _pid,
276299781Sjmcneill    uintfptr_t _startaddr, char *_path);
277299781Sjmcneillvoid	pmclog_process_procexit(struct pmc *_pm, struct pmc_process *_pp);
278299781Sjmcneillvoid	pmclog_process_procfork(struct pmc_owner *_po, pid_t _oldpid, pid_t _newpid);
279299781Sjmcneillvoid	pmclog_process_sysexit(struct pmc_owner *_po, pid_t _pid);
280299781Sjmcneillint	pmclog_process_userlog(struct pmc_owner *_po,
281299781Sjmcneill    struct pmc_op_writelog *_wl);
282299781Sjmcneillvoid	pmclog_shutdown(void);
283299781Sjmcneill#endif	/* _KERNEL */
284299781Sjmcneill
285299781Sjmcneill#endif	/* _SYS_PMCLOG_H_ */
286299781Sjmcneill