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