31 #include <sys/cdefs.h>
34 #include "opt_hwpmc_hooks.h"
36 #include <sys/types.h>
37 #include <sys/ctype.h>
38 #include <sys/param.h>
39 #include <sys/malloc.h>
40 #include <sys/kernel.h>
42 #include <sys/mutex.h>
44 #include <sys/pmckern.h>
46 #include <sys/sysctl.h>
47 #include <sys/systm.h>
50 FEATURE(hwpmc_hooks,
"Kernel support for HW PMC");
51 #define PMC_KERNEL_VERSION PMC_VERSION
53 #define PMC_KERNEL_VERSION 0
57 MALLOC_DEFINE(M_PMCHOOKS,
"pmchooks",
"Memory space for PMC hooks");
62 int (*
pmc_hook)(
struct thread *td,
int function,
void *arg) = NULL;
65 int (*
pmc_intr)(
int cpu,
struct trapframe *tf) = NULL;
96 SYSCTL_NODE(_kern, OID_AUTO, hwpmc, CTLFLAG_RW, 0,
"HWPMC parameters");
100 SYSCTL_INT(_kern_hwpmc, OID_AUTO, softevents, CTLFLAG_TUN|CTLFLAG_RD,
147 !CPU_ISSET(cpu, &hlt_cpus_mask));
164 return (!CPU_ABSENT(cpu));
174 return (!CPU_ISSET(cpu, &logical_cpus_mask));
202 pmc_cpu_max_active(
void)
230 for ( ; *p ==
'_' ; p++)
233 if (*p ==
'_' && (*(p + 1) ==
'_' || *(p + 1) ==
'\0'))
244 static int warned = 0;
248 ps->ps_ev.pm_ev_code = 0;
261 if (n == pmc_softevents) {
264 printf(
"hwpmc: too many soft events, "
265 "increase kern.hwpmc.softevents tunable\n");
271 ps->ps_ev.pm_ev_code = PMC_EV_SOFT_FIRST + n;
285 KASSERT(ps != NULL, (
"pmc_soft_deregister: called with NULL"));
289 if (ps->ps_ev.pm_ev_code != 0 &&
291 KASSERT(ps->ps_ev.pm_ev_code >= PMC_EV_SOFT_FIRST &&
292 ps->ps_ev.pm_ev_code <= PMC_EV_SOFT_LAST,
293 (
"pmc_soft_deregister: invalid event value"));
294 pmc_softs[ps->ps_ev.pm_ev_code - PMC_EV_SOFT_FIRST] = NULL;
308 KASSERT(ev >= PMC_EV_SOFT_FIRST &&
309 ev <= PMC_EV_SOFT_LAST,
310 (
"event out of range"));
336 (void)
printf(
"hwpmc: tunable \"softevents\"=%d out of "
341 KASSERT(
pmc_softs != NULL, (
"cannot allocate soft events table"));
void pmc_soft_ev_register(struct pmc_soft *ps)
void sx_init_flags(struct sx *sx, const char *description, int opts)
volatile cpuset_t pmc_cpumask
void * malloc(unsigned long size, struct malloc_type *mtp, int flags)
SYSCTL_INT(_kern_hwpmc, OID_AUTO, softevents, CTLFLAG_TUN|CTLFLAG_RD,&pmc_softevents, 0,"maximum number of soft events")
void pmc_soft_ev_deregister(struct pmc_soft *ps)
MALLOC_DECLARE(M_PMCHOOKS)
#define PMC_KERNEL_VERSION
unsigned int pmc_cpu_max(void)
struct pmc_soft ** pmc_softs
SYSCTL_NODE(_kern, OID_AUTO, hwpmc, CTLFLAG_RW, 0,"HWPMC parameters")
const int pmc_kernel_version
static void pmc_soft_namecleanup(char *name)
volatile int pmc_ss_count
static void pmc_init_sx(void)
struct trapframe pmc_tf[MAXCPU]
int pmc_cpu_is_primary(int cpu)
int(* pmc_intr)(int cpu, struct trapframe *tf)
static void init_hwpmc(void *dummy __unused)
int pmc_cpu_is_present(int cpu)
int printf(const char *fmt,...)
void pmc_soft_ev_release(struct pmc_soft *ps)
SYSINIT(pmcsx, SI_SUB_LOCK, SI_ORDER_MIDDLE, pmc_init_sx, NULL)
MTX_SYSINIT(pmc_soft_mtx,&pmc_softs_mtx,"pmc-softs", MTX_SPIN)
MALLOC_DEFINE(M_PMCHOOKS,"pmchooks","Memory space for PMC hooks")
FEATURE(kdtrace_hooks,"Kernel DTrace hooks which are required to load DTrace kernel modules")
int(* pmc_hook)(struct thread *td, int function, void *arg)
int pmc_cpu_is_disabled(int cpu)
static int pmc_softevents
struct pmc_soft * pmc_soft_ev_acquire(enum pmc_event ev)
int pmc_cpu_is_active(int cpu)
TUNABLE_INT(PMC_SYSCTL_NAME_PREFIX"softevents",&pmc_softevents)