1ebccf1e3SJoseph Koshy /*- 28a36da99SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 38a36da99SPedro F. Giffuni * 4122ccdc1SJoseph Koshy * Copyright (c) 2003-2008 Joseph Koshy 5d07f36b0SJoseph Koshy * Copyright (c) 2007 The FreeBSD Foundation 6d07f36b0SJoseph Koshy * All rights reserved. 7d07f36b0SJoseph Koshy * 8d07f36b0SJoseph Koshy * Portions of this software were developed by A. Joseph Koshy under 9d07f36b0SJoseph Koshy * sponsorship from the FreeBSD Foundation and Google, Inc. 10ebccf1e3SJoseph Koshy * 11ebccf1e3SJoseph Koshy * Redistribution and use in source and binary forms, with or without 12ebccf1e3SJoseph Koshy * modification, are permitted provided that the following conditions 13ebccf1e3SJoseph Koshy * are met: 14ebccf1e3SJoseph Koshy * 1. Redistributions of source code must retain the above copyright 15ebccf1e3SJoseph Koshy * notice, this list of conditions and the following disclaimer. 16ebccf1e3SJoseph Koshy * 2. Redistributions in binary form must reproduce the above copyright 17ebccf1e3SJoseph Koshy * notice, this list of conditions and the following disclaimer in the 18ebccf1e3SJoseph Koshy * documentation and/or other materials provided with the distribution. 19ebccf1e3SJoseph Koshy * 20ebccf1e3SJoseph Koshy * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 21ebccf1e3SJoseph Koshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22ebccf1e3SJoseph Koshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23ebccf1e3SJoseph Koshy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 24ebccf1e3SJoseph Koshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25ebccf1e3SJoseph Koshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26ebccf1e3SJoseph Koshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27ebccf1e3SJoseph Koshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28ebccf1e3SJoseph Koshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29ebccf1e3SJoseph Koshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30ebccf1e3SJoseph Koshy * SUCH DAMAGE. 31ebccf1e3SJoseph Koshy */ 32ebccf1e3SJoseph Koshy 33ebccf1e3SJoseph Koshy #include <sys/cdefs.h> 34ebccf1e3SJoseph Koshy __FBSDID("$FreeBSD$"); 35ebccf1e3SJoseph Koshy 36fadcc6e2SJoseph Koshy #include "opt_hwpmc_hooks.h" 37fadcc6e2SJoseph Koshy 38fadcc6e2SJoseph Koshy #include <sys/types.h> 39f5f9340bSFabien Thomas #include <sys/ctype.h> 40f5f9340bSFabien Thomas #include <sys/param.h> 41f5f9340bSFabien Thomas #include <sys/malloc.h> 42f5f9340bSFabien Thomas #include <sys/kernel.h> 43f5f9340bSFabien Thomas #include <sys/lock.h> 44f5f9340bSFabien Thomas #include <sys/mutex.h> 45fadcc6e2SJoseph Koshy #include <sys/pmc.h> 46ebccf1e3SJoseph Koshy #include <sys/pmckern.h> 47ebccf1e3SJoseph Koshy #include <sys/smp.h> 48de5b1952SAlexander Leidinger #include <sys/sysctl.h> 49f5f9340bSFabien Thomas #include <sys/systm.h> 50ebccf1e3SJoseph Koshy 510f00315cSMatt Macy #include <vm/vm.h> 520f00315cSMatt Macy #include <vm/vm_extern.h> 530f00315cSMatt Macy #include <vm/vm_kern.h> 540f00315cSMatt Macy 55f4e98881SRuslan Ermilov #ifdef HWPMC_HOOKS 56de5b1952SAlexander Leidinger FEATURE(hwpmc_hooks, "Kernel support for HW PMC"); 57fadcc6e2SJoseph Koshy #define PMC_KERNEL_VERSION PMC_VERSION 58fadcc6e2SJoseph Koshy #else 59fadcc6e2SJoseph Koshy #define PMC_KERNEL_VERSION 0 60fadcc6e2SJoseph Koshy #endif 61fadcc6e2SJoseph Koshy 62f5f9340bSFabien Thomas MALLOC_DECLARE(M_PMCHOOKS); 63f5f9340bSFabien Thomas MALLOC_DEFINE(M_PMCHOOKS, "pmchooks", "Memory space for PMC hooks"); 64f5f9340bSFabien Thomas 650f00315cSMatt Macy /* memory pool */ 660f00315cSMatt Macy MALLOC_DEFINE(M_PMC, "pmc", "Memory space for the PMC module"); 670f00315cSMatt Macy 68fadcc6e2SJoseph Koshy const int pmc_kernel_version = PMC_KERNEL_VERSION; 69ebccf1e3SJoseph Koshy 70ebccf1e3SJoseph Koshy /* Hook variable. */ 7195839d3dSMateusz Guzik int __read_mostly (*pmc_hook)(struct thread *td, int function, void *arg) = NULL; 72ebccf1e3SJoseph Koshy 73ebccf1e3SJoseph Koshy /* Interrupt handler */ 74*eb7c9019SMatt Macy int __read_mostly (*pmc_intr)(struct trapframe *tf) = NULL; 7536c0fd9dSJoseph Koshy 76e6b475e0SMatt Macy DPCPU_DEFINE(uint8_t, pmc_sampled); 77f263522aSJoseph Koshy 78f263522aSJoseph Koshy /* 79f263522aSJoseph Koshy * A global count of SS mode PMCs. When non-zero, this means that 80f263522aSJoseph Koshy * we have processes that are sampling the system as a whole. 81f263522aSJoseph Koshy */ 82f263522aSJoseph Koshy volatile int pmc_ss_count; 83ebccf1e3SJoseph Koshy 84ebccf1e3SJoseph Koshy /* 85ebccf1e3SJoseph Koshy * Since PMC(4) may not be loaded in the current kernel, the 86ebccf1e3SJoseph Koshy * convention followed is that a non-NULL value of 'pmc_hook' implies 87ebccf1e3SJoseph Koshy * the presence of this kernel module. 88ebccf1e3SJoseph Koshy * 89ebccf1e3SJoseph Koshy * This requires us to protect 'pmc_hook' with a 90ebccf1e3SJoseph Koshy * shared (sx) lock -- thus making the process of calling into PMC(4) 91ebccf1e3SJoseph Koshy * somewhat more expensive than a simple 'if' check and indirect call. 92ebccf1e3SJoseph Koshy */ 93fadcc6e2SJoseph Koshy struct sx pmc_sx; 940f00315cSMatt Macy SX_SYSINIT(pmcsx, &pmc_sx, "pmc-sx"); 95d07f36b0SJoseph Koshy 96f5f9340bSFabien Thomas /* 97f5f9340bSFabien Thomas * PMC Soft per cpu trapframe. 98f5f9340bSFabien Thomas */ 99f5f9340bSFabien Thomas struct trapframe pmc_tf[MAXCPU]; 100f5f9340bSFabien Thomas 101f5f9340bSFabien Thomas /* 1020f00315cSMatt Macy * Per domain list of buffer headers 1030f00315cSMatt Macy */ 1040f00315cSMatt Macy __read_mostly struct pmc_domain_buffer_header *pmc_dom_hdrs[MAXMEMDOM]; 1050f00315cSMatt Macy 1060f00315cSMatt Macy /* 107f5f9340bSFabien Thomas * PMC Soft use a global table to store registered events. 108f5f9340bSFabien Thomas */ 109f5f9340bSFabien Thomas 110f5f9340bSFabien Thomas SYSCTL_NODE(_kern, OID_AUTO, hwpmc, CTLFLAG_RW, 0, "HWPMC parameters"); 111f5f9340bSFabien Thomas 112f5f9340bSFabien Thomas static int pmc_softevents = 16; 113af3b2549SHans Petter Selasky SYSCTL_INT(_kern_hwpmc, OID_AUTO, softevents, CTLFLAG_RDTUN, 114f5f9340bSFabien Thomas &pmc_softevents, 0, "maximum number of soft events"); 115f5f9340bSFabien Thomas 116f5f9340bSFabien Thomas int pmc_softs_count; 117f5f9340bSFabien Thomas struct pmc_soft **pmc_softs; 118f5f9340bSFabien Thomas 1190f00315cSMatt Macy struct mtx pmc_softs_mtx; 120f5f9340bSFabien Thomas MTX_SYSINIT(pmc_soft_mtx, &pmc_softs_mtx, "pmc-softs", MTX_SPIN); 121f5f9340bSFabien Thomas 122ebccf1e3SJoseph Koshy /* 123122ccdc1SJoseph Koshy * Helper functions. 124122ccdc1SJoseph Koshy */ 125122ccdc1SJoseph Koshy 126122ccdc1SJoseph Koshy /* 127122ccdc1SJoseph Koshy * A note on the CPU numbering scheme used by the hwpmc(4) driver. 128122ccdc1SJoseph Koshy * 129122ccdc1SJoseph Koshy * CPUs are denoted using numbers in the range 0..[pmc_cpu_max()-1]. 130122ccdc1SJoseph Koshy * CPUs could be numbered "sparsely" in this range; the predicate 131122ccdc1SJoseph Koshy * `pmc_cpu_is_present()' is used to test whether a given CPU is 132122ccdc1SJoseph Koshy * physically present. 133122ccdc1SJoseph Koshy * 134122ccdc1SJoseph Koshy * Further, a CPU that is physically present may be administratively 135122ccdc1SJoseph Koshy * disabled or otherwise unavailable for use by hwpmc(4). The 136122ccdc1SJoseph Koshy * `pmc_cpu_is_active()' predicate tests for CPU usability. An 137122ccdc1SJoseph Koshy * "active" CPU participates in thread scheduling and can field 138122ccdc1SJoseph Koshy * interrupts raised by PMC hardware. 139122ccdc1SJoseph Koshy * 140122ccdc1SJoseph Koshy * On systems with hyperthreaded CPUs, multiple logical CPUs may share 141122ccdc1SJoseph Koshy * PMC hardware resources. For such processors one logical CPU is 142122ccdc1SJoseph Koshy * denoted as the primary owner of the in-CPU PMC resources. The 143122ccdc1SJoseph Koshy * pmc_cpu_is_primary() predicate is used to distinguish this primary 144122ccdc1SJoseph Koshy * CPU from the others. 145ebccf1e3SJoseph Koshy */ 146ebccf1e3SJoseph Koshy 147ebccf1e3SJoseph Koshy int 148122ccdc1SJoseph Koshy pmc_cpu_is_active(int cpu) 149ebccf1e3SJoseph Koshy { 150ebccf1e3SJoseph Koshy #ifdef SMP 151122ccdc1SJoseph Koshy return (pmc_cpu_is_present(cpu) && 15271a19bdcSAttilio Rao !CPU_ISSET(cpu, &hlt_cpus_mask)); 153ebccf1e3SJoseph Koshy #else 154122ccdc1SJoseph Koshy return (1); 155122ccdc1SJoseph Koshy #endif 156122ccdc1SJoseph Koshy } 157122ccdc1SJoseph Koshy 158122ccdc1SJoseph Koshy /* Deprecated. */ 159122ccdc1SJoseph Koshy int 160122ccdc1SJoseph Koshy pmc_cpu_is_disabled(int cpu) 161122ccdc1SJoseph Koshy { 162122ccdc1SJoseph Koshy return (!pmc_cpu_is_active(cpu)); 163122ccdc1SJoseph Koshy } 164122ccdc1SJoseph Koshy 165122ccdc1SJoseph Koshy int 166122ccdc1SJoseph Koshy pmc_cpu_is_present(int cpu) 167122ccdc1SJoseph Koshy { 168122ccdc1SJoseph Koshy #ifdef SMP 169122ccdc1SJoseph Koshy return (!CPU_ABSENT(cpu)); 170122ccdc1SJoseph Koshy #else 171122ccdc1SJoseph Koshy return (1); 172ebccf1e3SJoseph Koshy #endif 173ebccf1e3SJoseph Koshy } 174ebccf1e3SJoseph Koshy 175ebccf1e3SJoseph Koshy int 176122ccdc1SJoseph Koshy pmc_cpu_is_primary(int cpu) 177ebccf1e3SJoseph Koshy { 178ebccf1e3SJoseph Koshy #ifdef SMP 17971a19bdcSAttilio Rao return (!CPU_ISSET(cpu, &logical_cpus_mask)); 180ebccf1e3SJoseph Koshy #else 181122ccdc1SJoseph Koshy return (1); 182ebccf1e3SJoseph Koshy #endif 183ebccf1e3SJoseph Koshy } 184122ccdc1SJoseph Koshy 185122ccdc1SJoseph Koshy 186122ccdc1SJoseph Koshy /* 187122ccdc1SJoseph Koshy * Return the maximum CPU number supported by the system. The return 188122ccdc1SJoseph Koshy * value is used for scaling internal data structures and for runtime 189122ccdc1SJoseph Koshy * checks. 190122ccdc1SJoseph Koshy */ 191122ccdc1SJoseph Koshy unsigned int 192122ccdc1SJoseph Koshy pmc_cpu_max(void) 193122ccdc1SJoseph Koshy { 194122ccdc1SJoseph Koshy #ifdef SMP 195122ccdc1SJoseph Koshy return (mp_maxid+1); 196122ccdc1SJoseph Koshy #else 197122ccdc1SJoseph Koshy return (1); 198122ccdc1SJoseph Koshy #endif 199122ccdc1SJoseph Koshy } 200122ccdc1SJoseph Koshy 201122ccdc1SJoseph Koshy #ifdef INVARIANTS 202122ccdc1SJoseph Koshy 203122ccdc1SJoseph Koshy /* 204122ccdc1SJoseph Koshy * Return the count of CPUs in the `active' state in the system. 205122ccdc1SJoseph Koshy */ 206122ccdc1SJoseph Koshy int 207122ccdc1SJoseph Koshy pmc_cpu_max_active(void) 208122ccdc1SJoseph Koshy { 209122ccdc1SJoseph Koshy #ifdef SMP 210122ccdc1SJoseph Koshy /* 211122ccdc1SJoseph Koshy * When support for CPU hot-plugging is added to the kernel, 212122ccdc1SJoseph Koshy * this function would change to return the current number 213122ccdc1SJoseph Koshy * of "active" CPUs. 214122ccdc1SJoseph Koshy */ 215122ccdc1SJoseph Koshy return (mp_ncpus); 216122ccdc1SJoseph Koshy #else 217122ccdc1SJoseph Koshy return (1); 218122ccdc1SJoseph Koshy #endif 219122ccdc1SJoseph Koshy } 220122ccdc1SJoseph Koshy 221122ccdc1SJoseph Koshy #endif 222f5f9340bSFabien Thomas 223f5f9340bSFabien Thomas /* 224f5f9340bSFabien Thomas * Cleanup event name: 225f5f9340bSFabien Thomas * - remove duplicate '_' 226f5f9340bSFabien Thomas * - all uppercase 227f5f9340bSFabien Thomas */ 228f5f9340bSFabien Thomas static void 229f5f9340bSFabien Thomas pmc_soft_namecleanup(char *name) 230f5f9340bSFabien Thomas { 231f5f9340bSFabien Thomas char *p, *q; 232f5f9340bSFabien Thomas 233f5f9340bSFabien Thomas p = q = name; 234f5f9340bSFabien Thomas 235f5f9340bSFabien Thomas for ( ; *p == '_' ; p++) 236f5f9340bSFabien Thomas ; 237f5f9340bSFabien Thomas for ( ; *p ; p++) { 238f5f9340bSFabien Thomas if (*p == '_' && (*(p + 1) == '_' || *(p + 1) == '\0')) 239f5f9340bSFabien Thomas continue; 240f5f9340bSFabien Thomas else 241f5f9340bSFabien Thomas *q++ = toupper(*p); 242f5f9340bSFabien Thomas } 243f5f9340bSFabien Thomas *q = '\0'; 244f5f9340bSFabien Thomas } 245f5f9340bSFabien Thomas 246f5f9340bSFabien Thomas void 247f5f9340bSFabien Thomas pmc_soft_ev_register(struct pmc_soft *ps) 248f5f9340bSFabien Thomas { 249f5f9340bSFabien Thomas static int warned = 0; 250f5f9340bSFabien Thomas int n; 251f5f9340bSFabien Thomas 252f5f9340bSFabien Thomas ps->ps_running = 0; 253f5f9340bSFabien Thomas ps->ps_ev.pm_ev_code = 0; /* invalid */ 254f5f9340bSFabien Thomas pmc_soft_namecleanup(ps->ps_ev.pm_ev_name); 255f5f9340bSFabien Thomas 256f5f9340bSFabien Thomas mtx_lock_spin(&pmc_softs_mtx); 257f5f9340bSFabien Thomas 258f5f9340bSFabien Thomas if (pmc_softs_count >= pmc_softevents) { 259f5f9340bSFabien Thomas /* 260f5f9340bSFabien Thomas * XXX Reusing events can enter a race condition where 261f5f9340bSFabien Thomas * new allocated event will be used as an old one. 262f5f9340bSFabien Thomas */ 263f5f9340bSFabien Thomas for (n = 0; n < pmc_softevents; n++) 264f5f9340bSFabien Thomas if (pmc_softs[n] == NULL) 265f5f9340bSFabien Thomas break; 266f5f9340bSFabien Thomas if (n == pmc_softevents) { 267f5f9340bSFabien Thomas mtx_unlock_spin(&pmc_softs_mtx); 268f5f9340bSFabien Thomas if (!warned) { 269f5f9340bSFabien Thomas printf("hwpmc: too many soft events, " 270f5f9340bSFabien Thomas "increase kern.hwpmc.softevents tunable\n"); 271f5f9340bSFabien Thomas warned = 1; 272f5f9340bSFabien Thomas } 273f5f9340bSFabien Thomas return; 274f5f9340bSFabien Thomas } 275f5f9340bSFabien Thomas 276f5f9340bSFabien Thomas ps->ps_ev.pm_ev_code = PMC_EV_SOFT_FIRST + n; 277f5f9340bSFabien Thomas pmc_softs[n] = ps; 278f5f9340bSFabien Thomas } else { 279f5f9340bSFabien Thomas ps->ps_ev.pm_ev_code = PMC_EV_SOFT_FIRST + pmc_softs_count; 280f5f9340bSFabien Thomas pmc_softs[pmc_softs_count++] = ps; 281f5f9340bSFabien Thomas } 282f5f9340bSFabien Thomas 283f5f9340bSFabien Thomas mtx_unlock_spin(&pmc_softs_mtx); 284f5f9340bSFabien Thomas } 285f5f9340bSFabien Thomas 286f5f9340bSFabien Thomas void 287f5f9340bSFabien Thomas pmc_soft_ev_deregister(struct pmc_soft *ps) 288f5f9340bSFabien Thomas { 289f5f9340bSFabien Thomas 290f5f9340bSFabien Thomas KASSERT(ps != NULL, ("pmc_soft_deregister: called with NULL")); 291f5f9340bSFabien Thomas 292f5f9340bSFabien Thomas mtx_lock_spin(&pmc_softs_mtx); 293f5f9340bSFabien Thomas 294f5f9340bSFabien Thomas if (ps->ps_ev.pm_ev_code != 0 && 295f5f9340bSFabien Thomas (ps->ps_ev.pm_ev_code - PMC_EV_SOFT_FIRST) < pmc_softevents) { 296bbf6e514SWarner Losh KASSERT((int)ps->ps_ev.pm_ev_code >= PMC_EV_SOFT_FIRST && 297bbf6e514SWarner Losh (int)ps->ps_ev.pm_ev_code <= PMC_EV_SOFT_LAST, 298f5f9340bSFabien Thomas ("pmc_soft_deregister: invalid event value")); 299f5f9340bSFabien Thomas pmc_softs[ps->ps_ev.pm_ev_code - PMC_EV_SOFT_FIRST] = NULL; 300f5f9340bSFabien Thomas } 301f5f9340bSFabien Thomas 302f5f9340bSFabien Thomas mtx_unlock_spin(&pmc_softs_mtx); 303f5f9340bSFabien Thomas } 304f5f9340bSFabien Thomas 305f5f9340bSFabien Thomas struct pmc_soft * 306f5f9340bSFabien Thomas pmc_soft_ev_acquire(enum pmc_event ev) 307f5f9340bSFabien Thomas { 308f5f9340bSFabien Thomas struct pmc_soft *ps; 309f5f9340bSFabien Thomas 310f5f9340bSFabien Thomas if (ev == 0 || (ev - PMC_EV_SOFT_FIRST) >= pmc_softevents) 311f5f9340bSFabien Thomas return NULL; 312f5f9340bSFabien Thomas 313bbf6e514SWarner Losh KASSERT((int)ev >= PMC_EV_SOFT_FIRST && 314bbf6e514SWarner Losh (int)ev <= PMC_EV_SOFT_LAST, 315f5f9340bSFabien Thomas ("event out of range")); 316f5f9340bSFabien Thomas 317f5f9340bSFabien Thomas mtx_lock_spin(&pmc_softs_mtx); 318f5f9340bSFabien Thomas 319f5f9340bSFabien Thomas ps = pmc_softs[ev - PMC_EV_SOFT_FIRST]; 320f5f9340bSFabien Thomas if (ps == NULL) 321f5f9340bSFabien Thomas mtx_unlock_spin(&pmc_softs_mtx); 322f5f9340bSFabien Thomas 323f5f9340bSFabien Thomas return ps; 324f5f9340bSFabien Thomas } 325f5f9340bSFabien Thomas 326f5f9340bSFabien Thomas void 327f5f9340bSFabien Thomas pmc_soft_ev_release(struct pmc_soft *ps) 328f5f9340bSFabien Thomas { 329f5f9340bSFabien Thomas 330f5f9340bSFabien Thomas mtx_unlock_spin(&pmc_softs_mtx); 331f5f9340bSFabien Thomas } 332f5f9340bSFabien Thomas 3330f00315cSMatt Macy #ifdef NUMA 3340f00315cSMatt Macy #define NDOMAINS vm_ndomains 3350f00315cSMatt Macy 3360f00315cSMatt Macy static int 3370f00315cSMatt Macy getdomain(int cpu) 3380f00315cSMatt Macy { 3390f00315cSMatt Macy struct pcpu *pc; 3400f00315cSMatt Macy 3410f00315cSMatt Macy pc = pcpu_find(cpu); 3420f00315cSMatt Macy return (pc->pc_domain); 3430f00315cSMatt Macy } 3440f00315cSMatt Macy #else 3450f00315cSMatt Macy #define NDOMAINS 1 3460f00315cSMatt Macy #define malloc_domain(size, type, domain, flags) malloc((size), (type), (flags)) 3470f00315cSMatt Macy #define getdomain(cpu) 0 3480f00315cSMatt Macy #endif 349f5f9340bSFabien Thomas /* 350f5f9340bSFabien Thomas * Initialise hwpmc. 351f5f9340bSFabien Thomas */ 352f5f9340bSFabien Thomas static void 353f5f9340bSFabien Thomas init_hwpmc(void *dummy __unused) 354f5f9340bSFabien Thomas { 3550f00315cSMatt Macy int domain, cpu; 3560f00315cSMatt Macy 357f5f9340bSFabien Thomas if (pmc_softevents <= 0 || 358f5f9340bSFabien Thomas pmc_softevents > PMC_EV_DYN_COUNT) { 359f5f9340bSFabien Thomas (void) printf("hwpmc: tunable \"softevents\"=%d out of " 360f5f9340bSFabien Thomas "range.\n", pmc_softevents); 361f5f9340bSFabien Thomas pmc_softevents = PMC_EV_DYN_COUNT; 362f5f9340bSFabien Thomas } 363ac2fffa4SPedro F. Giffuni pmc_softs = malloc(pmc_softevents * sizeof(struct pmc_soft *), M_PMCHOOKS, M_NOWAIT|M_ZERO); 364f5f9340bSFabien Thomas KASSERT(pmc_softs != NULL, ("cannot allocate soft events table")); 3650f00315cSMatt Macy 3660f00315cSMatt Macy for (domain = 0; domain < NDOMAINS; domain++) { 3670f00315cSMatt Macy pmc_dom_hdrs[domain] = malloc_domain(sizeof(struct pmc_domain_buffer_header), M_PMC, domain, 3680f00315cSMatt Macy M_WAITOK|M_ZERO); 3690f00315cSMatt Macy mtx_init(&pmc_dom_hdrs[domain]->pdbh_mtx, "pmc_bufferlist_mtx", "pmc-leaf", MTX_SPIN); 3700f00315cSMatt Macy TAILQ_INIT(&pmc_dom_hdrs[domain]->pdbh_head); 3710f00315cSMatt Macy } 3720f00315cSMatt Macy CPU_FOREACH(cpu) { 3730f00315cSMatt Macy domain = getdomain(cpu); 3740f00315cSMatt Macy KASSERT(pmc_dom_hdrs[domain] != NULL, ("no mem allocated for domain: %d", domain)); 3750f00315cSMatt Macy pmc_dom_hdrs[domain]->pdbh_ncpus++; 3760f00315cSMatt Macy } 3770f00315cSMatt Macy 378f5f9340bSFabien Thomas } 379f5f9340bSFabien Thomas 380f5f9340bSFabien Thomas SYSINIT(hwpmc, SI_SUB_KDTRACE, SI_ORDER_FIRST, init_hwpmc, NULL); 381f5f9340bSFabien Thomas 382