pmclog.h revision 174214
1147191Sjkoshy/*-
2174214Sjkoshy * Copyright (c) 2005-2007, Joseph Koshy
3174214Sjkoshy * Copyright (c) 2007 The FreeBSD Foundation
4147191Sjkoshy * All rights reserved.
5147191Sjkoshy *
6174214Sjkoshy * Portions of this software were developed by A. Joseph Koshy under
7174214Sjkoshy * sponsorship from the FreeBSD Foundation and Google, Inc.
8174214Sjkoshy *
9147191Sjkoshy * Redistribution and use in source and binary forms, with or without
10147191Sjkoshy * modification, are permitted provided that the following conditions
11147191Sjkoshy * are met:
12147191Sjkoshy * 1. Redistributions of source code must retain the above copyright
13147191Sjkoshy *    notice, this list of conditions and the following disclaimer.
14147191Sjkoshy * 2. Redistributions in binary form must reproduce the above copyright
15147191Sjkoshy *    notice, this list of conditions and the following disclaimer in the
16147191Sjkoshy *    documentation and/or other materials provided with the distribution.
17147191Sjkoshy *
18147191Sjkoshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19147191Sjkoshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20147191Sjkoshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21147191Sjkoshy * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22147191Sjkoshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23147191Sjkoshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24147191Sjkoshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25147191Sjkoshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26147191Sjkoshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27147191Sjkoshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28147191Sjkoshy * SUCH DAMAGE.
29147191Sjkoshy *
30147191Sjkoshy * $FreeBSD: head/sys/sys/pmclog.h 174214 2007-12-03 11:11:08Z jkoshy $
31147191Sjkoshy */
32147191Sjkoshy
33147191Sjkoshy#ifndef	_SYS_PMCLOG_H_
34147191Sjkoshy#define	_SYS_PMCLOG_H_
35147191Sjkoshy
36147191Sjkoshy#include <sys/pmc.h>
37147191Sjkoshy
38147191Sjkoshyenum pmclog_type {
39157144Sjkoshy	/* V1 ABI */
40147191Sjkoshy	PMCLOG_TYPE_CLOSELOG,
41147191Sjkoshy	PMCLOG_TYPE_DROPNOTIFY,
42147191Sjkoshy	PMCLOG_TYPE_INITIALIZE,
43157144Sjkoshy	PMCLOG_TYPE_MAPPINGCHANGE, /* unused in v1 */
44147191Sjkoshy	PMCLOG_TYPE_PCSAMPLE,
45147191Sjkoshy	PMCLOG_TYPE_PMCALLOCATE,
46147191Sjkoshy	PMCLOG_TYPE_PMCATTACH,
47147191Sjkoshy	PMCLOG_TYPE_PMCDETACH,
48147191Sjkoshy	PMCLOG_TYPE_PROCCSW,
49147191Sjkoshy	PMCLOG_TYPE_PROCEXEC,
50147191Sjkoshy	PMCLOG_TYPE_PROCEXIT,
51147191Sjkoshy	PMCLOG_TYPE_PROCFORK,
52147191Sjkoshy	PMCLOG_TYPE_SYSEXIT,
53157144Sjkoshy	PMCLOG_TYPE_USERDATA,
54157144Sjkoshy	/*
55157144Sjkoshy	 * V2 ABI
56157144Sjkoshy	 *
57157144Sjkoshy	 * The MAP_{IN,OUT} event types obsolete the MAPPING_CHANGE
58174214Sjkoshy	 * event type.  The CALLCHAIN event type obsoletes the
59174214Sjkoshy	 * PCSAMPLE event type.
60157144Sjkoshy	 */
61157144Sjkoshy	PMCLOG_TYPE_MAP_IN,
62174214Sjkoshy	PMCLOG_TYPE_MAP_OUT,
63174214Sjkoshy	PMCLOG_TYPE_CALLCHAIN
64147191Sjkoshy};
65147191Sjkoshy
66147191Sjkoshy/*
67147191Sjkoshy * A log entry descriptor comprises of a 32 bit header and a 64 bit
68147191Sjkoshy * time stamp followed by as many 32 bit words are required to record
69147191Sjkoshy * the event.
70147191Sjkoshy *
71147191Sjkoshy * Header field format:
72147191Sjkoshy *
73147191Sjkoshy *  31           24           16                                   0
74147191Sjkoshy *   +------------+------------+-----------------------------------+
75147191Sjkoshy *   |    MAGIC   |    TYPE    |               LENGTH              |
76147191Sjkoshy *   +------------+------------+-----------------------------------+
77147191Sjkoshy *
78147191Sjkoshy * MAGIC 	is the constant PMCLOG_HEADER_MAGIC.
79147191Sjkoshy * TYPE  	contains a value of type enum pmclog_type.
80147191Sjkoshy * LENGTH	contains the length of the event record, in bytes.
81147191Sjkoshy */
82147191Sjkoshy
83147191Sjkoshy#define	PMCLOG_ENTRY_HEADER				\
84147191Sjkoshy	uint32_t		pl_header;		\
85147191Sjkoshy	uint32_t		pl_ts_sec;		\
86147191Sjkoshy	uint32_t		pl_ts_nsec;
87147191Sjkoshy
88147191Sjkoshy
89147191Sjkoshy/*
90147191Sjkoshy * The following structures are used to describe the size of each kind
91147191Sjkoshy * of log entry to sizeof().  To keep the compiler from adding
92147191Sjkoshy * padding, the fields of each structure are aligned to their natural
93147191Sjkoshy * boundaries, and the structures are marked as 'packed'.
94147191Sjkoshy *
95147191Sjkoshy * The actual reading and writing of the log file is always in terms
96147191Sjkoshy * of 4 byte quantities.
97147191Sjkoshy */
98147191Sjkoshy
99174214Sjkoshystruct pmclog_callchain {
100174214Sjkoshy	PMCLOG_ENTRY_HEADER
101174214Sjkoshy	uint32_t		pl_pid;
102174214Sjkoshy	uint32_t		pl_pmcid;
103174214Sjkoshy	uint32_t		pl_cpuflags;
104174214Sjkoshy	/* 8 byte aligned */
105174214Sjkoshy	uintptr_t		pl_pc[PMC_CALLCHAIN_DEPTH_MAX];
106174214Sjkoshy} __packed;
107174214Sjkoshy
108174214Sjkoshy#define	PMC_CALLCHAIN_CPUFLAGS_TO_CPU(CF)	(((CF) >> 16) & 0xFFFF)
109174214Sjkoshy#define	PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(CF)	((CF) & PMC_CC_F_USERSPACE)
110174214Sjkoshy#define	PMC_CALLCHAIN_TO_CPUFLAGS(CPU,FLAGS)	\
111174214Sjkoshy	(((CPU) << 16) | ((FLAGS) & 0xFFFF))
112174214Sjkoshy
113147191Sjkoshystruct pmclog_closelog {
114147191Sjkoshy	PMCLOG_ENTRY_HEADER
115147191Sjkoshy};
116147191Sjkoshy
117147191Sjkoshystruct pmclog_dropnotify {
118147191Sjkoshy	PMCLOG_ENTRY_HEADER
119147191Sjkoshy};
120147191Sjkoshy
121147191Sjkoshystruct pmclog_initialize {
122147191Sjkoshy	PMCLOG_ENTRY_HEADER
123147191Sjkoshy	uint32_t		pl_version;	/* driver version */
124147191Sjkoshy	uint32_t		pl_cpu;		/* enum pmc_cputype */
125147191Sjkoshy} __packed;
126147191Sjkoshy
127157144Sjkoshystruct pmclog_map_in {
128147191Sjkoshy	PMCLOG_ENTRY_HEADER
129157144Sjkoshy	uint32_t		pl_pid;
130147191Sjkoshy	uintfptr_t		pl_start;	/* 8 byte aligned */
131147191Sjkoshy	char			pl_pathname[PATH_MAX];
132147191Sjkoshy} __packed;
133147191Sjkoshy
134157144Sjkoshystruct pmclog_map_out {
135157144Sjkoshy	PMCLOG_ENTRY_HEADER
136157144Sjkoshy	uint32_t		pl_pid;
137157144Sjkoshy	uintfptr_t		pl_start;	/* 8 byte aligned */
138157144Sjkoshy	uintfptr_t		pl_end;
139157144Sjkoshy} __packed;
140147191Sjkoshy
141147191Sjkoshystruct pmclog_pcsample {
142147191Sjkoshy	PMCLOG_ENTRY_HEADER
143147191Sjkoshy	uint32_t		pl_pid;
144147191Sjkoshy	uintfptr_t		pl_pc;		/* 8 byte aligned */
145147191Sjkoshy	uint32_t		pl_pmcid;
146147708Sjkoshy	uint32_t		pl_usermode;
147147191Sjkoshy} __packed;
148147191Sjkoshy
149147191Sjkoshystruct pmclog_pmcallocate {
150147191Sjkoshy	PMCLOG_ENTRY_HEADER
151147191Sjkoshy	uint32_t		pl_pmcid;
152147191Sjkoshy	uint32_t		pl_event;
153147191Sjkoshy	uint32_t		pl_flags;
154147191Sjkoshy} __packed;
155147191Sjkoshy
156147191Sjkoshystruct pmclog_pmcattach {
157147191Sjkoshy	PMCLOG_ENTRY_HEADER
158147191Sjkoshy	uint32_t		pl_pmcid;
159147191Sjkoshy	uint32_t		pl_pid;
160147191Sjkoshy	char			pl_pathname[PATH_MAX];
161147191Sjkoshy} __packed;
162147191Sjkoshy
163147191Sjkoshystruct pmclog_pmcdetach {
164147191Sjkoshy	PMCLOG_ENTRY_HEADER
165147191Sjkoshy	uint32_t		pl_pmcid;
166147191Sjkoshy	uint32_t		pl_pid;
167147191Sjkoshy} __packed;
168147191Sjkoshy
169147191Sjkoshystruct pmclog_proccsw {
170147191Sjkoshy	PMCLOG_ENTRY_HEADER
171147191Sjkoshy	uint32_t		pl_pmcid;
172147191Sjkoshy	uint64_t		pl_value;	/* keep 8 byte aligned */
173147191Sjkoshy	uint32_t		pl_pid;
174147191Sjkoshy} __packed;
175147191Sjkoshy
176147191Sjkoshystruct pmclog_procexec {
177147191Sjkoshy	PMCLOG_ENTRY_HEADER
178147191Sjkoshy	uint32_t		pl_pid;
179147708Sjkoshy	uintfptr_t		pl_start;	/* keep 8 byte aligned */
180147708Sjkoshy	uint32_t		pl_pmcid;
181147191Sjkoshy	char			pl_pathname[PATH_MAX];
182147191Sjkoshy} __packed;
183147191Sjkoshy
184147191Sjkoshystruct pmclog_procexit {
185147191Sjkoshy	PMCLOG_ENTRY_HEADER
186147191Sjkoshy	uint32_t		pl_pmcid;
187147191Sjkoshy	uint64_t		pl_value;	/* keep 8 byte aligned */
188147191Sjkoshy	uint32_t		pl_pid;
189147191Sjkoshy} __packed;
190147191Sjkoshy
191147191Sjkoshystruct pmclog_procfork {
192147191Sjkoshy	PMCLOG_ENTRY_HEADER
193147191Sjkoshy	uint32_t		pl_oldpid;
194147191Sjkoshy	uint32_t		pl_newpid;
195147191Sjkoshy} __packed;
196147191Sjkoshy
197147191Sjkoshystruct pmclog_sysexit {
198147191Sjkoshy	PMCLOG_ENTRY_HEADER
199147191Sjkoshy	uint32_t		pl_pid;
200147191Sjkoshy} __packed;
201147191Sjkoshy
202147191Sjkoshystruct pmclog_userdata {
203147191Sjkoshy	PMCLOG_ENTRY_HEADER
204147191Sjkoshy	uint32_t		pl_userdata;
205147191Sjkoshy} __packed;
206147191Sjkoshy
207147191Sjkoshyunion pmclog_entry {		/* only used to size scratch areas */
208174214Sjkoshy	struct pmclog_callchain		pl_cc;
209147191Sjkoshy	struct pmclog_closelog		pl_cl;
210147191Sjkoshy	struct pmclog_dropnotify	pl_dn;
211147191Sjkoshy	struct pmclog_initialize	pl_i;
212157144Sjkoshy	struct pmclog_map_in		pl_mi;
213157144Sjkoshy	struct pmclog_map_out		pl_mo;
214147191Sjkoshy	struct pmclog_pcsample		pl_s;
215147191Sjkoshy	struct pmclog_pmcallocate	pl_a;
216147191Sjkoshy	struct pmclog_pmcattach		pl_t;
217147191Sjkoshy	struct pmclog_pmcdetach		pl_d;
218147191Sjkoshy	struct pmclog_proccsw		pl_c;
219147191Sjkoshy	struct pmclog_procexec		pl_x;
220147191Sjkoshy	struct pmclog_procexit		pl_e;
221147191Sjkoshy	struct pmclog_procfork		pl_f;
222147191Sjkoshy	struct pmclog_sysexit		pl_se;
223147191Sjkoshy	struct pmclog_userdata		pl_u;
224147191Sjkoshy};
225147191Sjkoshy
226147191Sjkoshy#define	PMCLOG_HEADER_MAGIC					0xEEU
227147191Sjkoshy
228147191Sjkoshy#define	PMCLOG_HEADER_TO_LENGTH(H)				\
229147191Sjkoshy	((H) & 0x0000FFFF)
230147191Sjkoshy#define	PMCLOG_HEADER_TO_TYPE(H)				\
231147191Sjkoshy	(((H) & 0x00FF0000) >> 16)
232147191Sjkoshy#define	PMCLOG_HEADER_TO_MAGIC(H)				\
233147191Sjkoshy	(((H) & 0xFF000000) >> 24)
234147191Sjkoshy#define	PMCLOG_HEADER_CHECK_MAGIC(H)				\
235147191Sjkoshy	(PMCLOG_HEADER_TO_MAGIC(H) == PMCLOG_HEADER_MAGIC)
236147191Sjkoshy
237147191Sjkoshy#ifdef	_KERNEL
238147191Sjkoshy
239147191Sjkoshy/*
240147191Sjkoshy * Prototypes
241147191Sjkoshy */
242147191Sjkoshyint	pmclog_configure_log(struct pmc_owner *_po, int _logfd);
243147191Sjkoshyint	pmclog_deconfigure_log(struct pmc_owner *_po);
244147191Sjkoshyint	pmclog_flush(struct pmc_owner *_po);
245147191Sjkoshyvoid	pmclog_initialize(void);
246147191Sjkoshyvoid	pmclog_process_closelog(struct pmc_owner *po);
247147191Sjkoshyvoid	pmclog_process_dropnotify(struct pmc_owner *po);
248157144Sjkoshyvoid	pmclog_process_map_in(struct pmc_owner *po, pid_t pid,
249157144Sjkoshy    uintfptr_t start, const char *path);
250157144Sjkoshyvoid	pmclog_process_map_out(struct pmc_owner *po, pid_t pid,
251157144Sjkoshy    uintfptr_t start, uintfptr_t end);
252147191Sjkoshyvoid	pmclog_process_pcsample(struct pmc *_pm, struct pmc_sample *_ps);
253147191Sjkoshyvoid	pmclog_process_pmcallocate(struct pmc *_pm);
254147191Sjkoshyvoid	pmclog_process_pmcattach(struct pmc *_pm, pid_t _pid, char *_path);
255147191Sjkoshyvoid	pmclog_process_pmcdetach(struct pmc *_pm, pid_t _pid);
256147191Sjkoshyvoid	pmclog_process_proccsw(struct pmc *_pm, struct pmc_process *_pp,
257147191Sjkoshy    pmc_value_t _v);
258147708Sjkoshyvoid	pmclog_process_procexec(struct pmc_owner *_po, pmc_id_t _pmid, pid_t _pid,
259147708Sjkoshy    uintfptr_t _startaddr, char *_path);
260147191Sjkoshyvoid	pmclog_process_procexit(struct pmc *_pm, struct pmc_process *_pp);
261147191Sjkoshyvoid	pmclog_process_procfork(struct pmc_owner *_po, pid_t _oldpid, pid_t _newpid);
262147191Sjkoshyvoid	pmclog_process_sysexit(struct pmc_owner *_po, pid_t _pid);
263147191Sjkoshyint	pmclog_process_userlog(struct pmc_owner *_po,
264147191Sjkoshy    struct pmc_op_writelog *_wl);
265147191Sjkoshyvoid	pmclog_shutdown(void);
266147191Sjkoshy#endif	/* _KERNEL */
267147191Sjkoshy
268147191Sjkoshy#endif	/* _SYS_PMCLOG_H_ */
269