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$
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,
63233628Sfabient	PMCLOG_TYPE_CALLCHAIN,
64233628Sfabient	/*
65233628Sfabient	 * V3 ABI
66233628Sfabient	 *
67233628Sfabient	 * New variant of PMCLOG_TYPE_PMCALLOCATE for dynamic event.
68233628Sfabient	 */
69233628Sfabient	PMCLOG_TYPE_PMCALLOCATEDYN
70147191Sjkoshy};
71147191Sjkoshy
72147191Sjkoshy/*
73147191Sjkoshy * A log entry descriptor comprises of a 32 bit header and a 64 bit
74147191Sjkoshy * time stamp followed by as many 32 bit words are required to record
75147191Sjkoshy * the event.
76147191Sjkoshy *
77147191Sjkoshy * Header field format:
78147191Sjkoshy *
79147191Sjkoshy *  31           24           16                                   0
80147191Sjkoshy *   +------------+------------+-----------------------------------+
81147191Sjkoshy *   |    MAGIC   |    TYPE    |               LENGTH              |
82147191Sjkoshy *   +------------+------------+-----------------------------------+
83147191Sjkoshy *
84147191Sjkoshy * MAGIC 	is the constant PMCLOG_HEADER_MAGIC.
85147191Sjkoshy * TYPE  	contains a value of type enum pmclog_type.
86147191Sjkoshy * LENGTH	contains the length of the event record, in bytes.
87147191Sjkoshy */
88147191Sjkoshy
89147191Sjkoshy#define	PMCLOG_ENTRY_HEADER				\
90147191Sjkoshy	uint32_t		pl_header;		\
91147191Sjkoshy	uint32_t		pl_ts_sec;		\
92147191Sjkoshy	uint32_t		pl_ts_nsec;
93147191Sjkoshy
94147191Sjkoshy
95147191Sjkoshy/*
96147191Sjkoshy * The following structures are used to describe the size of each kind
97147191Sjkoshy * of log entry to sizeof().  To keep the compiler from adding
98147191Sjkoshy * padding, the fields of each structure are aligned to their natural
99147191Sjkoshy * boundaries, and the structures are marked as 'packed'.
100147191Sjkoshy *
101147191Sjkoshy * The actual reading and writing of the log file is always in terms
102147191Sjkoshy * of 4 byte quantities.
103147191Sjkoshy */
104147191Sjkoshy
105174214Sjkoshystruct pmclog_callchain {
106174214Sjkoshy	PMCLOG_ENTRY_HEADER
107174214Sjkoshy	uint32_t		pl_pid;
108174214Sjkoshy	uint32_t		pl_pmcid;
109174214Sjkoshy	uint32_t		pl_cpuflags;
110174214Sjkoshy	/* 8 byte aligned */
111174214Sjkoshy	uintptr_t		pl_pc[PMC_CALLCHAIN_DEPTH_MAX];
112174214Sjkoshy} __packed;
113174214Sjkoshy
114174214Sjkoshy#define	PMC_CALLCHAIN_CPUFLAGS_TO_CPU(CF)	(((CF) >> 16) & 0xFFFF)
115174214Sjkoshy#define	PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(CF)	((CF) & PMC_CC_F_USERSPACE)
116174214Sjkoshy#define	PMC_CALLCHAIN_TO_CPUFLAGS(CPU,FLAGS)	\
117174214Sjkoshy	(((CPU) << 16) | ((FLAGS) & 0xFFFF))
118174214Sjkoshy
119147191Sjkoshystruct pmclog_closelog {
120147191Sjkoshy	PMCLOG_ENTRY_HEADER
121147191Sjkoshy};
122147191Sjkoshy
123147191Sjkoshystruct pmclog_dropnotify {
124147191Sjkoshy	PMCLOG_ENTRY_HEADER
125147191Sjkoshy};
126147191Sjkoshy
127147191Sjkoshystruct pmclog_initialize {
128147191Sjkoshy	PMCLOG_ENTRY_HEADER
129147191Sjkoshy	uint32_t		pl_version;	/* driver version */
130147191Sjkoshy	uint32_t		pl_cpu;		/* enum pmc_cputype */
131147191Sjkoshy} __packed;
132147191Sjkoshy
133157144Sjkoshystruct pmclog_map_in {
134147191Sjkoshy	PMCLOG_ENTRY_HEADER
135157144Sjkoshy	uint32_t		pl_pid;
136147191Sjkoshy	uintfptr_t		pl_start;	/* 8 byte aligned */
137147191Sjkoshy	char			pl_pathname[PATH_MAX];
138147191Sjkoshy} __packed;
139147191Sjkoshy
140157144Sjkoshystruct pmclog_map_out {
141157144Sjkoshy	PMCLOG_ENTRY_HEADER
142157144Sjkoshy	uint32_t		pl_pid;
143157144Sjkoshy	uintfptr_t		pl_start;	/* 8 byte aligned */
144157144Sjkoshy	uintfptr_t		pl_end;
145157144Sjkoshy} __packed;
146147191Sjkoshy
147147191Sjkoshystruct pmclog_pcsample {
148147191Sjkoshy	PMCLOG_ENTRY_HEADER
149147191Sjkoshy	uint32_t		pl_pid;
150147191Sjkoshy	uintfptr_t		pl_pc;		/* 8 byte aligned */
151147191Sjkoshy	uint32_t		pl_pmcid;
152147708Sjkoshy	uint32_t		pl_usermode;
153147191Sjkoshy} __packed;
154147191Sjkoshy
155147191Sjkoshystruct pmclog_pmcallocate {
156147191Sjkoshy	PMCLOG_ENTRY_HEADER
157147191Sjkoshy	uint32_t		pl_pmcid;
158147191Sjkoshy	uint32_t		pl_event;
159147191Sjkoshy	uint32_t		pl_flags;
160147191Sjkoshy} __packed;
161147191Sjkoshy
162147191Sjkoshystruct pmclog_pmcattach {
163147191Sjkoshy	PMCLOG_ENTRY_HEADER
164147191Sjkoshy	uint32_t		pl_pmcid;
165147191Sjkoshy	uint32_t		pl_pid;
166147191Sjkoshy	char			pl_pathname[PATH_MAX];
167147191Sjkoshy} __packed;
168147191Sjkoshy
169147191Sjkoshystruct pmclog_pmcdetach {
170147191Sjkoshy	PMCLOG_ENTRY_HEADER
171147191Sjkoshy	uint32_t		pl_pmcid;
172147191Sjkoshy	uint32_t		pl_pid;
173147191Sjkoshy} __packed;
174147191Sjkoshy
175147191Sjkoshystruct pmclog_proccsw {
176147191Sjkoshy	PMCLOG_ENTRY_HEADER
177147191Sjkoshy	uint32_t		pl_pmcid;
178147191Sjkoshy	uint64_t		pl_value;	/* keep 8 byte aligned */
179147191Sjkoshy	uint32_t		pl_pid;
180147191Sjkoshy} __packed;
181147191Sjkoshy
182147191Sjkoshystruct pmclog_procexec {
183147191Sjkoshy	PMCLOG_ENTRY_HEADER
184147191Sjkoshy	uint32_t		pl_pid;
185147708Sjkoshy	uintfptr_t		pl_start;	/* keep 8 byte aligned */
186147708Sjkoshy	uint32_t		pl_pmcid;
187147191Sjkoshy	char			pl_pathname[PATH_MAX];
188147191Sjkoshy} __packed;
189147191Sjkoshy
190147191Sjkoshystruct pmclog_procexit {
191147191Sjkoshy	PMCLOG_ENTRY_HEADER
192147191Sjkoshy	uint32_t		pl_pmcid;
193147191Sjkoshy	uint64_t		pl_value;	/* keep 8 byte aligned */
194147191Sjkoshy	uint32_t		pl_pid;
195147191Sjkoshy} __packed;
196147191Sjkoshy
197147191Sjkoshystruct pmclog_procfork {
198147191Sjkoshy	PMCLOG_ENTRY_HEADER
199147191Sjkoshy	uint32_t		pl_oldpid;
200147191Sjkoshy	uint32_t		pl_newpid;
201147191Sjkoshy} __packed;
202147191Sjkoshy
203147191Sjkoshystruct pmclog_sysexit {
204147191Sjkoshy	PMCLOG_ENTRY_HEADER
205147191Sjkoshy	uint32_t		pl_pid;
206147191Sjkoshy} __packed;
207147191Sjkoshy
208147191Sjkoshystruct pmclog_userdata {
209147191Sjkoshy	PMCLOG_ENTRY_HEADER
210147191Sjkoshy	uint32_t		pl_userdata;
211147191Sjkoshy} __packed;
212147191Sjkoshy
213233628Sfabientstruct pmclog_pmcallocatedyn {
214233628Sfabient	PMCLOG_ENTRY_HEADER
215233628Sfabient	uint32_t		pl_pmcid;
216233628Sfabient	uint32_t		pl_event;
217233628Sfabient	uint32_t		pl_flags;
218233628Sfabient	char			pl_evname[PMC_NAME_MAX];
219233628Sfabient} __packed;
220233628Sfabient
221147191Sjkoshyunion pmclog_entry {		/* only used to size scratch areas */
222174214Sjkoshy	struct pmclog_callchain		pl_cc;
223147191Sjkoshy	struct pmclog_closelog		pl_cl;
224147191Sjkoshy	struct pmclog_dropnotify	pl_dn;
225147191Sjkoshy	struct pmclog_initialize	pl_i;
226157144Sjkoshy	struct pmclog_map_in		pl_mi;
227157144Sjkoshy	struct pmclog_map_out		pl_mo;
228147191Sjkoshy	struct pmclog_pcsample		pl_s;
229147191Sjkoshy	struct pmclog_pmcallocate	pl_a;
230233628Sfabient	struct pmclog_pmcallocatedyn	pl_ad;
231147191Sjkoshy	struct pmclog_pmcattach		pl_t;
232147191Sjkoshy	struct pmclog_pmcdetach		pl_d;
233147191Sjkoshy	struct pmclog_proccsw		pl_c;
234147191Sjkoshy	struct pmclog_procexec		pl_x;
235147191Sjkoshy	struct pmclog_procexit		pl_e;
236147191Sjkoshy	struct pmclog_procfork		pl_f;
237147191Sjkoshy	struct pmclog_sysexit		pl_se;
238147191Sjkoshy	struct pmclog_userdata		pl_u;
239147191Sjkoshy};
240147191Sjkoshy
241147191Sjkoshy#define	PMCLOG_HEADER_MAGIC					0xEEU
242147191Sjkoshy
243147191Sjkoshy#define	PMCLOG_HEADER_TO_LENGTH(H)				\
244147191Sjkoshy	((H) & 0x0000FFFF)
245147191Sjkoshy#define	PMCLOG_HEADER_TO_TYPE(H)				\
246147191Sjkoshy	(((H) & 0x00FF0000) >> 16)
247147191Sjkoshy#define	PMCLOG_HEADER_TO_MAGIC(H)				\
248147191Sjkoshy	(((H) & 0xFF000000) >> 24)
249147191Sjkoshy#define	PMCLOG_HEADER_CHECK_MAGIC(H)				\
250147191Sjkoshy	(PMCLOG_HEADER_TO_MAGIC(H) == PMCLOG_HEADER_MAGIC)
251147191Sjkoshy
252147191Sjkoshy#ifdef	_KERNEL
253147191Sjkoshy
254147191Sjkoshy/*
255147191Sjkoshy * Prototypes
256147191Sjkoshy */
257185363Sjkoshyint	pmclog_configure_log(struct pmc_mdep *_md, struct pmc_owner *_po,
258185363Sjkoshy    int _logfd);
259147191Sjkoshyint	pmclog_deconfigure_log(struct pmc_owner *_po);
260147191Sjkoshyint	pmclog_flush(struct pmc_owner *_po);
261226514Sfabientint	pmclog_close(struct pmc_owner *_po);
262147191Sjkoshyvoid	pmclog_initialize(void);
263174395Sjkoshyvoid	pmclog_process_callchain(struct pmc *_pm, struct pmc_sample *_ps);
264147191Sjkoshyvoid	pmclog_process_closelog(struct pmc_owner *po);
265147191Sjkoshyvoid	pmclog_process_dropnotify(struct pmc_owner *po);
266157144Sjkoshyvoid	pmclog_process_map_in(struct pmc_owner *po, pid_t pid,
267157144Sjkoshy    uintfptr_t start, const char *path);
268157144Sjkoshyvoid	pmclog_process_map_out(struct pmc_owner *po, pid_t pid,
269157144Sjkoshy    uintfptr_t start, uintfptr_t end);
270147191Sjkoshyvoid	pmclog_process_pmcallocate(struct pmc *_pm);
271147191Sjkoshyvoid	pmclog_process_pmcattach(struct pmc *_pm, pid_t _pid, char *_path);
272147191Sjkoshyvoid	pmclog_process_pmcdetach(struct pmc *_pm, pid_t _pid);
273147191Sjkoshyvoid	pmclog_process_proccsw(struct pmc *_pm, struct pmc_process *_pp,
274147191Sjkoshy    pmc_value_t _v);
275147708Sjkoshyvoid	pmclog_process_procexec(struct pmc_owner *_po, pmc_id_t _pmid, pid_t _pid,
276147708Sjkoshy    uintfptr_t _startaddr, char *_path);
277147191Sjkoshyvoid	pmclog_process_procexit(struct pmc *_pm, struct pmc_process *_pp);
278147191Sjkoshyvoid	pmclog_process_procfork(struct pmc_owner *_po, pid_t _oldpid, pid_t _newpid);
279147191Sjkoshyvoid	pmclog_process_sysexit(struct pmc_owner *_po, pid_t _pid);
280147191Sjkoshyint	pmclog_process_userlog(struct pmc_owner *_po,
281147191Sjkoshy    struct pmc_op_writelog *_wl);
282147191Sjkoshyvoid	pmclog_shutdown(void);
283147191Sjkoshy#endif	/* _KERNEL */
284147191Sjkoshy
285147191Sjkoshy#endif	/* _SYS_PMCLOG_H_ */
286