1ebccf1e3SJoseph Koshy /*- 2ebccf1e3SJoseph Koshy * Copyright (c) 2003,2004 Joseph Koshy 3ebccf1e3SJoseph Koshy * All rights reserved. 4ebccf1e3SJoseph Koshy * 5ebccf1e3SJoseph Koshy * Redistribution and use in source and binary forms, with or without 6ebccf1e3SJoseph Koshy * modification, are permitted provided that the following conditions 7ebccf1e3SJoseph Koshy * are met: 8ebccf1e3SJoseph Koshy * 1. Redistributions of source code must retain the above copyright 9ebccf1e3SJoseph Koshy * notice, this list of conditions and the following disclaimer. 10ebccf1e3SJoseph Koshy * 2. Redistributions in binary form must reproduce the above copyright 11ebccf1e3SJoseph Koshy * notice, this list of conditions and the following disclaimer in the 12ebccf1e3SJoseph Koshy * documentation and/or other materials provided with the distribution. 13ebccf1e3SJoseph Koshy * 14ebccf1e3SJoseph Koshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15ebccf1e3SJoseph Koshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16ebccf1e3SJoseph Koshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17ebccf1e3SJoseph Koshy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18ebccf1e3SJoseph Koshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19ebccf1e3SJoseph Koshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20ebccf1e3SJoseph Koshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21ebccf1e3SJoseph Koshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22ebccf1e3SJoseph Koshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23ebccf1e3SJoseph Koshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24ebccf1e3SJoseph Koshy * SUCH DAMAGE. 25ebccf1e3SJoseph Koshy * 26ebccf1e3SJoseph Koshy */ 27ebccf1e3SJoseph Koshy 28ebccf1e3SJoseph Koshy #include <sys/cdefs.h> 29ebccf1e3SJoseph Koshy __FBSDID("$FreeBSD$"); 30ebccf1e3SJoseph Koshy 312953224eSAttilio Rao #include <sys/param.h> 32ebccf1e3SJoseph Koshy #include <sys/queue.h> 33095489dbSAttilio Rao #include <sys/cpuset.h> 34ebccf1e3SJoseph Koshy #include <sys/sysctl.h> 35ebccf1e3SJoseph Koshy 36ebccf1e3SJoseph Koshy #include <assert.h> 37ebccf1e3SJoseph Koshy #include <err.h> 38ebccf1e3SJoseph Koshy #include <errno.h> 39ebccf1e3SJoseph Koshy #include <fcntl.h> 40ebccf1e3SJoseph Koshy #include <limits.h> 41ebccf1e3SJoseph Koshy #include <pmc.h> 42ebccf1e3SJoseph Koshy #include <stdarg.h> 43ebccf1e3SJoseph Koshy #include <stdio.h> 44ebccf1e3SJoseph Koshy #include <stdlib.h> 45ebccf1e3SJoseph Koshy #include <string.h> 46ebccf1e3SJoseph Koshy #include <sysexits.h> 47ebccf1e3SJoseph Koshy #include <unistd.h> 48ebccf1e3SJoseph Koshy 49ebccf1e3SJoseph Koshy /* Compile time defaults */ 50ebccf1e3SJoseph Koshy 51ebccf1e3SJoseph Koshy #define PMCC_PRINT_USAGE 0 52ebccf1e3SJoseph Koshy #define PMCC_PRINT_EVENTS 1 53ebccf1e3SJoseph Koshy #define PMCC_LIST_STATE 2 54ebccf1e3SJoseph Koshy #define PMCC_ENABLE_DISABLE 3 55ebccf1e3SJoseph Koshy #define PMCC_SHOW_STATISTICS 4 56ebccf1e3SJoseph Koshy 57ebccf1e3SJoseph Koshy #define PMCC_CPU_ALL -1 58ebccf1e3SJoseph Koshy #define PMCC_CPU_WILDCARD '*' 59ebccf1e3SJoseph Koshy 60ebccf1e3SJoseph Koshy #define PMCC_PMC_ALL -1 61ebccf1e3SJoseph Koshy #define PMCC_PMC_WILDCARD '*' 62ebccf1e3SJoseph Koshy 63ebccf1e3SJoseph Koshy #define PMCC_OP_IGNORE 0 64ebccf1e3SJoseph Koshy #define PMCC_OP_DISABLE 1 65ebccf1e3SJoseph Koshy #define PMCC_OP_ENABLE 2 66ebccf1e3SJoseph Koshy 67ebccf1e3SJoseph Koshy #define PMCC_PROGRAM_NAME "pmccontrol" 68ebccf1e3SJoseph Koshy 69ebccf1e3SJoseph Koshy STAILQ_HEAD(pmcc_op_list, pmcc_op) head = STAILQ_HEAD_INITIALIZER(head); 70ebccf1e3SJoseph Koshy 71ebccf1e3SJoseph Koshy struct pmcc_op { 72ebccf1e3SJoseph Koshy char op_cpu; 73ebccf1e3SJoseph Koshy char op_pmc; 74ebccf1e3SJoseph Koshy char op_op; 75ebccf1e3SJoseph Koshy STAILQ_ENTRY(pmcc_op) op_next; 76ebccf1e3SJoseph Koshy }; 77ebccf1e3SJoseph Koshy 78ebccf1e3SJoseph Koshy /* Function Prototypes */ 79ebccf1e3SJoseph Koshy #if DEBUG 80ebccf1e3SJoseph Koshy static void pmcc_init_debug(void); 81ebccf1e3SJoseph Koshy #endif 82ebccf1e3SJoseph Koshy 83ebccf1e3SJoseph Koshy static int pmcc_do_list_state(void); 84ebccf1e3SJoseph Koshy static int pmcc_do_enable_disable(struct pmcc_op_list *); 85ebccf1e3SJoseph Koshy static int pmcc_do_list_events(void); 86ebccf1e3SJoseph Koshy 87ebccf1e3SJoseph Koshy /* Globals */ 88ebccf1e3SJoseph Koshy 89ebccf1e3SJoseph Koshy static char usage_message[] = 90ebccf1e3SJoseph Koshy "Usage:\n" 919798d180SJoseph Koshy " " PMCC_PROGRAM_NAME " -L\n" 92ebccf1e3SJoseph Koshy " " PMCC_PROGRAM_NAME " -l\n" 93ebccf1e3SJoseph Koshy " " PMCC_PROGRAM_NAME " -s\n" 94ebccf1e3SJoseph Koshy " " PMCC_PROGRAM_NAME " [-e pmc | -d pmc | -c cpu] ..."; 95ebccf1e3SJoseph Koshy 96ebccf1e3SJoseph Koshy #if DEBUG 97ebccf1e3SJoseph Koshy FILE *debug_stream = NULL; 98ebccf1e3SJoseph Koshy #endif 99ebccf1e3SJoseph Koshy 100ebccf1e3SJoseph Koshy #if DEBUG 101ebccf1e3SJoseph Koshy #define DEBUG_MSG(...) \ 102ebccf1e3SJoseph Koshy (void) fprintf(debug_stream, "[pmccontrol] " __VA_ARGS__); 103ebccf1e3SJoseph Koshy #else 104ebccf1e3SJoseph Koshy #define DEBUG_MSG(m) /* */ 105ebccf1e3SJoseph Koshy #endif /* !DEBUG */ 106ebccf1e3SJoseph Koshy 107ebccf1e3SJoseph Koshy int pmc_syscall = -1; 108ebccf1e3SJoseph Koshy 109ebccf1e3SJoseph Koshy #define PMC_CALL(cmd, params) \ 110ebccf1e3SJoseph Koshy if ((error = syscall(pmc_syscall, PMC_OP_##cmd, (params))) != 0) \ 111ebccf1e3SJoseph Koshy { \ 112ebccf1e3SJoseph Koshy DEBUG_MSG("ERROR: syscall [" #cmd "]"); \ 113ebccf1e3SJoseph Koshy exit(EX_OSERR); \ 114ebccf1e3SJoseph Koshy } 115ebccf1e3SJoseph Koshy 116ebccf1e3SJoseph Koshy #if DEBUG 117ebccf1e3SJoseph Koshy /* log debug messages to a separate file */ 118ebccf1e3SJoseph Koshy static void 119ebccf1e3SJoseph Koshy pmcc_init_debug(void) 120ebccf1e3SJoseph Koshy { 121ebccf1e3SJoseph Koshy char *fn; 122ebccf1e3SJoseph Koshy 123ebccf1e3SJoseph Koshy fn = getenv("PMCCONTROL_DEBUG"); 124ebccf1e3SJoseph Koshy if (fn != NULL) 125ebccf1e3SJoseph Koshy { 126ebccf1e3SJoseph Koshy debug_stream = fopen(fn, "w"); 127ebccf1e3SJoseph Koshy if (debug_stream == NULL) 128ebccf1e3SJoseph Koshy debug_stream = stderr; 129ebccf1e3SJoseph Koshy } else 130ebccf1e3SJoseph Koshy debug_stream = stderr; 131ebccf1e3SJoseph Koshy } 132ebccf1e3SJoseph Koshy #endif 133ebccf1e3SJoseph Koshy 134ebccf1e3SJoseph Koshy static int 135ebccf1e3SJoseph Koshy pmcc_do_enable_disable(struct pmcc_op_list *op_list) 136ebccf1e3SJoseph Koshy { 137ebccf1e3SJoseph Koshy int c, error, i, j, ncpu, npmc, t; 138ebccf1e3SJoseph Koshy struct pmcc_op *np; 139ebccf1e3SJoseph Koshy unsigned char *map; 14035cf650fSJoseph Koshy unsigned char op; 14135cf650fSJoseph Koshy int cpu, pmc; 142ebccf1e3SJoseph Koshy 143ebccf1e3SJoseph Koshy if ((ncpu = pmc_ncpu()) < 0) 144ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to determine the number of cpus"); 145ebccf1e3SJoseph Koshy 14635cf650fSJoseph Koshy /* Determine the maximum number of PMCs in any CPU. */ 147ebccf1e3SJoseph Koshy npmc = 0; 148ebccf1e3SJoseph Koshy for (c = 0; c < ncpu; c++) { 149ebccf1e3SJoseph Koshy if ((t = pmc_npmc(c)) < 0) 15037d6f8a9SDavid E. O'Brien err(EX_OSERR, 15137d6f8a9SDavid E. O'Brien "Unable to determine the number of PMCs in CPU %d", 15237d6f8a9SDavid E. O'Brien c); 153ebccf1e3SJoseph Koshy npmc = t > npmc ? t : npmc; 154ebccf1e3SJoseph Koshy } 155ebccf1e3SJoseph Koshy 156ebccf1e3SJoseph Koshy if (npmc == 0) 157ebccf1e3SJoseph Koshy errx(EX_CONFIG, "No PMCs found"); 158ebccf1e3SJoseph Koshy 159ebccf1e3SJoseph Koshy if ((map = malloc(npmc * ncpu)) == NULL) 160ebccf1e3SJoseph Koshy err(EX_SOFTWARE, "Out of memory"); 161ebccf1e3SJoseph Koshy 162ebccf1e3SJoseph Koshy (void) memset(map, PMCC_OP_IGNORE, npmc*ncpu); 163ebccf1e3SJoseph Koshy 164ebccf1e3SJoseph Koshy error = 0; 165ebccf1e3SJoseph Koshy STAILQ_FOREACH(np, op_list, op_next) { 166ebccf1e3SJoseph Koshy 167ebccf1e3SJoseph Koshy cpu = np->op_cpu; 168ebccf1e3SJoseph Koshy pmc = np->op_pmc; 169ebccf1e3SJoseph Koshy op = np->op_op; 170ebccf1e3SJoseph Koshy 171ebccf1e3SJoseph Koshy if (cpu >= ncpu) 172ebccf1e3SJoseph Koshy errx(EX_DATAERR, "CPU id too large: \"%d\"", cpu); 173ebccf1e3SJoseph Koshy 174ebccf1e3SJoseph Koshy if (pmc >= npmc) 175ebccf1e3SJoseph Koshy errx(EX_DATAERR, "PMC id too large: \"%d\"", pmc); 176ebccf1e3SJoseph Koshy 177ebccf1e3SJoseph Koshy #define MARKMAP(M,C,P,V) do { \ 178ebccf1e3SJoseph Koshy *((M) + (C)*npmc + (P)) = (V); \ 179ebccf1e3SJoseph Koshy } while (0) 180ebccf1e3SJoseph Koshy 181ebccf1e3SJoseph Koshy #define SET_PMCS(C,P,V) do { \ 182ebccf1e3SJoseph Koshy if ((P) == PMCC_PMC_ALL) { \ 183ebccf1e3SJoseph Koshy for (j = 0; j < npmc; j++) \ 184ebccf1e3SJoseph Koshy MARKMAP(map, (C), j, (V)); \ 185ebccf1e3SJoseph Koshy } else \ 186ebccf1e3SJoseph Koshy MARKMAP(map, (C), (P), (V)); \ 187ebccf1e3SJoseph Koshy } while (0) 188ebccf1e3SJoseph Koshy 189ebccf1e3SJoseph Koshy #define MAP(M,C,P) (*((M) + (C)*npmc + (P))) 190ebccf1e3SJoseph Koshy 191ebccf1e3SJoseph Koshy if (cpu == PMCC_CPU_ALL) 19235cf650fSJoseph Koshy for (i = 0; i < ncpu; i++) { 193ebccf1e3SJoseph Koshy SET_PMCS(i, pmc, op); 19435cf650fSJoseph Koshy } 195ebccf1e3SJoseph Koshy else 196ebccf1e3SJoseph Koshy SET_PMCS(cpu, pmc, op); 197ebccf1e3SJoseph Koshy } 198ebccf1e3SJoseph Koshy 199ebccf1e3SJoseph Koshy /* Configure PMCS */ 200ebccf1e3SJoseph Koshy for (i = 0; i < ncpu; i++) 201ebccf1e3SJoseph Koshy for (j = 0; j < npmc; j++) { 202ebccf1e3SJoseph Koshy unsigned char b; 203ebccf1e3SJoseph Koshy 204ebccf1e3SJoseph Koshy b = MAP(map, i, j); 205ebccf1e3SJoseph Koshy 206ebccf1e3SJoseph Koshy error = 0; 207ebccf1e3SJoseph Koshy 208ebccf1e3SJoseph Koshy if (b == PMCC_OP_ENABLE) 209ebccf1e3SJoseph Koshy error = pmc_enable(i, j); 210ebccf1e3SJoseph Koshy else if (b == PMCC_OP_DISABLE) 211ebccf1e3SJoseph Koshy error = pmc_disable(i, j); 212ebccf1e3SJoseph Koshy 213ebccf1e3SJoseph Koshy if (error < 0) 214ebccf1e3SJoseph Koshy err(EX_OSERR, "%s of PMC %d on CPU %d failed", 21537d6f8a9SDavid E. O'Brien b == PMCC_OP_ENABLE ? "Enable" : "Disable", 21637d6f8a9SDavid E. O'Brien j, i); 217ebccf1e3SJoseph Koshy } 218ebccf1e3SJoseph Koshy 219ebccf1e3SJoseph Koshy return error; 220ebccf1e3SJoseph Koshy } 221ebccf1e3SJoseph Koshy 222ebccf1e3SJoseph Koshy static int 223ebccf1e3SJoseph Koshy pmcc_do_list_state(void) 224ebccf1e3SJoseph Koshy { 225095489dbSAttilio Rao cpuset_t logical_cpus_mask; 226095489dbSAttilio Rao long cpusetsize; 227095489dbSAttilio Rao size_t setsize; 228ebccf1e3SJoseph Koshy int c, cpu, n, npmc, ncpu; 229ebccf1e3SJoseph Koshy struct pmc_info *pd; 230f263522aSJoseph Koshy struct pmc_pmcinfo *pi; 231f263522aSJoseph Koshy const struct pmc_cpuinfo *pc; 232ebccf1e3SJoseph Koshy 233ebccf1e3SJoseph Koshy if (pmc_cpuinfo(&pc) != 0) 234ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to determine CPU information"); 235ebccf1e3SJoseph Koshy 23688660748SGeorge V. Neville-Neil printf("%d %s CPUs present, with %d PMCs per CPU\n", pc->pm_ncpu, 23788660748SGeorge V. Neville-Neil pmc_name_of_cputype(pc->pm_cputype), 23888660748SGeorge V. Neville-Neil pc->pm_npmc); 23988660748SGeorge V. Neville-Neil 240095489dbSAttilio Rao /* Determine the set of logical CPUs. */ 241095489dbSAttilio Rao cpusetsize = sysconf(_SC_CPUSET_SIZE); 242095489dbSAttilio Rao if (cpusetsize == -1 || (u_long)cpusetsize > sizeof(cpuset_t)) 243095489dbSAttilio Rao err(EX_OSERR, "Cannot determine which CPUs are logical"); 244095489dbSAttilio Rao CPU_ZERO(&logical_cpus_mask); 245095489dbSAttilio Rao setsize = (size_t)cpusetsize; 246ebccf1e3SJoseph Koshy if (sysctlbyname("machdep.logical_cpus_mask", &logical_cpus_mask, 247095489dbSAttilio Rao &setsize, NULL, 0) < 0) 248095489dbSAttilio Rao CPU_ZERO(&logical_cpus_mask); 249ebccf1e3SJoseph Koshy 250ebccf1e3SJoseph Koshy ncpu = pc->pm_ncpu; 251ebccf1e3SJoseph Koshy 252ebccf1e3SJoseph Koshy for (c = cpu = 0; cpu < ncpu; cpu++) { 2535943a2a3SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 254ebccf1e3SJoseph Koshy if (pc->pm_cputype == PMC_CPU_INTEL_PIV && 255095489dbSAttilio Rao CPU_ISSET(cpu, &logical_cpus_mask)) 256ebccf1e3SJoseph Koshy continue; /* skip P4-style 'logical' cpus */ 257ebccf1e3SJoseph Koshy #endif 2585d09484bSJoseph Koshy if (pmc_pmcinfo(cpu, &pi) < 0) { 2595d09484bSJoseph Koshy if (errno == ENXIO) 2605d09484bSJoseph Koshy continue; 261ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to get PMC status for CPU %d", 262ebccf1e3SJoseph Koshy cpu); 2635d09484bSJoseph Koshy } 264ebccf1e3SJoseph Koshy 265ebccf1e3SJoseph Koshy printf("#CPU %d:\n", c++); 266ebccf1e3SJoseph Koshy npmc = pmc_npmc(cpu); 267ebccf1e3SJoseph Koshy printf("#N NAME CLASS STATE ROW-DISP\n"); 268ebccf1e3SJoseph Koshy 269ebccf1e3SJoseph Koshy for (n = 0; n < npmc; n++) { 270ebccf1e3SJoseph Koshy pd = &pi->pm_pmcs[n]; 271ebccf1e3SJoseph Koshy 272ebccf1e3SJoseph Koshy printf(" %-2d %-16s %-6s %-8s %-10s", 273ebccf1e3SJoseph Koshy n, 274ebccf1e3SJoseph Koshy pd->pm_name, 275ebccf1e3SJoseph Koshy pmc_name_of_class(pd->pm_class), 276ebccf1e3SJoseph Koshy pd->pm_enabled ? "ENABLED" : "DISABLED", 277ebccf1e3SJoseph Koshy pmc_name_of_disposition(pd->pm_rowdisp)); 278ebccf1e3SJoseph Koshy 279ebccf1e3SJoseph Koshy if (pd->pm_ownerpid != -1) { 280ebccf1e3SJoseph Koshy printf(" (pid %d)", pd->pm_ownerpid); 281ebccf1e3SJoseph Koshy printf(" %-32s", 282ebccf1e3SJoseph Koshy pmc_name_of_event(pd->pm_event)); 283ebccf1e3SJoseph Koshy if (PMC_IS_SAMPLING_MODE(pd->pm_mode)) 284ebccf1e3SJoseph Koshy printf(" (reload count %jd)", 285ebccf1e3SJoseph Koshy pd->pm_reloadcount); 286ebccf1e3SJoseph Koshy } 287ebccf1e3SJoseph Koshy printf("\n"); 288ebccf1e3SJoseph Koshy } 289ebccf1e3SJoseph Koshy free(pi); 290ebccf1e3SJoseph Koshy } 291ebccf1e3SJoseph Koshy return 0; 292ebccf1e3SJoseph Koshy } 293ebccf1e3SJoseph Koshy 294ebccf1e3SJoseph Koshy static int 295ebccf1e3SJoseph Koshy pmcc_do_list_events(void) 296ebccf1e3SJoseph Koshy { 297ebccf1e3SJoseph Koshy enum pmc_class c; 298ebccf1e3SJoseph Koshy unsigned int i, j, nevents; 299ebccf1e3SJoseph Koshy const char **eventnamelist; 300f263522aSJoseph Koshy const struct pmc_cpuinfo *ci; 301ebccf1e3SJoseph Koshy 302ebccf1e3SJoseph Koshy if (pmc_cpuinfo(&ci) != 0) 303ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to determine CPU information"); 304ebccf1e3SJoseph Koshy 305ebccf1e3SJoseph Koshy eventnamelist = NULL; 306ebccf1e3SJoseph Koshy 307ebccf1e3SJoseph Koshy for (i = 0; i < ci->pm_nclass; i++) { 308c5153e19SJoseph Koshy c = ci->pm_classes[i].pm_class; 309ebccf1e3SJoseph Koshy 310ebccf1e3SJoseph Koshy printf("%s\n", pmc_name_of_class(c)); 311ebccf1e3SJoseph Koshy if (pmc_event_names_of_class(c, &eventnamelist, &nevents) < 0) 31237d6f8a9SDavid E. O'Brien err(EX_OSERR, 31337d6f8a9SDavid E. O'Brien "ERROR: Cannot find information for event class \"%s\"", 31437d6f8a9SDavid E. O'Brien pmc_name_of_class(c)); 315ebccf1e3SJoseph Koshy 316ebccf1e3SJoseph Koshy for (j = 0; j < nevents; j++) 317ebccf1e3SJoseph Koshy printf("\t%s\n", eventnamelist[j]); 318ebccf1e3SJoseph Koshy 319ebccf1e3SJoseph Koshy free(eventnamelist); 320ebccf1e3SJoseph Koshy } 321ebccf1e3SJoseph Koshy return 0; 322ebccf1e3SJoseph Koshy } 323ebccf1e3SJoseph Koshy 324ebccf1e3SJoseph Koshy static int 325ebccf1e3SJoseph Koshy pmcc_show_statistics(void) 326ebccf1e3SJoseph Koshy { 327ebccf1e3SJoseph Koshy 328f263522aSJoseph Koshy struct pmc_driverstats gms; 329ebccf1e3SJoseph Koshy 330ebccf1e3SJoseph Koshy if (pmc_get_driver_stats(&gms) < 0) 331ebccf1e3SJoseph Koshy err(EX_OSERR, "ERROR: cannot retrieve driver statistics"); 332ebccf1e3SJoseph Koshy 333ebccf1e3SJoseph Koshy /* 334ebccf1e3SJoseph Koshy * Print statistics. 335ebccf1e3SJoseph Koshy */ 336ebccf1e3SJoseph Koshy 337f263522aSJoseph Koshy #define PRINT(N,V) (void) printf("%-40s %d\n", (N), gms.pm_##V) 338f263522aSJoseph Koshy PRINT("interrupts processed:", intr_processed); 339f263522aSJoseph Koshy PRINT("non-PMC interrupts:", intr_ignored); 340f35f2fc8SJoseph Koshy PRINT("sampling stalls due to space shortages:", intr_bufferfull); 341f263522aSJoseph Koshy PRINT("system calls:", syscalls); 342f263522aSJoseph Koshy PRINT("system calls with errors:", syscall_errors); 343f263522aSJoseph Koshy PRINT("buffer requests:", buffer_requests); 344f263522aSJoseph Koshy PRINT("buffer requests failed:", buffer_requests_failed); 345f263522aSJoseph Koshy PRINT("sampling log sweeps:", log_sweeps); 346ebccf1e3SJoseph Koshy 347ebccf1e3SJoseph Koshy return 0; 348ebccf1e3SJoseph Koshy } 349ebccf1e3SJoseph Koshy 350ebccf1e3SJoseph Koshy /* 351ebccf1e3SJoseph Koshy * Main 352ebccf1e3SJoseph Koshy */ 353ebccf1e3SJoseph Koshy 354ebccf1e3SJoseph Koshy int 355ebccf1e3SJoseph Koshy main(int argc, char **argv) 356ebccf1e3SJoseph Koshy { 357ebccf1e3SJoseph Koshy int error, command, currentcpu, option, pmc; 358ebccf1e3SJoseph Koshy char *dummy; 359ebccf1e3SJoseph Koshy struct pmcc_op *p; 360ebccf1e3SJoseph Koshy 361ebccf1e3SJoseph Koshy #if DEBUG 362ebccf1e3SJoseph Koshy pmcc_init_debug(); 363ebccf1e3SJoseph Koshy #endif 364ebccf1e3SJoseph Koshy 365ebccf1e3SJoseph Koshy /* parse args */ 366ebccf1e3SJoseph Koshy 367ebccf1e3SJoseph Koshy currentcpu = PMCC_CPU_ALL; 368ebccf1e3SJoseph Koshy command = PMCC_PRINT_USAGE; 369ebccf1e3SJoseph Koshy error = 0; 370ebccf1e3SJoseph Koshy 371ebccf1e3SJoseph Koshy STAILQ_INIT(&head); 372ebccf1e3SJoseph Koshy 373ebccf1e3SJoseph Koshy while ((option = getopt(argc, argv, ":c:d:e:lLs")) != -1) 374ebccf1e3SJoseph Koshy switch (option) { 375ebccf1e3SJoseph Koshy case 'L': 376ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE) { 377ebccf1e3SJoseph Koshy error = 1; 378ebccf1e3SJoseph Koshy break; 379ebccf1e3SJoseph Koshy } 380ebccf1e3SJoseph Koshy command = PMCC_PRINT_EVENTS; 381ebccf1e3SJoseph Koshy break; 382ebccf1e3SJoseph Koshy 383ebccf1e3SJoseph Koshy case 'c': 384ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE && 385ebccf1e3SJoseph Koshy command != PMCC_ENABLE_DISABLE) { 386ebccf1e3SJoseph Koshy error = 1; 387ebccf1e3SJoseph Koshy break; 388ebccf1e3SJoseph Koshy } 389ebccf1e3SJoseph Koshy command = PMCC_ENABLE_DISABLE; 390ebccf1e3SJoseph Koshy 391ebccf1e3SJoseph Koshy if (*optarg == PMCC_CPU_WILDCARD) 392ebccf1e3SJoseph Koshy currentcpu = PMCC_CPU_ALL; 393ebccf1e3SJoseph Koshy else { 394ebccf1e3SJoseph Koshy currentcpu = strtoul(optarg, &dummy, 0); 395ebccf1e3SJoseph Koshy if (*dummy != '\0' || currentcpu < 0) 396ebccf1e3SJoseph Koshy errx(EX_DATAERR, 397ebccf1e3SJoseph Koshy "\"%s\" is not a valid CPU id", 398ebccf1e3SJoseph Koshy optarg); 399ebccf1e3SJoseph Koshy } 400ebccf1e3SJoseph Koshy break; 401ebccf1e3SJoseph Koshy 402ebccf1e3SJoseph Koshy case 'd': 403ebccf1e3SJoseph Koshy case 'e': 404ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE && 405ebccf1e3SJoseph Koshy command != PMCC_ENABLE_DISABLE) { 406ebccf1e3SJoseph Koshy error = 1; 407ebccf1e3SJoseph Koshy break; 408ebccf1e3SJoseph Koshy } 409ebccf1e3SJoseph Koshy command = PMCC_ENABLE_DISABLE; 410ebccf1e3SJoseph Koshy 411ebccf1e3SJoseph Koshy if (*optarg == PMCC_PMC_WILDCARD) 412ebccf1e3SJoseph Koshy pmc = PMCC_PMC_ALL; 413ebccf1e3SJoseph Koshy else { 414ebccf1e3SJoseph Koshy pmc = strtoul(optarg, &dummy, 0); 415ebccf1e3SJoseph Koshy if (*dummy != '\0' || pmc < 0) 416ebccf1e3SJoseph Koshy errx(EX_DATAERR, 417ebccf1e3SJoseph Koshy "\"%s\" is not a valid PMC id", 418ebccf1e3SJoseph Koshy optarg); 419ebccf1e3SJoseph Koshy } 420ebccf1e3SJoseph Koshy 421ebccf1e3SJoseph Koshy if ((p = malloc(sizeof(*p))) == NULL) 422ebccf1e3SJoseph Koshy err(EX_SOFTWARE, "Out of memory"); 423ebccf1e3SJoseph Koshy 424ebccf1e3SJoseph Koshy p->op_cpu = currentcpu; 425ebccf1e3SJoseph Koshy p->op_pmc = pmc; 426ebccf1e3SJoseph Koshy p->op_op = option == 'd' ? PMCC_OP_DISABLE : 427ebccf1e3SJoseph Koshy PMCC_OP_ENABLE; 428ebccf1e3SJoseph Koshy 429ebccf1e3SJoseph Koshy STAILQ_INSERT_TAIL(&head, p, op_next); 430ebccf1e3SJoseph Koshy break; 431ebccf1e3SJoseph Koshy 432ebccf1e3SJoseph Koshy case 'l': 433ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE) { 434ebccf1e3SJoseph Koshy error = 1; 435ebccf1e3SJoseph Koshy break; 436ebccf1e3SJoseph Koshy } 437ebccf1e3SJoseph Koshy command = PMCC_LIST_STATE; 438ebccf1e3SJoseph Koshy break; 439ebccf1e3SJoseph Koshy 440ebccf1e3SJoseph Koshy case 's': 441ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE) { 442ebccf1e3SJoseph Koshy error = 1; 443ebccf1e3SJoseph Koshy break; 444ebccf1e3SJoseph Koshy } 445ebccf1e3SJoseph Koshy command = PMCC_SHOW_STATISTICS; 446ebccf1e3SJoseph Koshy break; 447ebccf1e3SJoseph Koshy 448ebccf1e3SJoseph Koshy case ':': 449ebccf1e3SJoseph Koshy errx(EX_USAGE, 450ebccf1e3SJoseph Koshy "Missing argument to option '-%c'", optopt); 451ebccf1e3SJoseph Koshy break; 452ebccf1e3SJoseph Koshy 453ebccf1e3SJoseph Koshy case '?': 454ebccf1e3SJoseph Koshy warnx("Unrecognized option \"-%c\"", optopt); 455*e2d0cd59SDimitry Andric errx(EX_USAGE, "%s", usage_message); 456ebccf1e3SJoseph Koshy break; 457ebccf1e3SJoseph Koshy 458ebccf1e3SJoseph Koshy default: 459ebccf1e3SJoseph Koshy error = 1; 460ebccf1e3SJoseph Koshy break; 461ebccf1e3SJoseph Koshy 462ebccf1e3SJoseph Koshy } 463ebccf1e3SJoseph Koshy 464ebccf1e3SJoseph Koshy if (command == PMCC_PRINT_USAGE) 465*e2d0cd59SDimitry Andric (void) errx(EX_USAGE, "%s", usage_message); 466ebccf1e3SJoseph Koshy 467ebccf1e3SJoseph Koshy if (error) 468ebccf1e3SJoseph Koshy exit(EX_USAGE); 469ebccf1e3SJoseph Koshy 470ebccf1e3SJoseph Koshy if (pmc_init() < 0) 471ebccf1e3SJoseph Koshy err(EX_UNAVAILABLE, 472ebccf1e3SJoseph Koshy "Initialization of the pmc(3) library failed"); 473ebccf1e3SJoseph Koshy 474ebccf1e3SJoseph Koshy switch (command) { 475ebccf1e3SJoseph Koshy case PMCC_LIST_STATE: 476ebccf1e3SJoseph Koshy error = pmcc_do_list_state(); 477ebccf1e3SJoseph Koshy break; 478ebccf1e3SJoseph Koshy case PMCC_PRINT_EVENTS: 479ebccf1e3SJoseph Koshy error = pmcc_do_list_events(); 480ebccf1e3SJoseph Koshy break; 481ebccf1e3SJoseph Koshy case PMCC_SHOW_STATISTICS: 482ebccf1e3SJoseph Koshy error = pmcc_show_statistics(); 483ebccf1e3SJoseph Koshy break; 484ebccf1e3SJoseph Koshy case PMCC_ENABLE_DISABLE: 485ebccf1e3SJoseph Koshy if (STAILQ_EMPTY(&head)) 48637d6f8a9SDavid E. O'Brien errx(EX_USAGE, 48737d6f8a9SDavid E. O'Brien "No PMCs specified to enable or disable"); 488ebccf1e3SJoseph Koshy error = pmcc_do_enable_disable(&head); 489ebccf1e3SJoseph Koshy break; 490ebccf1e3SJoseph Koshy default: 491ebccf1e3SJoseph Koshy assert(0); 492ebccf1e3SJoseph Koshy 493ebccf1e3SJoseph Koshy } 494ebccf1e3SJoseph Koshy 495ebccf1e3SJoseph Koshy if (error != 0) 496ebccf1e3SJoseph Koshy err(EX_OSERR, "Command failed"); 497ebccf1e3SJoseph Koshy exit(0); 498ebccf1e3SJoseph Koshy } 499