| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-2-Clause |
| 3 | * |
| 4 | * Copyright (c) 2003-2008, 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 | |
| 33 | #ifndef _SYS_PMC_H_ |
| 34 | #define	_SYS_PMC_H_ |
| 35 | |
| 36 | #include <dev/hwpmc/pmc_events.h> |
| 37 | #include <sys/proc.h> |
| 38 | #include <sys/counter.h> |
| 39 | #include <machine/pmc_mdep.h> |
| 40 | #include <machine/profile.h> |
| 41 | #ifdef _KERNEL |
| 42 | #include <sys/epoch.h> |
| 43 | #include <ck_queue.h> |
| 44 | #endif |
| 45 | |
| 46 | #define	PMC_MODULE_NAME		"hwpmc" |
| 47 | #define	PMC_NAME_MAX		64 /* HW counter name size */ |
| 48 | #define	PMC_CLASS_MAX		8 /* max #classes of PMCs per-system */ |
| 49 | |
| 50 | /* |
| 51 | * Kernel<->userland API version number [MMmmpppp] |
| 52 | * |
| 53 | * Major numbers are to be incremented when an incompatible change to |
| 54 | * the ABI occurs that older clients will not be able to handle. |
| 55 | * |
| 56 | * Minor numbers are incremented when a backwards compatible change |
| 57 | * occurs that allows older correct programs to run unchanged. For |
| 58 | * example, when support for a new PMC type is added. |
| 59 | * |
| 60 | * The patch version is incremented for every bug fix. |
| 61 | */ |
| 62 | #define	PMC_VERSION_MAJOR	0x0A |
| 63 | #define	PMC_VERSION_MINOR	0x00 |
| 64 | #define	PMC_VERSION_PATCH	0x0000 |
| 65 | |
| 66 | #define	PMC_VERSION		(PMC_VERSION_MAJOR << 24 |		\ |
| 67 | 	PMC_VERSION_MINOR << 16 | PMC_VERSION_PATCH) |
| 68 | |
| 69 | #define PMC_CPUID_LEN 64 |
| 70 | /* cpu model name for pmu lookup */ |
| 71 | extern char pmc_cpuid[PMC_CPUID_LEN]; |
| 72 | |
| 73 | /* |
| 74 | * Kinds of CPUs known. |
| 75 | * |
| 76 | * We keep track of CPU variants that need to be distinguished in |
| 77 | * some way for PMC operations. CPU names are grouped by manufacturer |
| 78 | * and numbered sparsely in order to minimize changes to the ABI involved |
| 79 | * when new CPUs are added. |
| 80 | * |
| 81 | * Please keep the pmc(3) manual page in sync with this list. |
| 82 | */ |
| 83 | #define	__PMC_CPUS()								\ |
| 84 | __PMC_CPU(AMD_K8,			0x01,	"AMD K8")			\ |
| 85 | __PMC_CPU(INTEL_CORE,		0x87,	"Intel Core Solo/Duo")		\ |
| 86 | __PMC_CPU(INTEL_CORE2,		0x88,	"Intel Core2")			\ |
| 87 | __PMC_CPU(INTEL_CORE2EXTREME,	0x89,	"Intel Core2 Extreme")		\ |
| 88 | __PMC_CPU(INTEL_ATOM,		0x8A,	"Intel Atom")			\ |
| 89 | __PMC_CPU(INTEL_COREI7,		0x8B,	"Intel Core i7")		\ |
| 90 | __PMC_CPU(INTEL_WESTMERE,		0x8C,	"Intel Westmere")		\ |
| 91 | __PMC_CPU(INTEL_SANDYBRIDGE,	0x8D,	"Intel Sandy Bridge")		\ |
| 92 | __PMC_CPU(INTEL_IVYBRIDGE,		0x8E,	"Intel Ivy Bridge")		\ |
| 93 | __PMC_CPU(INTEL_SANDYBRIDGE_XEON,	0x8F,	"Intel Sandy Bridge Xeon")	\ |
| 94 | __PMC_CPU(INTEL_IVYBRIDGE_XEON,	0x90,	"Intel Ivy Bridge Xeon")	\ |
| 95 | __PMC_CPU(INTEL_HASWELL,		0x91,	"Intel Haswell")		\ |
| 96 | __PMC_CPU(INTEL_ATOM_SILVERMONT,	0x92,	"Intel Atom Silvermont")	\ |
| 97 | __PMC_CPU(INTEL_NEHALEM_EX,		0x93,	"Intel Nehalem Xeon 7500")	\ |
| 98 | __PMC_CPU(INTEL_WESTMERE_EX,	0x94,	"Intel Westmere Xeon E7")	\ |
| 99 | __PMC_CPU(INTEL_HASWELL_XEON,	0x95,	"Intel Haswell Xeon E5 v3")	\ |
| 100 | __PMC_CPU(INTEL_BROADWELL,		0x96,	"Intel Broadwell")		\ |
| 101 | __PMC_CPU(INTEL_BROADWELL_XEON,	0x97,	"Intel Broadwell Xeon")		\ |
| 102 | __PMC_CPU(INTEL_SKYLAKE,		0x98,	"Intel Skylake")		\ |
| 103 | __PMC_CPU(INTEL_SKYLAKE_XEON,	0x99,	"Intel Skylake Xeon")		\ |
| 104 | __PMC_CPU(INTEL_ATOM_GOLDMONT,	0x9A,	"Intel Atom Goldmont")		\ |
| 105 | __PMC_CPU(INTEL_ICELAKE,		0x9B,	"Intel Icelake")		\ |
| 106 | __PMC_CPU(INTEL_ICELAKE_XEON,	0x9C,	"Intel Icelake Xeon")		\ |
| 107 | __PMC_CPU(INTEL_ALDERLAKE,		0x9D,	"Intel Alderlake")		\ |
| 108 | __PMC_CPU(INTEL_ATOM_GOLDMONT_P,	0x9E,	"Intel Atom Goldmont Plus")	\ |
| 109 | __PMC_CPU(INTEL_ATOM_TREMONT,	0x9F,	"Intel Atom Tremont")		\ |
| 110 | __PMC_CPU(INTEL_XSCALE,		0x100,	"Intel XScale")			\ |
| 111 | __PMC_CPU(PPC_7450,			0x300,	"PowerPC MPC7450")		\ |
| 112 | __PMC_CPU(PPC_E500,			0x340,	"PowerPC e500 Core")		\ |
| 113 | __PMC_CPU(PPC_970,			0x380,	"IBM PowerPC 970")		\ |
| 114 | __PMC_CPU(PPC_POWER8,		0x390,	"IBM POWER8")			\ |
| 115 | __PMC_CPU(GENERIC,			0x400,	"Generic")			\ |
| 116 | __PMC_CPU(ARMV7_CORTEX_A5,		0x500,	"ARMv7 Cortex A5")		\ |
| 117 | __PMC_CPU(ARMV7_CORTEX_A7,		0x501,	"ARMv7 Cortex A7")		\ |
| 118 | __PMC_CPU(ARMV7_CORTEX_A8,		0x502,	"ARMv7 Cortex A8")		\ |
| 119 | __PMC_CPU(ARMV7_CORTEX_A9,		0x503,	"ARMv7 Cortex A9")		\ |
| 120 | __PMC_CPU(ARMV7_CORTEX_A15,		0x504,	"ARMv7 Cortex A15")		\ |
| 121 | __PMC_CPU(ARMV7_CORTEX_A17,		0x505,	"ARMv7 Cortex A17")		\ |
| 122 | __PMC_CPU(ARMV8_CORTEX_A53,		0x600,	"ARMv8 Cortex A53")		\ |
| 123 | __PMC_CPU(ARMV8_CORTEX_A57,		0x601,	"ARMv8 Cortex A57")		\ |
| 124 | __PMC_CPU(ARMV8_CORTEX_A76,		0x602,	"ARMv8 Cortex A76") |
| 125 | |
| 126 | enum pmc_cputype { |
| 127 | #undef	__PMC_CPU |
| 128 | #define	__PMC_CPU(S,V,D)	PMC_CPU_##S = V, |
| 129 | 	__PMC_CPUS() |
| 130 | }; |
| 131 | |
| 132 | #define	PMC_CPU_FIRST	PMC_CPU_AMD_K8 |
| 133 | #define	PMC_CPU_LAST	PMC_CPU_ARMV8_CORTEX_A76 |
| 134 | |
| 135 | /* |
| 136 | * Classes of PMCs |
| 137 | */ |
| 138 | #define	__PMC_CLASSES()								\ |
| 139 | __PMC_CLASS(TSC,		0x00,	"CPU Timestamp counter")		\ |
| 140 | __PMC_CLASS(K8,		0x02,	"AMD K8 performance counters")		\ |
| 141 | __PMC_CLASS(IAF,		0x06,	"Intel Core2/Atom, fixed function")	\ |
| 142 | __PMC_CLASS(IAP,		0x07,	"Intel Core...Atom, programmable")	\ |
| 143 | __PMC_CLASS(UCF,		0x08,	"Intel Uncore fixed function")		\ |
| 144 | __PMC_CLASS(UCP,		0x09,	"Intel Uncore programmable")		\ |
| 145 | __PMC_CLASS(XSCALE,		0x0A,	"Intel XScale counters")		\ |
| 146 | __PMC_CLASS(PPC7450,	0x0D,	"Motorola MPC7450 class")		\ |
| 147 | __PMC_CLASS(PPC970,		0x0E,	"IBM PowerPC 970 class")		\ |
| 148 | __PMC_CLASS(SOFT,		0x0F,	"Software events")			\ |
| 149 | __PMC_CLASS(ARMV7,		0x10,	"ARMv7")				\ |
| 150 | __PMC_CLASS(ARMV8,		0x11,	"ARMv8")				\ |
| 151 | __PMC_CLASS(E500,		0x13,	"Freescale e500 class")			\ |
| 152 | __PMC_CLASS(POWER8,		0x15,	"IBM POWER8 class")			\ |
| 153 | __PMC_CLASS(DMC620_PMU_CD2,	0x16,	"ARM DMC620 Memory Controller PMU CLKDIV2") \ |
| 154 | __PMC_CLASS(DMC620_PMU_C,	0x17,	"ARM DMC620 Memory Controller PMU CLK")	\ |
| 155 | __PMC_CLASS(CMN600_PMU,	0x18,	"Arm CoreLink CMN600 Coherent Mesh Network PMU") |
| 156 | |
| 157 | enum pmc_class { |
| 158 | #undef __PMC_CLASS |
| 159 | #define	__PMC_CLASS(S,V,D)	PMC_CLASS_##S = V, |
| 160 | 	__PMC_CLASSES() |
| 161 | }; |
| 162 | |
| 163 | #define	PMC_CLASS_FIRST	PMC_CLASS_TSC |
| 164 | #define	PMC_CLASS_LAST	PMC_CLASS_CMN600_PMU |
| 165 | |
| 166 | /* |
| 167 | * A PMC can be in the following states: |
| 168 | * |
| 169 | * Hardware states: |
| 170 | * DISABLED -- administratively prohibited from being used. |
| 171 | * FREE -- HW available for use |
| 172 | * Software states: |
| 173 | * ALLOCATED -- allocated |
| 174 | * STOPPED -- allocated, but not counting events |
| 175 | * RUNNING -- allocated, and in operation; 'pm_runcount' |
| 176 | * holds the number of CPUs using this PMC at |
| 177 | * a given instant |
| 178 | * DELETED -- being destroyed |
| 179 | */ |
| 180 | |
| 181 | #define	__PMC_HWSTATES()			\ |
| 182 | 	__PMC_STATE(DISABLED)			\ |
| 183 | 	__PMC_STATE(FREE) |
| 184 | |
| 185 | #define	__PMC_SWSTATES()			\ |
| 186 | 	__PMC_STATE(ALLOCATED)			\ |
| 187 | 	__PMC_STATE(STOPPED)			\ |
| 188 | 	__PMC_STATE(RUNNING)			\ |
| 189 | 	__PMC_STATE(DELETED) |
| 190 | |
| 191 | #define	__PMC_STATES()				\ |
| 192 | 	__PMC_HWSTATES()			\ |
| 193 | 	__PMC_SWSTATES() |
| 194 | |
| 195 | enum pmc_state { |
| 196 | #undef	__PMC_STATE |
| 197 | #define	__PMC_STATE(S)	PMC_STATE_##S, |
| 198 | 	__PMC_STATES() |
| 199 | 	__PMC_STATE(MAX) |
| 200 | }; |
| 201 | |
| 202 | #define	PMC_STATE_FIRST	PMC_STATE_DISABLED |
| 203 | #define	PMC_STATE_LAST	PMC_STATE_DELETED |
| 204 | |
| 205 | /* |
| 206 | * An allocated PMC may used as a 'global' counter or as a |
| 207 | * 'thread-private' one. Each such mode of use can be in either |
| 208 | * statistical sampling mode or in counting mode. Thus a PMC in use |
| 209 | * |
| 210 | * SS i.e., SYSTEM STATISTICAL -- system-wide statistical profiling |
| 211 | * SC i.e., SYSTEM COUNTER -- system-wide counting mode |
| 212 | * TS i.e., THREAD STATISTICAL -- thread virtual, statistical profiling |
| 213 | * TC i.e., THREAD COUNTER -- thread virtual, counting mode |
| 214 | * |
| 215 | * Statistical profiling modes rely on the PMC periodically delivering |
| 216 | * a interrupt to the CPU (when the configured number of events have |
| 217 | * been measured), so the PMC must have the ability to generate |
| 218 | * interrupts. |
| 219 | * |
| 220 | * In counting modes, the PMC counts its configured events, with the |
| 221 | * value of the PMC being read whenever needed by its owner process. |
| 222 | * |
| 223 | * The thread specific modes "virtualize" the PMCs -- the PMCs appear |
| 224 | * to be thread private and count events only when the profiled thread |
| 225 | * actually executes on the CPU. |
| 226 | * |
| 227 | * The system-wide "global" modes keep the PMCs running all the time |
| 228 | * and are used to measure the behaviour of the whole system. |
| 229 | */ |
| 230 | |
| 231 | #define	__PMC_MODES()				\ |
| 232 | 	__PMC_MODE(SS,	0)			\ |
| 233 | 	__PMC_MODE(SC,	1)			\ |
| 234 | 	__PMC_MODE(TS,	2)			\ |
| 235 | 	__PMC_MODE(TC,	3) |
| 236 | |
| 237 | enum pmc_mode { |
| 238 | #undef	__PMC_MODE |
| 239 | #define	__PMC_MODE(M,N)	PMC_MODE_##M = N, |
| 240 | 	__PMC_MODES() |
| 241 | }; |
| 242 | |
| 243 | #define	PMC_MODE_FIRST	PMC_MODE_SS |
| 244 | #define	PMC_MODE_LAST	PMC_MODE_TC |
| 245 | |
| 246 | #define	PMC_IS_COUNTING_MODE(mode)				\ |
| 247 | 	((mode) == PMC_MODE_SC || (mode) == PMC_MODE_TC) |
| 248 | #define	PMC_IS_SYSTEM_MODE(mode)				\ |
| 249 | 	((mode) == PMC_MODE_SS || (mode) == PMC_MODE_SC) |
| 250 | #define	PMC_IS_SAMPLING_MODE(mode)				\ |
| 251 | 	((mode) == PMC_MODE_SS || (mode) == PMC_MODE_TS) |
| 252 | #define	PMC_IS_VIRTUAL_MODE(mode)				\ |
| 253 | 	((mode) == PMC_MODE_TS || (mode) == PMC_MODE_TC) |
| 254 | |
| 255 | /* |
| 256 | * PMC row disposition |
| 257 | */ |
| 258 | |
| 259 | #define	__PMC_DISPOSITIONS(N)					\ |
| 260 | 	__PMC_DISP(STANDALONE)	/* global/disabled counters */	\ |
| 261 | 	__PMC_DISP(FREE)	/* free/available */		\ |
| 262 | 	__PMC_DISP(THREAD)	/* thread-virtual PMCs */	\ |
| 263 | 	__PMC_DISP(UNKNOWN)	/* sentinel */ |
| 264 | |
| 265 | enum pmc_disp { |
| 266 | #undef	__PMC_DISP |
| 267 | #define	__PMC_DISP(D)	PMC_DISP_##D , |
| 268 | 	__PMC_DISPOSITIONS() |
| 269 | }; |
| 270 | |
| 271 | #define	PMC_DISP_FIRST	PMC_DISP_STANDALONE |
| 272 | #define	PMC_DISP_LAST	PMC_DISP_THREAD |
| 273 | |
| 274 | /* |
| 275 | * Counter capabilities |
| 276 | * |
| 277 | * __PMC_CAPS(NAME, VALUE, DESCRIPTION) |
| 278 | */ |
| 279 | |
| 280 | #define	__PMC_CAPS()							\ |
| 281 | 	__PMC_CAP(INTERRUPT,	0, "generate interrupts")		\ |
| 282 | 	__PMC_CAP(USER,		1, "count user-mode events")		\ |
| 283 | 	__PMC_CAP(SYSTEM,	2, "count system-mode events")		\ |
| 284 | 	__PMC_CAP(EDGE,		3, "do edge detection of events")	\ |
| 285 | 	__PMC_CAP(THRESHOLD,	4, "ignore events below a threshold")	\ |
| 286 | 	__PMC_CAP(READ,		5, "read PMC counter")			\ |
| 287 | 	__PMC_CAP(WRITE,	6, "reprogram PMC counter")		\ |
| 288 | 	__PMC_CAP(INVERT,	7, "invert comparison sense")		\ |
| 289 | 	__PMC_CAP(QUALIFIER,	8, "further qualify monitored events")	\ |
| 290 | 	__PMC_CAP(PRECISE,	9, "perform precise sampling")		\ |
| 291 | 	__PMC_CAP(TAGGING,	10, "tag upstream events")		\ |
| 292 | 	__PMC_CAP(CASCADE,	11, "cascade counters")			\ |
| 293 | 	__PMC_CAP(SYSWIDE,	12, "system wide counter")		\ |
| 294 | 	__PMC_CAP(DOMWIDE,	13, "NUMA domain wide counter") |
| 295 | |
| 296 | enum pmc_caps |
| 297 | { |
| 298 | #undef	__PMC_CAP |
| 299 | #define	__PMC_CAP(NAME, VALUE, DESCR)	PMC_CAP_##NAME = (1 << VALUE) , |
| 300 | 	__PMC_CAPS() |
| 301 | }; |
| 302 | |
| 303 | #define	PMC_CAP_FIRST		PMC_CAP_INTERRUPT |
| 304 | #define	PMC_CAP_LAST		PMC_CAP_DOMWIDE |
| 305 | |
| 306 | /* |
| 307 | * PMC Event Numbers |
| 308 | * |
| 309 | * These are generated from the definitions in "dev/hwpmc/pmc_events.h". |
| 310 | */ |
| 311 | |
| 312 | enum pmc_event { |
| 313 | #undef	__PMC_EV |
| 314 | #undef	__PMC_EV_BLOCK |
| 315 | #define	__PMC_EV_BLOCK(C,V)	PMC_EV_ ## C ## __BLOCK_START = (V) - 1 , |
| 316 | #define	__PMC_EV(C,N)		PMC_EV_ ## C ## _ ## N , |
| 317 | 	__PMC_EVENTS() |
| 318 | }; |
| 319 | |
| 320 | /* |
| 321 | * PMC SYSCALL INTERFACE |
| 322 | */ |
| 323 | |
| 324 | /* |
| 325 | * "PMC_OPS" -- these are the commands recognized by the kernel |
| 326 | * module, and are used when performing a system call from userland. |
| 327 | */ |
| 328 | #define	__PMC_OPS()							\ |
| 329 | 	__PMC_OP(CONFIGURELOG, "Set log file")				\ |
| 330 | 	__PMC_OP(FLUSHLOG, "Flush log file")				\ |
| 331 | 	__PMC_OP(GETCPUINFO, "Get system CPU information")		\ |
| 332 | 	__PMC_OP(GETDRIVERSTATS, "Get driver statistics")		\ |
| 333 | 	__PMC_OP(GETMODULEVERSION, "Get module version")		\ |
| 334 | 	__PMC_OP(GETPMCINFO, "Get per-cpu PMC information")		\ |
| 335 | 	__PMC_OP(PMCADMIN, "Set PMC state")				\ |
| 336 | 	__PMC_OP(PMCALLOCATE, "Allocate and configure a PMC")		\ |
| 337 | 	__PMC_OP(PMCATTACH, "Attach a PMC to a process")		\ |
| 338 | 	__PMC_OP(PMCDETACH, "Detach a PMC from a process")		\ |
| 339 | 	__PMC_OP(PMCGETMSR, "Get a PMC's hardware address")		\ |
| 340 | 	__PMC_OP(PMCRELEASE, "Release a PMC")				\ |
| 341 | 	__PMC_OP(PMCRW, "Read/Set a PMC")				\ |
| 342 | 	__PMC_OP(PMCSETCOUNT, "Set initial count/sampling rate")	\ |
| 343 | 	__PMC_OP(PMCSTART, "Start a PMC")				\ |
| 344 | 	__PMC_OP(PMCSTOP, "Stop a PMC")					\ |
| 345 | 	__PMC_OP(WRITELOG, "Write a cookie to the log file")		\ |
| 346 | 	__PMC_OP(CLOSELOG, "Close log file")				\ |
| 347 | 	__PMC_OP(GETDYNEVENTINFO, "Get dynamic events list") |
| 348 | |
| 349 | enum pmc_ops { |
| 350 | #undef	__PMC_OP |
| 351 | #define	__PMC_OP(N, D)	PMC_OP_##N, |
| 352 | 	__PMC_OPS() |
| 353 | }; |
| 354 | |
| 355 | /* |
| 356 | * Flags used in operations on PMCs. |
| 357 | */ |
| 358 | |
| 359 | #define	PMC_F_UNUSED1		0x00000001 /* unused */ |
| 360 | #define	PMC_F_DESCENDANTS	0x00000002 /*OP ALLOCATE track descendants */ |
| 361 | #define	PMC_F_LOG_PROCCSW	0x00000004 /*OP ALLOCATE track ctx switches */ |
| 362 | #define	PMC_F_LOG_PROCEXIT	0x00000008 /*OP ALLOCATE log proc exits */ |
| 363 | #define	PMC_F_NEWVALUE		0x00000010 /*OP RW write new value */ |
| 364 | #define	PMC_F_OLDVALUE		0x00000020 /*OP RW get old value */ |
| 365 | |
| 366 | /* V2 API */ |
| 367 | #define	PMC_F_CALLCHAIN		0x00000080 /*OP ALLOCATE capture callchains */ |
| 368 | #define	PMC_F_USERCALLCHAIN	0x00000100 /*OP ALLOCATE use userspace stack */ |
| 369 | |
| 370 | /* V10 API */ |
| 371 | #define	PMC_F_EV_PMU		0x00000200 /* |
| 372 | 					 * OP ALLOCATE: pm_ev has special |
| 373 | 					 * userspace meaning; counter |
| 374 | 					 * configuration is communicated |
| 375 | 					 * through class-dependent fields |
| 376 | 					 */ |
| 377 | |
| 378 | /* internal flags */ |
| 379 | #define	PMC_F_ATTACHED_TO_OWNER	0x00010000 /*attached to owner*/ |
| 380 | #define	PMC_F_NEEDS_LOGFILE	0x00020000 /*needs log file */ |
| 381 | #define	PMC_F_ATTACH_DONE	0x00040000 /*attached at least once */ |
| 382 | |
| 383 | #define	PMC_CALLCHAIN_DEPTH_MAX	512 |
| 384 | |
| 385 | #define	PMC_CC_F_USERSPACE	0x01	 /*userspace callchain*/ |
| 386 | |
| 387 | /* |
| 388 | * Cookies used to denote allocated PMCs, and the values of PMCs. |
| 389 | */ |
| 390 | |
| 391 | typedef uint32_t	pmc_id_t; |
| 392 | typedef uint64_t	pmc_value_t; |
| 393 | |
| 394 | #define	PMC_ID_INVALID		(~ (pmc_id_t) 0) |
| 395 | |
| 396 | /* |
| 397 | * PMC IDs have the following format: |
| 398 | * |
| 399 | * +-----------------------+-------+-----------+ |
| 400 | * | CPU | PMC MODE | CLASS | ROW INDEX | |
| 401 | * +-----------------------+-------+-----------+ |
| 402 | * |
| 403 | * where CPU is 12 bits, MODE 4, CLASS 8, and ROW INDEX 8 Field 'CPU' |
| 404 | * is set to the requested CPU for system-wide PMCs or PMC_CPU_ANY for |
| 405 | * process-mode PMCs. Field 'PMC MODE' is the allocated PMC mode. |
| 406 | * Field 'PMC CLASS' is the class of the PMC. Field 'ROW INDEX' is the |
| 407 | * row index for the PMC. |
| 408 | * |
| 409 | * The 'ROW INDEX' ranges over 0..NWPMCS where NHWPMCS is the total |
| 410 | * number of hardware PMCs on this cpu. |
| 411 | */ |
| 412 | |
| 413 | #define	PMC_ID_TO_ROWINDEX(ID)	((ID) & 0xFF) |
| 414 | #define	PMC_ID_TO_CLASS(ID)	(((ID) & 0xFF00) >> 8) |
| 415 | #define	PMC_ID_TO_MODE(ID)	(((ID) & 0xF0000) >> 16) |
| 416 | #define	PMC_ID_TO_CPU(ID)	(((ID) & 0xFFF00000) >> 20) |
| 417 | #define	PMC_ID_MAKE_ID(CPU,MODE,CLASS,ROWINDEX)			\ |
| 418 | 	((((CPU) & 0xFFF) << 20) | (((MODE) & 0xF) << 16) |	\ |
| 419 | 	(((CLASS) & 0xFF) << 8) | ((ROWINDEX) & 0xFF)) |
| 420 | |
| 421 | /* |
| 422 | * Data structures for system calls supported by the pmc driver. |
| 423 | */ |
| 424 | |
| 425 | /* |
| 426 | * OP PMCALLOCATE |
| 427 | * |
| 428 | * Allocate a PMC on the named CPU. |
| 429 | */ |
| 430 | |
| 431 | #define	PMC_CPU_ANY	~0 |
| 432 | |
| 433 | struct pmc_op_pmcallocate { |
| 434 | 	uint32_t	pm_caps;	/* PMC_CAP_* */ |
| 435 | 	uint32_t	pm_cpu;		/* CPU number or PMC_CPU_ANY */ |
| 436 | 	enum pmc_class	pm_class;	/* class of PMC desired */ |
| 437 | 	enum pmc_event	pm_ev;		/* [enum pmc_event] desired */ |
| 438 | 	uint32_t	pm_flags;	/* additional modifiers PMC_F_* */ |
| 439 | 	enum pmc_mode	pm_mode;	/* desired mode */ |
| 440 | 	pmc_id_t	pm_pmcid;	/* [return] process pmc id */ |
| 441 | 	pmc_value_t	pm_count;	/* initial/sample count */ |
| 442 | |
| 443 | 	union pmc_md_op_pmcallocate pm_md; /* MD layer extensions */ |
| 444 | }; |
| 445 | |
| 446 | /* |
| 447 | * OP PMCADMIN |
| 448 | * |
| 449 | * Set the administrative state (i.e., whether enabled or disabled) of |
| 450 | * a PMC 'pm_pmc' on CPU 'pm_cpu'. Note that 'pm_pmc' specifies an |
| 451 | * absolute PMC number and need not have been first allocated by the |
| 452 | * calling process. |
| 453 | */ |
| 454 | |
| 455 | struct pmc_op_pmcadmin { |
| 456 | 	int		pm_cpu;		/* CPU# */ |
| 457 | 	uint32_t	pm_flags;	/* flags */ |
| 458 | 	int		pm_pmc; /* PMC# */ |
| 459 | 	enum pmc_state pm_state;	/* desired state */ |
| 460 | }; |
| 461 | |
| 462 | /* |
| 463 | * OP PMCATTACH / OP PMCDETACH |
| 464 | * |
| 465 | * Attach/detach a PMC and a process. |
| 466 | */ |
| 467 | |
| 468 | struct pmc_op_pmcattach { |
| 469 | 	pmc_id_t	pm_pmc;		/* PMC to attach to */ |
| 470 | 	pid_t		pm_pid;		/* target process */ |
| 471 | }; |
| 472 | |
| 473 | /* |
| 474 | * OP PMCSETCOUNT |
| 475 | * |
| 476 | * Set the sampling rate (i.e., the reload count) for statistical counters. |
| 477 | * 'pm_pmcid' need to have been previously allocated using PMCALLOCATE. |
| 478 | */ |
| 479 | |
| 480 | struct pmc_op_pmcsetcount { |
| 481 | 	pmc_value_t	pm_count;	/* initial/sample count */ |
| 482 | 	pmc_id_t	pm_pmcid;	/* PMC id to set */ |
| 483 | }; |
| 484 | |
| 485 | /* |
| 486 | * OP PMCRW |
| 487 | * |
| 488 | * Read the value of a PMC named by 'pm_pmcid'. 'pm_pmcid' needs |
| 489 | * to have been previously allocated using PMCALLOCATE. |
| 490 | */ |
| 491 | |
| 492 | struct pmc_op_pmcrw { |
| 493 | 	uint32_t	pm_flags;	/* PMC_F_{OLD,NEW}VALUE*/ |
| 494 | 	pmc_id_t	pm_pmcid;	/* pmc id */ |
| 495 | 	pmc_value_t	pm_value;	/* new&returned value */ |
| 496 | }; |
| 497 | |
| 498 | /* |
| 499 | * OP GETPMCINFO |
| 500 | * |
| 501 | * retrieve PMC state for a named CPU. The caller is expected to |
| 502 | * allocate 'npmc' * 'struct pmc_info' bytes of space for the return |
| 503 | * values. |
| 504 | */ |
| 505 | |
| 506 | struct pmc_info { |
| 507 | 	char		pm_name[PMC_NAME_MAX]; /* pmc name */ |
| 508 | 	enum pmc_class	pm_class;	/* enum pmc_class */ |
| 509 | 	int		pm_enabled;	/* whether enabled */ |
| 510 | 	enum pmc_disp	pm_rowdisp;	/* FREE, THREAD or STANDLONE */ |
| 511 | 	pid_t		pm_ownerpid;	/* owner, or -1 */ |
| 512 | 	enum pmc_mode	pm_mode;	/* current mode [enum pmc_mode] */ |
| 513 | 	enum pmc_event	pm_event;	/* current event */ |
| 514 | 	uint32_t	pm_flags;	/* current flags */ |
| 515 | 	pmc_value_t	pm_reloadcount;	/* sampling counters only */ |
| 516 | }; |
| 517 | |
| 518 | struct pmc_op_getpmcinfo { |
| 519 | 	int32_t		pm_cpu;		/* 0 <= cpu < mp_maxid */ |
| 520 | 	struct pmc_info	pm_pmcs[];	/* space for 'npmc' structures */ |
| 521 | }; |
| 522 | |
| 523 | /* |
| 524 | * OP GETCPUINFO |
| 525 | * |
| 526 | * Retrieve system CPU information. |
| 527 | */ |
| 528 | |
| 529 | struct pmc_classinfo { |
| 530 | 	enum pmc_class	pm_class;	/* class id */ |
| 531 | 	uint32_t	pm_caps;	/* counter capabilities */ |
| 532 | 	uint32_t	pm_width;	/* width of the PMC */ |
| 533 | 	uint32_t	pm_num;		/* number of PMCs in class */ |
| 534 | }; |
| 535 | |
| 536 | struct pmc_op_getcpuinfo { |
| 537 | 	enum pmc_cputype pm_cputype; /* what kind of CPU */ |
| 538 | 	uint32_t	pm_ncpu; /* max CPU number */ |
| 539 | 	uint32_t	pm_npmc; /* #PMCs per CPU */ |
| 540 | 	uint32_t	pm_nclass; /* #classes of PMCs */ |
| 541 | 	struct pmc_classinfo pm_classes[PMC_CLASS_MAX]; |
| 542 | }; |
| 543 | |
| 544 | /* |
| 545 | * OP CONFIGURELOG |
| 546 | * |
| 547 | * Configure a log file for writing system-wide statistics to. |
| 548 | */ |
| 549 | |
| 550 | struct pmc_op_configurelog { |
| 551 | 	int		pm_flags; |
| 552 | 	int		pm_logfd; /* logfile fd (or -1) */ |
| 553 | }; |
| 554 | |
| 555 | /* |
| 556 | * OP GETDRIVERSTATS |
| 557 | * |
| 558 | * Retrieve pmc(4) driver-wide statistics. |
| 559 | */ |
| 560 | #ifdef _KERNEL |
| 561 | struct pmc_driverstats { |
| 562 | 	counter_u64_t	pm_intr_ignored;	/* #interrupts ignored */ |
| 563 | 	counter_u64_t	pm_intr_processed;	/* #interrupts processed */ |
| 564 | 	counter_u64_t	pm_intr_bufferfull;	/* #interrupts with ENOSPC */ |
| 565 | 	counter_u64_t	pm_syscalls;		/* #syscalls */ |
| 566 | 	counter_u64_t	pm_syscall_errors;	/* #syscalls with errors */ |
| 567 | 	counter_u64_t	pm_buffer_requests;	/* #buffer requests */ |
| 568 | 	counter_u64_t	pm_buffer_requests_failed; /* #failed buffer requests */ |
| 569 | 	counter_u64_t	pm_log_sweeps;		/* #sample buffer processing |
| 570 | 						 passes */ |
| 571 | 	counter_u64_t	pm_merges;		/* merged k+u */ |
| 572 | 	counter_u64_t	pm_overwrites;		/* UR overwrites */ |
| 573 | }; |
| 574 | #endif |
| 575 | |
| 576 | struct pmc_op_getdriverstats { |
| 577 | 	unsigned int	pm_intr_ignored;	/* #interrupts ignored */ |
| 578 | 	unsigned int	pm_intr_processed;	/* #interrupts processed */ |
| 579 | 	unsigned int	pm_intr_bufferfull;	/* #interrupts with ENOSPC */ |
| 580 | 	unsigned int	pm_syscalls;		/* #syscalls */ |
| 581 | 	unsigned int	pm_syscall_errors;	/* #syscalls with errors */ |
| 582 | 	unsigned int	pm_buffer_requests;	/* #buffer requests */ |
| 583 | 	unsigned int	pm_buffer_requests_failed; /* #failed buffer requests */ |
| 584 | 	unsigned int	pm_log_sweeps;		/* #sample buffer processing |
| 585 | 						 passes */ |
| 586 | }; |
| 587 | |
| 588 | /* |
| 589 | * OP RELEASE / OP START / OP STOP |
| 590 | * |
| 591 | * Simple operations on a PMC id. |
| 592 | */ |
| 593 | |
| 594 | struct pmc_op_simple { |
| 595 | 	pmc_id_t	pm_pmcid; |
| 596 | }; |
| 597 | |
| 598 | /* |
| 599 | * OP WRITELOG |
| 600 | * |
| 601 | * Flush the current log buffer and write 4 bytes of user data to it. |
| 602 | */ |
| 603 | |
| 604 | struct pmc_op_writelog { |
| 605 | 	uint32_t	pm_userdata; |
| 606 | }; |
| 607 | |
| 608 | /* |
| 609 | * OP GETMSR |
| 610 | * |
| 611 | * Retrieve the machine specific address associated with the allocated |
| 612 | * PMC. This number can be used subsequently with a read-performance-counter |
| 613 | * instruction. |
| 614 | */ |
| 615 | |
| 616 | struct pmc_op_getmsr { |
| 617 | 	uint32_t	pm_msr;		/* machine specific address */ |
| 618 | 	pmc_id_t	pm_pmcid;	/* allocated pmc id */ |
| 619 | }; |
| 620 | |
| 621 | /* |
| 622 | * OP GETDYNEVENTINFO |
| 623 | * |
| 624 | * Retrieve a PMC dynamic class events list. |
| 625 | */ |
| 626 | |
| 627 | struct pmc_dyn_event_descr { |
| 628 | 	char		pm_ev_name[PMC_NAME_MAX]; |
| 629 | 	enum pmc_event	pm_ev_code; |
| 630 | }; |
| 631 | |
| 632 | struct pmc_op_getdyneventinfo { |
| 633 | 	enum pmc_class			pm_class; |
| 634 | 	unsigned int			pm_nevent; |
| 635 | 	struct pmc_dyn_event_descr	pm_events[PMC_EV_DYN_COUNT]; |
| 636 | }; |
| 637 | |
| 638 | #ifdef _KERNEL |
| 639 | |
| 640 | #include <sys/malloc.h> |
| 641 | #include <sys/sysctl.h> |
| 642 | #include <sys/_cpuset.h> |
| 643 | |
| 644 | #include <machine/frame.h> |
| 645 | |
| 646 | #define	PMC_HASH_SIZE				1024 |
| 647 | #define	PMC_MTXPOOL_SIZE			2048 |
| 648 | #define	PMC_LOG_BUFFER_SIZE			256 |
| 649 | #define	PMC_NLOGBUFFERS_PCPU			32 |
| 650 | #define	PMC_NSAMPLES				256 |
| 651 | #define	PMC_CALLCHAIN_DEPTH			128 |
| 652 | #define	PMC_THREADLIST_MAX			128 |
| 653 | |
| 654 | #define PMC_SYSCTL_NAME_PREFIX "kern." PMC_MODULE_NAME "." |
| 655 | |
| 656 | /* |
| 657 | * Locking keys |
| 658 | * |
| 659 | * (b) - pmc_bufferlist_mtx (spin lock) |
| 660 | * (k) - pmc_kthread_mtx (sleep lock) |
| 661 | * (o) - po->po_mtx (spin lock) |
| 662 | * (g) - global_epoch_preempt (epoch) |
| 663 | * (p) - pmc_sx (sx) |
| 664 | */ |
| 665 | |
| 666 | /* |
| 667 | * PMC commands |
| 668 | */ |
| 669 | |
| 670 | struct pmc_syscall_args { |
| 671 | 	register_t	pmop_code;	/* one of PMC_OP_* */ |
| 672 | 	void		*pmop_data;	/* syscall parameter */ |
| 673 | }; |
| 674 | |
| 675 | /* |
| 676 | * Interface to processor specific s1tuff |
| 677 | */ |
| 678 | |
| 679 | /* |
| 680 | * struct pmc_descr |
| 681 | * |
| 682 | * Machine independent (i.e., the common parts) of a human readable |
| 683 | * PMC description. |
| 684 | */ |
| 685 | |
| 686 | struct pmc_descr { |
| 687 | 	char		pd_name[PMC_NAME_MAX]; /* name */ |
| 688 | 	uint32_t	pd_caps;	/* capabilities */ |
| 689 | 	enum pmc_class	pd_class;	/* class of the PMC */ |
| 690 | 	uint32_t	pd_width;	/* width in bits */ |
| 691 | }; |
| 692 | |
| 693 | /* |
| 694 | * struct pmc_target |
| 695 | * |
| 696 | * This structure records all the target processes associated with a |
| 697 | * PMC. |
| 698 | */ |
| 699 | |
| 700 | struct pmc_target { |
| 701 | 	LIST_ENTRY(pmc_target)	pt_next; |
| 702 | 	struct pmc_process	*pt_process; /* target descriptor */ |
| 703 | }; |
| 704 | |
| 705 | /* |
| 706 | * struct pmc |
| 707 | * |
| 708 | * Describes each allocated PMC. |
| 709 | * |
| 710 | * Each PMC has precisely one owner, namely the process that allocated |
| 711 | * the PMC. |
| 712 | * |
| 713 | * A PMC may be attached to multiple target processes. The |
| 714 | * 'pm_targets' field links all the target processes being monitored |
| 715 | * by this PMC. |
| 716 | * |
| 717 | * The 'pm_savedvalue' field is protected by a mutex. |
| 718 | * |
| 719 | * On a multi-cpu machine, multiple target threads associated with a |
| 720 | * process-virtual PMC could be concurrently executing on different |
| 721 | * CPUs. The 'pm_runcount' field is atomically incremented every time |
| 722 | * the PMC gets scheduled on a CPU and atomically decremented when it |
| 723 | * get descheduled. Deletion of a PMC is only permitted when this |
| 724 | * field is '0'. |
| 725 | * |
| 726 | */ |
| 727 | struct pmc_pcpu_state { |
| 728 | 	uint32_t pps_overflowcnt;	/* count overflow interrupts */ |
| 729 | 	uint8_t pps_stalled; |
| 730 | 	uint8_t pps_cpustate; |
| 731 | } __aligned(CACHE_LINE_SIZE); |
| 732 | struct pmc { |
| 733 | 	LIST_HEAD(,pmc_target)	pm_targets;	/* list of target processes */ |
| 734 | 	LIST_ENTRY(pmc)		pm_next;	/* owner's list */ |
| 735 | |
| 736 | 	/* |
| 737 | 	 * System-wide PMCs are allocated on a CPU and are not moved |
| 738 | 	 * around. For system-wide PMCs we record the CPU the PMC was |
| 739 | 	 * allocated on in the 'CPU' field of the pmc ID. |
| 740 | 	 * |
| 741 | 	 * Virtual PMCs run on whichever CPU is currently executing |
| 742 | 	 * their targets' threads. For these PMCs we need to save |
| 743 | 	 * their current PMC counter values when they are taken off |
| 744 | 	 * CPU. |
| 745 | 	 */ |
| 746 | |
| 747 | 	union { |
| 748 | 		pmc_value_t	pm_savedvalue;	/* Virtual PMCS */ |
| 749 | 	} pm_gv; |
| 750 | |
| 751 | 	/* |
| 752 | 	 * For sampling mode PMCs, we keep track of the PMC's "reload |
| 753 | 	 * count", which is the counter value to be loaded in when |
| 754 | 	 * arming the PMC for the next counting session. For counting |
| 755 | 	 * modes on PMCs that are read-only (e.g., the x86 TSC), we |
| 756 | 	 * keep track of the initial value at the start of |
| 757 | 	 * counting-mode operation. |
| 758 | 	 */ |
| 759 | |
| 760 | 	union { |
| 761 | 		pmc_value_t	pm_reloadcount;	/* sampling PMC modes */ |
| 762 | 		pmc_value_t	pm_initial;	/* counting PMC modes */ |
| 763 | 	} pm_sc; |
| 764 | |
| 765 | 	struct pmc_pcpu_state *pm_pcpu_state; |
| 766 | 	volatile cpuset_t pm_cpustate;	/* CPUs where PMC should be active */ |
| 767 | 	uint32_t	pm_caps;	/* PMC capabilities */ |
| 768 | 	enum pmc_event	pm_event;	/* event being measured */ |
| 769 | 	uint32_t	pm_flags;	/* additional flags PMC_F_... */ |
| 770 | 	struct pmc_owner *pm_owner;	/* owner thread state */ |
| 771 | 	counter_u64_t		pm_runcount;	/* #cpus currently on */ |
| 772 | 	enum pmc_state	pm_state;	/* current PMC state */ |
| 773 | |
| 774 | 	/* |
| 775 | 	 * The PMC ID field encodes the row-index for the PMC, its |
| 776 | 	 * mode, class and the CPU# associated with the PMC. |
| 777 | 	 */ |
| 778 | |
| 779 | 	pmc_id_t	pm_id;		/* allocated PMC id */ |
| 780 | 	enum pmc_class pm_class; |
| 781 | |
| 782 | 	/* md extensions */ |
| 783 | 	union pmc_md_pmc	pm_md; |
| 784 | }; |
| 785 | |
| 786 | /* |
| 787 | * Accessor macros for 'struct pmc' |
| 788 | */ |
| 789 | |
| 790 | #define	PMC_TO_MODE(P)		PMC_ID_TO_MODE((P)->pm_id) |
| 791 | #define	PMC_TO_CLASS(P)		PMC_ID_TO_CLASS((P)->pm_id) |
| 792 | #define	PMC_TO_ROWINDEX(P)	PMC_ID_TO_ROWINDEX((P)->pm_id) |
| 793 | #define	PMC_TO_CPU(P)		PMC_ID_TO_CPU((P)->pm_id) |
| 794 | |
| 795 | /* |
| 796 | * struct pmc_threadpmcstate |
| 797 | * |
| 798 | * Record per-PMC, per-thread state. |
| 799 | */ |
| 800 | struct pmc_threadpmcstate { |
| 801 | 	pmc_value_t	pt_pmcval;	/* per-thread reload count */ |
| 802 | }; |
| 803 | |
| 804 | /* |
| 805 | * struct pmc_thread |
| 806 | * |
| 807 | * Record a 'target' thread being profiled. |
| 808 | */ |
| 809 | struct pmc_thread { |
| 810 | 	LIST_ENTRY(pmc_thread) pt_next;		/* linked list */ |
| 811 | 	struct thread	*pt_td;			/* target thread */ |
| 812 | 	struct pmc_threadpmcstate pt_pmcs[];	/* per-PMC state */ |
| 813 | }; |
| 814 | |
| 815 | /* |
| 816 | * struct pmc_process |
| 817 | * |
| 818 | * Record a 'target' process being profiled. |
| 819 | * |
| 820 | * The target process being profiled could be different from the owner |
| 821 | * process which allocated the PMCs. Each target process descriptor |
| 822 | * is associated with NHWPMC 'struct pmc *' pointers. Each PMC at a |
| 823 | * given hardware row-index 'n' will use slot 'n' of the 'pp_pmcs[]' |
| 824 | * array. The size of this structure is thus PMC architecture |
| 825 | * dependent. |
| 826 | * |
| 827 | */ |
| 828 | |
| 829 | struct pmc_targetstate { |
| 830 | 	struct pmc	*pp_pmc; /* target PMC */ |
| 831 | 	pmc_value_t	pp_pmcval; /* per-process value */ |
| 832 | }; |
| 833 | |
| 834 | struct pmc_process { |
| 835 | 	LIST_ENTRY(pmc_process) pp_next;	/* hash chain */ |
| 836 | 	LIST_HEAD(,pmc_thread) pp_tds;		/* list of threads */ |
| 837 | 	struct mtx	*pp_tdslock;		/* lock on pp_tds thread list */ |
| 838 | 	int		pp_refcnt;		/* reference count */ |
| 839 | 	uint32_t	pp_flags;		/* flags PMC_PP_* */ |
| 840 | 	struct proc	*pp_proc;		/* target process */ |
| 841 | 	struct pmc_targetstate pp_pmcs[]; /* NHWPMCs */ |
| 842 | }; |
| 843 | |
| 844 | #define	PMC_PP_ENABLE_MSR_ACCESS	0x00000001 |
| 845 | |
| 846 | /* |
| 847 | * struct pmc_owner |
| 848 | * |
| 849 | * We associate a PMC with an 'owner' process. |
| 850 | * |
| 851 | * A process can be associated with 0..NCPUS*NHWPMC PMCs during its |
| 852 | * lifetime, where NCPUS is the numbers of CPUS in the system and |
| 853 | * NHWPMC is the number of hardware PMCs per CPU. These are |
| 854 | * maintained in the list headed by the 'po_pmcs' to save on space. |
| 855 | * |
| 856 | */ |
| 857 | |
| 858 | struct pmc_owner { |
| 859 | 	LIST_ENTRY(pmc_owner)	po_next;	/* hash chain */ |
| 860 | 	CK_LIST_ENTRY(pmc_owner)	po_ssnext;	/* (g/p) list of SS PMC owners */ |
| 861 | 	LIST_HEAD(, pmc)	po_pmcs;	/* owned PMC list */ |
| 862 | 	TAILQ_HEAD(, pmclog_buffer) po_logbuffers; /* (o) logbuffer list */ |
| 863 | 	struct mtx		po_mtx;		/* spin lock for (o) */ |
| 864 | 	struct proc		*po_owner;	/* owner proc */ |
| 865 | 	uint32_t		po_flags;	/* (k) flags PMC_PO_* */ |
| 866 | 	struct proc		*po_kthread;	/* (k) helper kthread */ |
| 867 | 	struct file		*po_file;	/* file reference */ |
| 868 | 	int			po_error;	/* recorded error */ |
| 869 | 	short			po_sscount;	/* # SS PMCs owned */ |
| 870 | 	short			po_logprocmaps;	/* global mappings done */ |
| 871 | 	struct pmclog_buffer	*po_curbuf[MAXCPU];	/* current log buffer */ |
| 872 | }; |
| 873 | |
| 874 | #define	PMC_PO_OWNS_LOGFILE		0x00000001 /* has a log file */ |
| 875 | #define	PMC_PO_SHUTDOWN			0x00000010 /* in the process of shutdown */ |
| 876 | #define	PMC_PO_INITIAL_MAPPINGS_DONE	0x00000020 |
| 877 | |
| 878 | /* |
| 879 | * struct pmc_hw -- describe the state of the PMC hardware |
| 880 | * |
| 881 | * When in use, a HW PMC is associated with one allocated 'struct pmc' |
| 882 | * pointed to by field 'phw_pmc'. When inactive, this field is NULL. |
| 883 | * |
| 884 | * On an SMP box, one or more HW PMC's in process virtual mode with |
| 885 | * the same 'phw_pmc' could be executing on different CPUs. In order |
| 886 | * to handle this case correctly, we need to ensure that only |
| 887 | * incremental counts get added to the saved value in the associated |
| 888 | * 'struct pmc'. The 'phw_save' field is used to keep the saved PMC |
| 889 | * value at the time the hardware is started during this context |
| 890 | * switch (i.e., the difference between the new (hardware) count and |
| 891 | * the saved count is atomically added to the count field in 'struct |
| 892 | * pmc' at context switch time). |
| 893 | * |
| 894 | */ |
| 895 | |
| 896 | struct pmc_hw { |
| 897 | 	uint32_t	phw_state;	/* see PHW_* macros below */ |
| 898 | 	struct pmc	*phw_pmc;	/* current thread PMC */ |
| 899 | }; |
| 900 | |
| 901 | #define	PMC_PHW_RI_MASK		0x000000FF |
| 902 | #define	PMC_PHW_CPU_SHIFT	8 |
| 903 | #define	PMC_PHW_CPU_MASK	0x0000FF00 |
| 904 | #define	PMC_PHW_FLAGS_SHIFT	16 |
| 905 | #define	PMC_PHW_FLAGS_MASK	0xFFFF0000 |
| 906 | |
| 907 | #define	PMC_PHW_INDEX_TO_STATE(ri)	((ri) & PMC_PHW_RI_MASK) |
| 908 | #define	PMC_PHW_STATE_TO_INDEX(state)	((state) & PMC_PHW_RI_MASK) |
| 909 | #define	PMC_PHW_CPU_TO_STATE(cpu)	(((cpu) << PMC_PHW_CPU_SHIFT) & \ |
| 910 | 	PMC_PHW_CPU_MASK) |
| 911 | #define	PMC_PHW_STATE_TO_CPU(state)	(((state) & PMC_PHW_CPU_MASK) >> \ |
| 912 | 	PMC_PHW_CPU_SHIFT) |
| 913 | #define	PMC_PHW_FLAGS_TO_STATE(flags)	(((flags) << PMC_PHW_FLAGS_SHIFT) & \ |
| 914 | 	PMC_PHW_FLAGS_MASK) |
| 915 | #define	PMC_PHW_STATE_TO_FLAGS(state)	(((state) & PMC_PHW_FLAGS_MASK) >> \ |
| 916 | 	PMC_PHW_FLAGS_SHIFT) |
| 917 | #define	PMC_PHW_FLAG_IS_ENABLED		(PMC_PHW_FLAGS_TO_STATE(0x01)) |
| 918 | #define	PMC_PHW_FLAG_IS_SHAREABLE	(PMC_PHW_FLAGS_TO_STATE(0x02)) |
| 919 | |
| 920 | /* |
| 921 | * struct pmc_sample |
| 922 | * |
| 923 | * Space for N (tunable) PC samples and associated control data. |
| 924 | */ |
| 925 | |
| 926 | struct pmc_sample { |
| 927 | 	uint16_t		ps_nsamples;	/* callchain depth */ |
| 928 | 	uint16_t		ps_nsamples_actual; |
| 929 | 	uint16_t		ps_cpu;		/* cpu number */ |
| 930 | 	uint16_t		ps_flags;	/* other flags */ |
| 931 | 	lwpid_t			ps_tid;		/* thread id */ |
| 932 | 	pid_t			ps_pid;		/* process PID or -1 */ |
| 933 | 	int		ps_ticks; /* ticks at sample time */ |
| 934 | 	/* pad */ |
| 935 | 	struct thread		*ps_td;		/* which thread */ |
| 936 | 	struct pmc		*ps_pmc;	/* interrupting PMC */ |
| 937 | 	uintptr_t		*ps_pc;		/* (const) callchain start */ |
| 938 | 	uint64_t		ps_tsc;		/* tsc value */ |
| 939 | }; |
| 940 | |
| 941 | #define 	PMC_SAMPLE_FREE		((uint16_t) 0) |
| 942 | #define 	PMC_USER_CALLCHAIN_PENDING	((uint16_t) 0xFFFF) |
| 943 | |
| 944 | struct pmc_samplebuffer { |
| 945 | 	volatile uint64_t		ps_prodidx; /* producer index */ |
| 946 | 	volatile uint64_t		ps_considx; /* consumer index */ |
| 947 | 	uintptr_t		*ps_callchains;	/* all saved call chains */ |
| 948 | 	struct pmc_sample	ps_samples[];	/* array of sample entries */ |
| 949 | }; |
| 950 | |
| 951 | #define PMC_CONS_SAMPLE(psb)					\ |
| 952 | 	(&(psb)->ps_samples[(psb)->ps_considx & pmc_sample_mask]) |
| 953 | |
| 954 | #define PMC_CONS_SAMPLE_OFF(psb, off)							\ |
| 955 | 	(&(psb)->ps_samples[(off) & pmc_sample_mask]) |
| 956 | |
| 957 | #define PMC_PROD_SAMPLE(psb)					\ |
| 958 | 	(&(psb)->ps_samples[(psb)->ps_prodidx & pmc_sample_mask]) |
| 959 | |
| 960 | /* |
| 961 | * struct pmc_cpustate |
| 962 | * |
| 963 | * A CPU is modelled as a collection of HW PMCs with space for additional |
| 964 | * flags. |
| 965 | */ |
| 966 | |
| 967 | struct pmc_cpu { |
| 968 | 	uint32_t	pc_state;	/* physical cpu number + flags */ |
| 969 | 	struct pmc_samplebuffer *pc_sb[3]; /* space for samples */ |
| 970 | 	struct pmc_hw	*pc_hwpmcs[];	/* 'npmc' pointers */ |
| 971 | }; |
| 972 | |
| 973 | #define	PMC_PCPU_CPU_MASK		0x000000FF |
| 974 | #define	PMC_PCPU_FLAGS_MASK		0xFFFFFF00 |
| 975 | #define	PMC_PCPU_FLAGS_SHIFT		8 |
| 976 | #define	PMC_PCPU_STATE_TO_CPU(S)	((S) & PMC_PCPU_CPU_MASK) |
| 977 | #define	PMC_PCPU_STATE_TO_FLAGS(S)	(((S) & PMC_PCPU_FLAGS_MASK) >> PMC_PCPU_FLAGS_SHIFT) |
| 978 | #define	PMC_PCPU_FLAGS_TO_STATE(F)	(((F) << PMC_PCPU_FLAGS_SHIFT) & PMC_PCPU_FLAGS_MASK) |
| 979 | #define	PMC_PCPU_CPU_TO_STATE(C)	((C) & PMC_PCPU_CPU_MASK) |
| 980 | #define	PMC_PCPU_FLAG_HTT		(PMC_PCPU_FLAGS_TO_STATE(0x1)) |
| 981 | |
| 982 | /* |
| 983 | * struct pmc_binding |
| 984 | * |
| 985 | * CPU binding information. |
| 986 | */ |
| 987 | |
| 988 | struct pmc_binding { |
| 989 | 	int	pb_bound;	/* is bound? */ |
| 990 | 	int	pb_cpu;		/* if so, to which CPU */ |
| 991 | 	u_char	pb_priority;	/* Thread active priority. */ |
| 992 | }; |
| 993 | |
| 994 | struct pmc_mdep; |
| 995 | |
| 996 | /* |
| 997 | * struct pmc_classdep |
| 998 | * |
| 999 | * PMC class-dependent operations. |
| 1000 | */ |
| 1001 | struct pmc_classdep { |
| 1002 | 	uint32_t	pcd_caps;	/* class capabilities */ |
| 1003 | 	enum pmc_class	pcd_class;	/* class id */ |
| 1004 | 	int		pcd_num;	/* number of PMCs */ |
| 1005 | 	int		pcd_ri;		/* row index of the first PMC in class */ |
| 1006 | 	int		pcd_width;	/* width of the PMC */ |
| 1007 | |
| 1008 | 	/* configuring/reading/writing the hardware PMCs */ |
| 1009 | 	int (*pcd_config_pmc)(int _cpu, int _ri, struct pmc *_pm); |
| 1010 | 	int (*pcd_get_config)(int _cpu, int _ri, struct pmc **_ppm); |
| 1011 | 	int (*pcd_read_pmc)(int _cpu, int _ri, struct pmc *_pm, |
| 1012 | 	 pmc_value_t *_value); |
| 1013 | 	int (*pcd_write_pmc)(int _cpu, int _ri, struct pmc *_pm, |
| 1014 | 	 pmc_value_t _value); |
| 1015 | |
| 1016 | 	/* pmc allocation/release */ |
| 1017 | 	int (*pcd_allocate_pmc)(int _cpu, int _ri, struct pmc *_t, |
| 1018 | 		const struct pmc_op_pmcallocate *_a); |
| 1019 | 	int (*pcd_release_pmc)(int _cpu, int _ri, struct pmc *_pm); |
| 1020 | |
| 1021 | 	/* starting and stopping PMCs */ |
| 1022 | 	int (*pcd_start_pmc)(int _cpu, int _ri, struct pmc *_pm); |
| 1023 | 	int (*pcd_stop_pmc)(int _cpu, int _ri, struct pmc *_pm); |
| 1024 | |
| 1025 | 	/* description */ |
| 1026 | 	int (*pcd_describe)(int _cpu, int _ri, struct pmc_info *_pi, |
| 1027 | 		struct pmc **_ppmc); |
| 1028 | |
| 1029 | 	/* class-dependent initialization & finalization */ |
| 1030 | 	int (*pcd_pcpu_init)(struct pmc_mdep *_md, int _cpu); |
| 1031 | 	int (*pcd_pcpu_fini)(struct pmc_mdep *_md, int _cpu); |
| 1032 | |
| 1033 | 	/* machine-specific interface */ |
| 1034 | 	int (*pcd_get_msr)(int _ri, uint32_t *_msr); |
| 1035 | }; |
| 1036 | |
| 1037 | /* |
| 1038 | * struct pmc_mdep |
| 1039 | * |
| 1040 | * Machine dependent bits needed per CPU type. |
| 1041 | */ |
| 1042 | |
| 1043 | struct pmc_mdep { |
| 1044 | 	uint32_t	pmd_cputype; /* from enum pmc_cputype */ |
| 1045 | 	uint32_t	pmd_npmc;	/* number of PMCs per CPU */ |
| 1046 | 	uint32_t	pmd_nclass;	/* number of PMC classes present */ |
| 1047 | |
| 1048 | 	/* |
| 1049 | 	 * Machine dependent methods. |
| 1050 | 	 */ |
| 1051 | |
| 1052 | 	/* thread context switch in/out */ |
| 1053 | 	int (*pmd_switch_in)(struct pmc_cpu *_p, struct pmc_process *_pp); |
| 1054 | 	int (*pmd_switch_out)(struct pmc_cpu *_p, struct pmc_process *_pp); |
| 1055 | |
| 1056 | 	/* handle a PMC interrupt */ |
| 1057 | 	int (*pmd_intr)(struct trapframe *_tf); |
| 1058 | |
| 1059 | 	/* |
| 1060 | 	 * PMC class dependent information. |
| 1061 | 	 */ |
| 1062 | 	struct pmc_classdep pmd_classdep[]; |
| 1063 | }; |
| 1064 | |
| 1065 | /* |
| 1066 | * Per-CPU state. This is an array of 'mp_ncpu' pointers |
| 1067 | * to struct pmc_cpu descriptors. |
| 1068 | */ |
| 1069 | |
| 1070 | extern struct pmc_cpu **pmc_pcpu; |
| 1071 | |
| 1072 | /* driver statistics */ |
| 1073 | extern struct pmc_driverstats pmc_stats; |
| 1074 | |
| 1075 | #if	defined(HWPMC_DEBUG) |
| 1076 | |
| 1077 | /* HWPMC_DEBUG without KTR will compile but is a no-op. */ |
| 1078 | #if !defined(KTR) || !defined(KTR_COMPILE) || ((KTR_COMPILE & KTR_SUBSYS) == 0) |
| 1079 | #error "HWPMC_DEBUG requires KTR and KTR_COMPILE=KTR_SUBSYS -- see ktr(4)" |
| 1080 | #endif |
| 1081 | |
| 1082 | #include <sys/ktr.h> |
| 1083 | |
| 1084 | #define	__pmcdbg_used		/* unused variable annotation */ |
| 1085 | |
| 1086 | /* |
| 1087 | * Debug flags, major flag groups. |
| 1088 | * |
| 1089 | * Please keep the DEBUGGING section of the hwpmc(4) man page in sync. |
| 1090 | */ |
| 1091 | struct pmc_debugflags { |
| 1092 | 	int	pdb_CPU; |
| 1093 | 	int	pdb_CSW; |
| 1094 | 	int	pdb_LOG; |
| 1095 | 	int	pdb_MDP; |
| 1096 | 	int	pdb_MOD; |
| 1097 | 	int	pdb_OWN; |
| 1098 | 	int	pdb_PMC; |
| 1099 | 	int	pdb_PRC; |
| 1100 | 	int	pdb_SAM; |
| 1101 | }; |
| 1102 | |
| 1103 | extern struct pmc_debugflags pmc_debugflags; |
| 1104 | |
| 1105 | #define	KTR_PMC			KTR_SUBSYS |
| 1106 | |
| 1107 | #define	PMC_DEBUG_STRSIZE		128 |
| 1108 | #define	PMC_DEBUG_DEFAULT_FLAGS		{ 0, 0, 0, 0, 0, 0, 0, 0, 0 } |
| 1109 | |
| 1110 | #define	PMCDBG0(M, N, L, F) do {					\ |
| 1111 | 	if (pmc_debugflags.pdb_ ## M & (1 << PMC_DEBUG_MIN_ ## N))	\ |
| 1112 | 		CTR0(KTR_PMC, #M ":" #N ":" #L ": " F);		\ |
| 1113 | } while (0) |
| 1114 | #define	PMCDBG1(M, N, L, F, p1) do {					\ |
| 1115 | 	if (pmc_debugflags.pdb_ ## M & (1 << PMC_DEBUG_MIN_ ## N))	\ |
| 1116 | 		CTR1(KTR_PMC, #M ":" #N ":" #L ": " F, p1);		\ |
| 1117 | } while (0) |
| 1118 | #define	PMCDBG2(M, N, L, F, p1, p2) do {				\ |
| 1119 | 	if (pmc_debugflags.pdb_ ## M & (1 << PMC_DEBUG_MIN_ ## N))	\ |
| 1120 | 		CTR2(KTR_PMC, #M ":" #N ":" #L ": " F, p1, p2);	\ |
| 1121 | } while (0) |
| 1122 | #define	PMCDBG3(M, N, L, F, p1, p2, p3) do {				\ |
| 1123 | 	if (pmc_debugflags.pdb_ ## M & (1 << PMC_DEBUG_MIN_ ## N))	\ |
| 1124 | 		CTR3(KTR_PMC, #M ":" #N ":" #L ": " F, p1, p2, p3);	\ |
| 1125 | } while (0) |
| 1126 | #define	PMCDBG4(M, N, L, F, p1, p2, p3, p4) do {			\ |
| 1127 | 	if (pmc_debugflags.pdb_ ## M & (1 << PMC_DEBUG_MIN_ ## N))	\ |
| 1128 | 		CTR4(KTR_PMC, #M ":" #N ":" #L ": " F, p1, p2, p3, p4);\ |
| 1129 | } while (0) |
| 1130 | #define	PMCDBG5(M, N, L, F, p1, p2, p3, p4, p5) do {			\ |
| 1131 | 	if (pmc_debugflags.pdb_ ## M & (1 << PMC_DEBUG_MIN_ ## N))	\ |
| 1132 | 		CTR5(KTR_PMC, #M ":" #N ":" #L ": " F, p1, p2, p3, p4,	\ |
| 1133 | 		 p5);						\ |
| 1134 | } while (0) |
| 1135 | #define	PMCDBG6(M, N, L, F, p1, p2, p3, p4, p5, p6) do {		\ |
| 1136 | 	if (pmc_debugflags.pdb_ ## M & (1 << PMC_DEBUG_MIN_ ## N))	\ |
| 1137 | 		CTR6(KTR_PMC, #M ":" #N ":" #L ": " F, p1, p2, p3, p4,	\ |
| 1138 | 		 p5, p6);						\ |
| 1139 | } while (0) |
| 1140 | |
| 1141 | /* Major numbers */ |
| 1142 | #define	PMC_DEBUG_MAJ_CPU		0 /* cpu switches */ |
| 1143 | #define	PMC_DEBUG_MAJ_CSW		1 /* context switches */ |
| 1144 | #define	PMC_DEBUG_MAJ_LOG		2 /* logging */ |
| 1145 | #define	PMC_DEBUG_MAJ_MDP		3 /* machine dependent */ |
| 1146 | #define	PMC_DEBUG_MAJ_MOD		4 /* misc module infrastructure */ |
| 1147 | #define	PMC_DEBUG_MAJ_OWN		5 /* owner */ |
| 1148 | #define	PMC_DEBUG_MAJ_PMC		6 /* pmc management */ |
| 1149 | #define	PMC_DEBUG_MAJ_PRC		7 /* processes */ |
| 1150 | #define	PMC_DEBUG_MAJ_SAM		8 /* sampling */ |
| 1151 | |
| 1152 | /* Minor numbers */ |
| 1153 | |
| 1154 | /* Common (8 bits) */ |
| 1155 | #define	PMC_DEBUG_MIN_ALL		0 /* allocation */ |
| 1156 | #define	PMC_DEBUG_MIN_REL		1 /* release */ |
| 1157 | #define	PMC_DEBUG_MIN_OPS		2 /* ops: start, stop, ... */ |
| 1158 | #define	PMC_DEBUG_MIN_INI		3 /* init */ |
| 1159 | #define	PMC_DEBUG_MIN_FND		4 /* find */ |
| 1160 | |
| 1161 | /* MODULE */ |
| 1162 | #define	PMC_DEBUG_MIN_PMH	 14 /* pmc_hook */ |
| 1163 | #define	PMC_DEBUG_MIN_PMS	 15 /* pmc_syscall */ |
| 1164 | |
| 1165 | /* OWN */ |
| 1166 | #define	PMC_DEBUG_MIN_ORM		8 /* owner remove */ |
| 1167 | #define	PMC_DEBUG_MIN_OMR		9 /* owner maybe remove */ |
| 1168 | |
| 1169 | /* PROCESSES */ |
| 1170 | #define	PMC_DEBUG_MIN_TLK		8 /* link target */ |
| 1171 | #define	PMC_DEBUG_MIN_TUL		9 /* unlink target */ |
| 1172 | #define	PMC_DEBUG_MIN_EXT	 10 /* process exit */ |
| 1173 | #define	PMC_DEBUG_MIN_EXC	 11 /* process exec */ |
| 1174 | #define	PMC_DEBUG_MIN_FRK	 12 /* process fork */ |
| 1175 | #define	PMC_DEBUG_MIN_ATT	 13 /* attach/detach */ |
| 1176 | #define	PMC_DEBUG_MIN_SIG	 14 /* signalling */ |
| 1177 | |
| 1178 | /* CONTEXT SWITCHES */ |
| 1179 | #define	PMC_DEBUG_MIN_SWI		8 /* switch in */ |
| 1180 | #define	PMC_DEBUG_MIN_SWO		9 /* switch out */ |
| 1181 | |
| 1182 | /* PMC */ |
| 1183 | #define	PMC_DEBUG_MIN_REG		8 /* pmc register */ |
| 1184 | #define	PMC_DEBUG_MIN_ALR		9 /* allocate row */ |
| 1185 | |
| 1186 | /* MACHINE DEPENDENT LAYER */ |
| 1187 | #define	PMC_DEBUG_MIN_REA		8 /* read */ |
| 1188 | #define	PMC_DEBUG_MIN_WRI		9 /* write */ |
| 1189 | #define	PMC_DEBUG_MIN_CFG	 10 /* config */ |
| 1190 | #define	PMC_DEBUG_MIN_STA	 11 /* start */ |
| 1191 | #define	PMC_DEBUG_MIN_STO	 12 /* stop */ |
| 1192 | #define	PMC_DEBUG_MIN_INT	 13 /* interrupts */ |
| 1193 | |
| 1194 | /* CPU */ |
| 1195 | #define	PMC_DEBUG_MIN_BND		8 /* bind */ |
| 1196 | #define	PMC_DEBUG_MIN_SEL		9 /* select */ |
| 1197 | |
| 1198 | /* LOG */ |
| 1199 | #define	PMC_DEBUG_MIN_GTB		8 /* get buf */ |
| 1200 | #define	PMC_DEBUG_MIN_SIO		9 /* schedule i/o */ |
| 1201 | #define	PMC_DEBUG_MIN_FLS	 10 /* flush */ |
| 1202 | #define	PMC_DEBUG_MIN_SAM	 11 /* sample */ |
| 1203 | #define	PMC_DEBUG_MIN_CLO	 12 /* close */ |
| 1204 | |
| 1205 | #else |
| 1206 | #define	__pmcdbg_used			__unused |
| 1207 | #define	PMCDBG0(M, N, L, F)		/* nothing */ |
| 1208 | #define	PMCDBG1(M, N, L, F, p1) |
| 1209 | #define	PMCDBG2(M, N, L, F, p1, p2) |
| 1210 | #define	PMCDBG3(M, N, L, F, p1, p2, p3) |
| 1211 | #define	PMCDBG4(M, N, L, F, p1, p2, p3, p4) |
| 1212 | #define	PMCDBG5(M, N, L, F, p1, p2, p3, p4, p5) |
| 1213 | #define	PMCDBG6(M, N, L, F, p1, p2, p3, p4, p5, p6) |
| 1214 | #endif |
| 1215 | |
| 1216 | /* declare a dedicated memory pool */ |
| 1217 | MALLOC_DECLARE(M_PMC); |
| 1218 | |
| 1219 | /* |
| 1220 | * Functions |
| 1221 | */ |
| 1222 | |
| 1223 | struct pmc_mdep *pmc_md_initialize(void);	/* MD init function */ |
| 1224 | void	pmc_md_finalize(struct pmc_mdep *_md);	/* MD fini function */ |
| 1225 | int	pmc_getrowdisp(int _ri); |
| 1226 | int	pmc_process_interrupt(int _ring, struct pmc *_pm, struct trapframe *_tf); |
| 1227 | int	pmc_save_kernel_callchain(uintptr_t *_cc, int _maxsamples, |
| 1228 | struct trapframe *_tf); |
| 1229 | int	pmc_save_user_callchain(uintptr_t *_cc, int _maxsamples, |
| 1230 | struct trapframe *_tf); |
| 1231 | void	pmc_restore_cpu_binding(struct pmc_binding *pb); |
| 1232 | void	pmc_save_cpu_binding(struct pmc_binding *pb); |
| 1233 | void	pmc_select_cpu(int cpu); |
| 1234 | struct pmc_mdep *pmc_mdep_alloc(int nclasses); |
| 1235 | void pmc_mdep_free(struct pmc_mdep *md); |
| 1236 | uint64_t pmc_rdtsc(void); |
| 1237 | #endif /* _KERNEL */ |
| 1238 | #endif /* _SYS_PMC_H_ */ |