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 31ebccf1e3SJoseph Koshy #include <sys/types.h> 32ebccf1e3SJoseph Koshy #include <sys/queue.h> 33ebccf1e3SJoseph Koshy #include <sys/sysctl.h> 34ebccf1e3SJoseph Koshy 35ebccf1e3SJoseph Koshy #include <assert.h> 36ebccf1e3SJoseph Koshy #include <err.h> 37ebccf1e3SJoseph Koshy #include <errno.h> 38ebccf1e3SJoseph Koshy #include <fcntl.h> 39ebccf1e3SJoseph Koshy #include <limits.h> 40ebccf1e3SJoseph Koshy #include <pmc.h> 41ebccf1e3SJoseph Koshy #include <stdarg.h> 42ebccf1e3SJoseph Koshy #include <stdio.h> 43ebccf1e3SJoseph Koshy #include <stdlib.h> 44ebccf1e3SJoseph Koshy #include <string.h> 45ebccf1e3SJoseph Koshy #include <sysexits.h> 46ebccf1e3SJoseph Koshy #include <unistd.h> 47ebccf1e3SJoseph Koshy 48ebccf1e3SJoseph Koshy /* Compile time defaults */ 49ebccf1e3SJoseph Koshy 50ebccf1e3SJoseph Koshy #define PMCC_PRINT_USAGE 0 51ebccf1e3SJoseph Koshy #define PMCC_PRINT_EVENTS 1 52ebccf1e3SJoseph Koshy #define PMCC_LIST_STATE 2 53ebccf1e3SJoseph Koshy #define PMCC_ENABLE_DISABLE 3 54ebccf1e3SJoseph Koshy #define PMCC_SHOW_STATISTICS 4 55ebccf1e3SJoseph Koshy 56ebccf1e3SJoseph Koshy #define PMCC_CPU_ALL -1 57ebccf1e3SJoseph Koshy #define PMCC_CPU_WILDCARD '*' 58ebccf1e3SJoseph Koshy 59ebccf1e3SJoseph Koshy #define PMCC_PMC_ALL -1 60ebccf1e3SJoseph Koshy #define PMCC_PMC_WILDCARD '*' 61ebccf1e3SJoseph Koshy 62ebccf1e3SJoseph Koshy #define PMCC_OP_IGNORE 0 63ebccf1e3SJoseph Koshy #define PMCC_OP_DISABLE 1 64ebccf1e3SJoseph Koshy #define PMCC_OP_ENABLE 2 65ebccf1e3SJoseph Koshy 66ebccf1e3SJoseph Koshy #define PMCC_PROGRAM_NAME "pmccontrol" 67ebccf1e3SJoseph Koshy 68ebccf1e3SJoseph Koshy STAILQ_HEAD(pmcc_op_list, pmcc_op) head = STAILQ_HEAD_INITIALIZER(head); 69ebccf1e3SJoseph Koshy 70ebccf1e3SJoseph Koshy struct pmcc_op { 71ebccf1e3SJoseph Koshy char op_cpu; 72ebccf1e3SJoseph Koshy char op_pmc; 73ebccf1e3SJoseph Koshy char op_op; 74ebccf1e3SJoseph Koshy STAILQ_ENTRY(pmcc_op) op_next; 75ebccf1e3SJoseph Koshy }; 76ebccf1e3SJoseph Koshy 77ebccf1e3SJoseph Koshy /* Function Prototypes */ 78ebccf1e3SJoseph Koshy #if DEBUG 79ebccf1e3SJoseph Koshy static void pmcc_init_debug(void); 80ebccf1e3SJoseph Koshy #endif 81ebccf1e3SJoseph Koshy 82ebccf1e3SJoseph Koshy static int pmcc_do_list_state(void); 83ebccf1e3SJoseph Koshy static int pmcc_do_enable_disable(struct pmcc_op_list *); 84ebccf1e3SJoseph Koshy static int pmcc_do_list_events(void); 85ebccf1e3SJoseph Koshy 86ebccf1e3SJoseph Koshy /* Globals */ 87ebccf1e3SJoseph Koshy 88ebccf1e3SJoseph Koshy static char usage_message[] = 89ebccf1e3SJoseph Koshy "Usage:\n" 909798d180SJoseph Koshy " " PMCC_PROGRAM_NAME " -L\n" 91ebccf1e3SJoseph Koshy " " PMCC_PROGRAM_NAME " -l\n" 92ebccf1e3SJoseph Koshy " " PMCC_PROGRAM_NAME " -s\n" 93ebccf1e3SJoseph Koshy " " PMCC_PROGRAM_NAME " [-e pmc | -d pmc | -c cpu] ..."; 94ebccf1e3SJoseph Koshy 95ebccf1e3SJoseph Koshy #if DEBUG 96ebccf1e3SJoseph Koshy FILE *debug_stream = NULL; 97ebccf1e3SJoseph Koshy #endif 98ebccf1e3SJoseph Koshy 99ebccf1e3SJoseph Koshy #if DEBUG 100ebccf1e3SJoseph Koshy #define DEBUG_MSG(...) \ 101ebccf1e3SJoseph Koshy (void) fprintf(debug_stream, "[pmccontrol] " __VA_ARGS__); 102ebccf1e3SJoseph Koshy #else 103ebccf1e3SJoseph Koshy #define DEBUG_MSG(m) /* */ 104ebccf1e3SJoseph Koshy #endif /* !DEBUG */ 105ebccf1e3SJoseph Koshy 106ebccf1e3SJoseph Koshy int pmc_syscall = -1; 107ebccf1e3SJoseph Koshy 108ebccf1e3SJoseph Koshy #define PMC_CALL(cmd, params) \ 109ebccf1e3SJoseph Koshy if ((error = syscall(pmc_syscall, PMC_OP_##cmd, (params))) != 0) \ 110ebccf1e3SJoseph Koshy { \ 111ebccf1e3SJoseph Koshy DEBUG_MSG("ERROR: syscall [" #cmd "]"); \ 112ebccf1e3SJoseph Koshy exit(EX_OSERR); \ 113ebccf1e3SJoseph Koshy } 114ebccf1e3SJoseph Koshy 115ebccf1e3SJoseph Koshy #if DEBUG 116ebccf1e3SJoseph Koshy /* log debug messages to a separate file */ 117ebccf1e3SJoseph Koshy static void 118ebccf1e3SJoseph Koshy pmcc_init_debug(void) 119ebccf1e3SJoseph Koshy { 120ebccf1e3SJoseph Koshy char *fn; 121ebccf1e3SJoseph Koshy 122ebccf1e3SJoseph Koshy fn = getenv("PMCCONTROL_DEBUG"); 123ebccf1e3SJoseph Koshy if (fn != NULL) 124ebccf1e3SJoseph Koshy { 125ebccf1e3SJoseph Koshy debug_stream = fopen(fn, "w"); 126ebccf1e3SJoseph Koshy if (debug_stream == NULL) 127ebccf1e3SJoseph Koshy debug_stream = stderr; 128ebccf1e3SJoseph Koshy } else 129ebccf1e3SJoseph Koshy debug_stream = stderr; 130ebccf1e3SJoseph Koshy } 131ebccf1e3SJoseph Koshy #endif 132ebccf1e3SJoseph Koshy 133ebccf1e3SJoseph Koshy static int 134ebccf1e3SJoseph Koshy pmcc_do_enable_disable(struct pmcc_op_list *op_list) 135ebccf1e3SJoseph Koshy { 136ebccf1e3SJoseph Koshy int c, error, i, j, ncpu, npmc, t; 13735cf650fSJoseph Koshy cpumask_t haltedcpus, cpumask; 138ebccf1e3SJoseph Koshy struct pmcc_op *np; 139ebccf1e3SJoseph Koshy unsigned char *map; 14035cf650fSJoseph Koshy unsigned char op; 14135cf650fSJoseph Koshy int cpu, pmc; 14235cf650fSJoseph Koshy size_t dummy; 143ebccf1e3SJoseph Koshy 144ebccf1e3SJoseph Koshy if ((ncpu = pmc_ncpu()) < 0) 145ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to determine the number of cpus"); 146ebccf1e3SJoseph Koshy 14735cf650fSJoseph Koshy /* Determine the set of active CPUs. */ 14835cf650fSJoseph Koshy cpumask = (1 << ncpu) - 1; 14935cf650fSJoseph Koshy dummy = sizeof(int); 15035cf650fSJoseph Koshy haltedcpus = (cpumask_t) 0; 15135cf650fSJoseph Koshy if (ncpu > 1 && sysctlbyname("machdep.hlt_cpus", &haltedcpus, 15235cf650fSJoseph Koshy &dummy, NULL, 0) < 0) 15335cf650fSJoseph Koshy err(EX_OSERR, "ERROR: Cannot determine which CPUs are " 15435cf650fSJoseph Koshy "halted"); 15535cf650fSJoseph Koshy cpumask &= ~haltedcpus; 15635cf650fSJoseph Koshy 15735cf650fSJoseph Koshy /* Determine the maximum number of PMCs in any CPU. */ 158ebccf1e3SJoseph Koshy npmc = 0; 159ebccf1e3SJoseph Koshy for (c = 0; c < ncpu; c++) { 160ebccf1e3SJoseph Koshy if ((t = pmc_npmc(c)) < 0) 16135cf650fSJoseph Koshy err(EX_OSERR, "Unable to determine the number of " 16235cf650fSJoseph Koshy "PMCs in CPU %d", c); 163ebccf1e3SJoseph Koshy npmc = t > npmc ? t : npmc; 164ebccf1e3SJoseph Koshy } 165ebccf1e3SJoseph Koshy 166ebccf1e3SJoseph Koshy if (npmc == 0) 167ebccf1e3SJoseph Koshy errx(EX_CONFIG, "No PMCs found"); 168ebccf1e3SJoseph Koshy 169ebccf1e3SJoseph Koshy if ((map = malloc(npmc * ncpu)) == NULL) 170ebccf1e3SJoseph Koshy err(EX_SOFTWARE, "Out of memory"); 171ebccf1e3SJoseph Koshy 172ebccf1e3SJoseph Koshy (void) memset(map, PMCC_OP_IGNORE, npmc*ncpu); 173ebccf1e3SJoseph Koshy 174ebccf1e3SJoseph Koshy error = 0; 175ebccf1e3SJoseph Koshy STAILQ_FOREACH(np, op_list, op_next) { 176ebccf1e3SJoseph Koshy 177ebccf1e3SJoseph Koshy cpu = np->op_cpu; 178ebccf1e3SJoseph Koshy pmc = np->op_pmc; 179ebccf1e3SJoseph Koshy op = np->op_op; 180ebccf1e3SJoseph Koshy 181ebccf1e3SJoseph Koshy if (cpu >= ncpu) 182ebccf1e3SJoseph Koshy errx(EX_DATAERR, "CPU id too large: \"%d\"", cpu); 183ebccf1e3SJoseph Koshy 184ebccf1e3SJoseph Koshy if (pmc >= npmc) 185ebccf1e3SJoseph Koshy errx(EX_DATAERR, "PMC id too large: \"%d\"", pmc); 186ebccf1e3SJoseph Koshy 187ebccf1e3SJoseph Koshy #define MARKMAP(M,C,P,V) do { \ 188ebccf1e3SJoseph Koshy *((M) + (C)*npmc + (P)) = (V); \ 189ebccf1e3SJoseph Koshy } while (0) 190ebccf1e3SJoseph Koshy 191ebccf1e3SJoseph Koshy #define SET_PMCS(C,P,V) do { \ 192ebccf1e3SJoseph Koshy if ((P) == PMCC_PMC_ALL) { \ 193ebccf1e3SJoseph Koshy for (j = 0; j < npmc; j++) \ 194ebccf1e3SJoseph Koshy MARKMAP(map, (C), j, (V)); \ 195ebccf1e3SJoseph Koshy } else \ 196ebccf1e3SJoseph Koshy MARKMAP(map, (C), (P), (V)); \ 197ebccf1e3SJoseph Koshy } while (0) 198ebccf1e3SJoseph Koshy 199ebccf1e3SJoseph Koshy #define MAP(M,C,P) (*((M) + (C)*npmc + (P))) 200ebccf1e3SJoseph Koshy 201ebccf1e3SJoseph Koshy if (cpu == PMCC_CPU_ALL) 20235cf650fSJoseph Koshy for (i = 0; i < ncpu; i++) { 20335cf650fSJoseph Koshy if ((1 << i) & cpumask) 204ebccf1e3SJoseph Koshy SET_PMCS(i, pmc, op); 20535cf650fSJoseph Koshy } 206ebccf1e3SJoseph Koshy else 207ebccf1e3SJoseph Koshy SET_PMCS(cpu, pmc, op); 208ebccf1e3SJoseph Koshy } 209ebccf1e3SJoseph Koshy 210ebccf1e3SJoseph Koshy /* Configure PMCS */ 211ebccf1e3SJoseph Koshy for (i = 0; i < ncpu; i++) 212ebccf1e3SJoseph Koshy for (j = 0; j < npmc; j++) { 213ebccf1e3SJoseph Koshy unsigned char b; 214ebccf1e3SJoseph Koshy 215ebccf1e3SJoseph Koshy b = MAP(map, i, j); 216ebccf1e3SJoseph Koshy 217ebccf1e3SJoseph Koshy error = 0; 218ebccf1e3SJoseph Koshy 219ebccf1e3SJoseph Koshy if (b == PMCC_OP_ENABLE) 220ebccf1e3SJoseph Koshy error = pmc_enable(i, j); 221ebccf1e3SJoseph Koshy else if (b == PMCC_OP_DISABLE) 222ebccf1e3SJoseph Koshy error = pmc_disable(i, j); 223ebccf1e3SJoseph Koshy 224ebccf1e3SJoseph Koshy if (error < 0) 225ebccf1e3SJoseph Koshy err(EX_OSERR, "%s of PMC %d on CPU %d failed", 226ebccf1e3SJoseph Koshy b == PMCC_OP_ENABLE ? "Enable" : 227ebccf1e3SJoseph Koshy "Disable", j, i); 228ebccf1e3SJoseph Koshy } 229ebccf1e3SJoseph Koshy 230ebccf1e3SJoseph Koshy return error; 231ebccf1e3SJoseph Koshy } 232ebccf1e3SJoseph Koshy 233ebccf1e3SJoseph Koshy static int 234ebccf1e3SJoseph Koshy pmcc_do_list_state(void) 235ebccf1e3SJoseph Koshy { 236ebccf1e3SJoseph Koshy size_t dummy; 237ebccf1e3SJoseph Koshy int c, cpu, n, npmc, ncpu; 238ebccf1e3SJoseph Koshy unsigned int logical_cpus_mask; 239ebccf1e3SJoseph Koshy struct pmc_info *pd; 240f263522aSJoseph Koshy struct pmc_pmcinfo *pi; 241f263522aSJoseph Koshy const struct pmc_cpuinfo *pc; 242ebccf1e3SJoseph Koshy 243ebccf1e3SJoseph Koshy if (pmc_cpuinfo(&pc) != 0) 244ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to determine CPU information"); 245ebccf1e3SJoseph Koshy 246*88660748SGeorge V. Neville-Neil printf("%d %s CPUs present, with %d PMCs per CPU\n", pc->pm_ncpu, 247*88660748SGeorge V. Neville-Neil pmc_name_of_cputype(pc->pm_cputype), 248*88660748SGeorge V. Neville-Neil pc->pm_npmc); 249*88660748SGeorge V. Neville-Neil 250ebccf1e3SJoseph Koshy dummy = sizeof(logical_cpus_mask); 251ebccf1e3SJoseph Koshy if (sysctlbyname("machdep.logical_cpus_mask", &logical_cpus_mask, 252ebccf1e3SJoseph Koshy &dummy, NULL, 0) < 0) 253ebccf1e3SJoseph Koshy logical_cpus_mask = 0; 254ebccf1e3SJoseph Koshy 255ebccf1e3SJoseph Koshy ncpu = pc->pm_ncpu; 256ebccf1e3SJoseph Koshy 257ebccf1e3SJoseph Koshy for (c = cpu = 0; cpu < ncpu; cpu++) { 2585943a2a3SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 259ebccf1e3SJoseph Koshy if (pc->pm_cputype == PMC_CPU_INTEL_PIV && 260ebccf1e3SJoseph Koshy (logical_cpus_mask & (1 << cpu))) 261ebccf1e3SJoseph Koshy continue; /* skip P4-style 'logical' cpus */ 262ebccf1e3SJoseph Koshy #endif 2635d09484bSJoseph Koshy if (pmc_pmcinfo(cpu, &pi) < 0) { 2645d09484bSJoseph Koshy if (errno == ENXIO) 2655d09484bSJoseph Koshy continue; 266ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to get PMC status for CPU %d", 267ebccf1e3SJoseph Koshy cpu); 2685d09484bSJoseph Koshy } 269ebccf1e3SJoseph Koshy 270ebccf1e3SJoseph Koshy printf("#CPU %d:\n", c++); 271ebccf1e3SJoseph Koshy npmc = pmc_npmc(cpu); 272ebccf1e3SJoseph Koshy printf("#N NAME CLASS STATE ROW-DISP\n"); 273ebccf1e3SJoseph Koshy 274ebccf1e3SJoseph Koshy for (n = 0; n < npmc; n++) { 275ebccf1e3SJoseph Koshy pd = &pi->pm_pmcs[n]; 276ebccf1e3SJoseph Koshy 277ebccf1e3SJoseph Koshy printf(" %-2d %-16s %-6s %-8s %-10s", 278ebccf1e3SJoseph Koshy n, 279ebccf1e3SJoseph Koshy pd->pm_name, 280ebccf1e3SJoseph Koshy pmc_name_of_class(pd->pm_class), 281ebccf1e3SJoseph Koshy pd->pm_enabled ? "ENABLED" : "DISABLED", 282ebccf1e3SJoseph Koshy pmc_name_of_disposition(pd->pm_rowdisp)); 283ebccf1e3SJoseph Koshy 284ebccf1e3SJoseph Koshy if (pd->pm_ownerpid != -1) { 285ebccf1e3SJoseph Koshy printf(" (pid %d)", pd->pm_ownerpid); 286ebccf1e3SJoseph Koshy printf(" %-32s", 287ebccf1e3SJoseph Koshy pmc_name_of_event(pd->pm_event)); 288ebccf1e3SJoseph Koshy if (PMC_IS_SAMPLING_MODE(pd->pm_mode)) 289ebccf1e3SJoseph Koshy printf(" (reload count %jd)", 290ebccf1e3SJoseph Koshy pd->pm_reloadcount); 291ebccf1e3SJoseph Koshy } 292ebccf1e3SJoseph Koshy printf("\n"); 293ebccf1e3SJoseph Koshy } 294ebccf1e3SJoseph Koshy free(pi); 295ebccf1e3SJoseph Koshy } 296ebccf1e3SJoseph Koshy return 0; 297ebccf1e3SJoseph Koshy } 298ebccf1e3SJoseph Koshy 299ebccf1e3SJoseph Koshy static int 300ebccf1e3SJoseph Koshy pmcc_do_list_events(void) 301ebccf1e3SJoseph Koshy { 302ebccf1e3SJoseph Koshy enum pmc_class c; 303ebccf1e3SJoseph Koshy unsigned int i, j, nevents; 304ebccf1e3SJoseph Koshy const char **eventnamelist; 305f263522aSJoseph Koshy const struct pmc_cpuinfo *ci; 306ebccf1e3SJoseph Koshy 307ebccf1e3SJoseph Koshy if (pmc_cpuinfo(&ci) != 0) 308ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to determine CPU information"); 309ebccf1e3SJoseph Koshy 310ebccf1e3SJoseph Koshy eventnamelist = NULL; 311ebccf1e3SJoseph Koshy 312ebccf1e3SJoseph Koshy for (i = 0; i < ci->pm_nclass; i++) { 313c5153e19SJoseph Koshy c = ci->pm_classes[i].pm_class; 314ebccf1e3SJoseph Koshy 315ebccf1e3SJoseph Koshy printf("%s\n", pmc_name_of_class(c)); 316ebccf1e3SJoseph Koshy if (pmc_event_names_of_class(c, &eventnamelist, &nevents) < 0) 317ebccf1e3SJoseph Koshy err(EX_OSERR, "ERROR: Cannot find information for " 318ebccf1e3SJoseph Koshy "event class \"%s\"", pmc_name_of_class(c)); 319ebccf1e3SJoseph Koshy 320ebccf1e3SJoseph Koshy for (j = 0; j < nevents; j++) 321ebccf1e3SJoseph Koshy printf("\t%s\n", eventnamelist[j]); 322ebccf1e3SJoseph Koshy 323ebccf1e3SJoseph Koshy free(eventnamelist); 324ebccf1e3SJoseph Koshy } 325ebccf1e3SJoseph Koshy return 0; 326ebccf1e3SJoseph Koshy } 327ebccf1e3SJoseph Koshy 328ebccf1e3SJoseph Koshy static int 329ebccf1e3SJoseph Koshy pmcc_show_statistics(void) 330ebccf1e3SJoseph Koshy { 331ebccf1e3SJoseph Koshy 332f263522aSJoseph Koshy struct pmc_driverstats gms; 333ebccf1e3SJoseph Koshy 334ebccf1e3SJoseph Koshy if (pmc_get_driver_stats(&gms) < 0) 335ebccf1e3SJoseph Koshy err(EX_OSERR, "ERROR: cannot retrieve driver statistics"); 336ebccf1e3SJoseph Koshy 337ebccf1e3SJoseph Koshy /* 338ebccf1e3SJoseph Koshy * Print statistics. 339ebccf1e3SJoseph Koshy */ 340ebccf1e3SJoseph Koshy 341f263522aSJoseph Koshy #define PRINT(N,V) (void) printf("%-40s %d\n", (N), gms.pm_##V) 342f263522aSJoseph Koshy PRINT("interrupts processed:", intr_processed); 343f263522aSJoseph Koshy PRINT("non-PMC interrupts:", intr_ignored); 344f35f2fc8SJoseph Koshy PRINT("sampling stalls due to space shortages:", intr_bufferfull); 345f263522aSJoseph Koshy PRINT("system calls:", syscalls); 346f263522aSJoseph Koshy PRINT("system calls with errors:", syscall_errors); 347f263522aSJoseph Koshy PRINT("buffer requests:", buffer_requests); 348f263522aSJoseph Koshy PRINT("buffer requests failed:", buffer_requests_failed); 349f263522aSJoseph Koshy PRINT("sampling log sweeps:", log_sweeps); 350ebccf1e3SJoseph Koshy 351ebccf1e3SJoseph Koshy return 0; 352ebccf1e3SJoseph Koshy } 353ebccf1e3SJoseph Koshy 354ebccf1e3SJoseph Koshy /* 355ebccf1e3SJoseph Koshy * Main 356ebccf1e3SJoseph Koshy */ 357ebccf1e3SJoseph Koshy 358ebccf1e3SJoseph Koshy int 359ebccf1e3SJoseph Koshy main(int argc, char **argv) 360ebccf1e3SJoseph Koshy { 361ebccf1e3SJoseph Koshy int error, command, currentcpu, option, pmc; 362ebccf1e3SJoseph Koshy char *dummy; 363ebccf1e3SJoseph Koshy struct pmcc_op *p; 364ebccf1e3SJoseph Koshy 365ebccf1e3SJoseph Koshy #if DEBUG 366ebccf1e3SJoseph Koshy pmcc_init_debug(); 367ebccf1e3SJoseph Koshy #endif 368ebccf1e3SJoseph Koshy 369ebccf1e3SJoseph Koshy /* parse args */ 370ebccf1e3SJoseph Koshy 371ebccf1e3SJoseph Koshy currentcpu = PMCC_CPU_ALL; 372ebccf1e3SJoseph Koshy command = PMCC_PRINT_USAGE; 373ebccf1e3SJoseph Koshy error = 0; 374ebccf1e3SJoseph Koshy 375ebccf1e3SJoseph Koshy STAILQ_INIT(&head); 376ebccf1e3SJoseph Koshy 377ebccf1e3SJoseph Koshy while ((option = getopt(argc, argv, ":c:d:e:lLs")) != -1) 378ebccf1e3SJoseph Koshy switch (option) { 379ebccf1e3SJoseph Koshy case 'L': 380ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE) { 381ebccf1e3SJoseph Koshy error = 1; 382ebccf1e3SJoseph Koshy break; 383ebccf1e3SJoseph Koshy } 384ebccf1e3SJoseph Koshy command = PMCC_PRINT_EVENTS; 385ebccf1e3SJoseph Koshy break; 386ebccf1e3SJoseph Koshy 387ebccf1e3SJoseph Koshy case 'c': 388ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE && 389ebccf1e3SJoseph Koshy command != PMCC_ENABLE_DISABLE) { 390ebccf1e3SJoseph Koshy error = 1; 391ebccf1e3SJoseph Koshy break; 392ebccf1e3SJoseph Koshy } 393ebccf1e3SJoseph Koshy command = PMCC_ENABLE_DISABLE; 394ebccf1e3SJoseph Koshy 395ebccf1e3SJoseph Koshy if (*optarg == PMCC_CPU_WILDCARD) 396ebccf1e3SJoseph Koshy currentcpu = PMCC_CPU_ALL; 397ebccf1e3SJoseph Koshy else { 398ebccf1e3SJoseph Koshy currentcpu = strtoul(optarg, &dummy, 0); 399ebccf1e3SJoseph Koshy if (*dummy != '\0' || currentcpu < 0) 400ebccf1e3SJoseph Koshy errx(EX_DATAERR, 401ebccf1e3SJoseph Koshy "\"%s\" is not a valid CPU id", 402ebccf1e3SJoseph Koshy optarg); 403ebccf1e3SJoseph Koshy } 404ebccf1e3SJoseph Koshy break; 405ebccf1e3SJoseph Koshy 406ebccf1e3SJoseph Koshy case 'd': 407ebccf1e3SJoseph Koshy case 'e': 408ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE && 409ebccf1e3SJoseph Koshy command != PMCC_ENABLE_DISABLE) { 410ebccf1e3SJoseph Koshy error = 1; 411ebccf1e3SJoseph Koshy break; 412ebccf1e3SJoseph Koshy } 413ebccf1e3SJoseph Koshy command = PMCC_ENABLE_DISABLE; 414ebccf1e3SJoseph Koshy 415ebccf1e3SJoseph Koshy if (*optarg == PMCC_PMC_WILDCARD) 416ebccf1e3SJoseph Koshy pmc = PMCC_PMC_ALL; 417ebccf1e3SJoseph Koshy else { 418ebccf1e3SJoseph Koshy pmc = strtoul(optarg, &dummy, 0); 419ebccf1e3SJoseph Koshy if (*dummy != '\0' || pmc < 0) 420ebccf1e3SJoseph Koshy errx(EX_DATAERR, 421ebccf1e3SJoseph Koshy "\"%s\" is not a valid PMC id", 422ebccf1e3SJoseph Koshy optarg); 423ebccf1e3SJoseph Koshy } 424ebccf1e3SJoseph Koshy 425ebccf1e3SJoseph Koshy if ((p = malloc(sizeof(*p))) == NULL) 426ebccf1e3SJoseph Koshy err(EX_SOFTWARE, "Out of memory"); 427ebccf1e3SJoseph Koshy 428ebccf1e3SJoseph Koshy p->op_cpu = currentcpu; 429ebccf1e3SJoseph Koshy p->op_pmc = pmc; 430ebccf1e3SJoseph Koshy p->op_op = option == 'd' ? PMCC_OP_DISABLE : 431ebccf1e3SJoseph Koshy PMCC_OP_ENABLE; 432ebccf1e3SJoseph Koshy 433ebccf1e3SJoseph Koshy STAILQ_INSERT_TAIL(&head, p, op_next); 434ebccf1e3SJoseph Koshy break; 435ebccf1e3SJoseph Koshy 436ebccf1e3SJoseph Koshy case 'l': 437ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE) { 438ebccf1e3SJoseph Koshy error = 1; 439ebccf1e3SJoseph Koshy break; 440ebccf1e3SJoseph Koshy } 441ebccf1e3SJoseph Koshy command = PMCC_LIST_STATE; 442ebccf1e3SJoseph Koshy break; 443ebccf1e3SJoseph Koshy 444ebccf1e3SJoseph Koshy case 's': 445ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE) { 446ebccf1e3SJoseph Koshy error = 1; 447ebccf1e3SJoseph Koshy break; 448ebccf1e3SJoseph Koshy } 449ebccf1e3SJoseph Koshy command = PMCC_SHOW_STATISTICS; 450ebccf1e3SJoseph Koshy break; 451ebccf1e3SJoseph Koshy 452ebccf1e3SJoseph Koshy case ':': 453ebccf1e3SJoseph Koshy errx(EX_USAGE, 454ebccf1e3SJoseph Koshy "Missing argument to option '-%c'", optopt); 455ebccf1e3SJoseph Koshy break; 456ebccf1e3SJoseph Koshy 457ebccf1e3SJoseph Koshy case '?': 458ebccf1e3SJoseph Koshy warnx("Unrecognized option \"-%c\"", optopt); 459ebccf1e3SJoseph Koshy errx(EX_USAGE, usage_message); 460ebccf1e3SJoseph Koshy break; 461ebccf1e3SJoseph Koshy 462ebccf1e3SJoseph Koshy default: 463ebccf1e3SJoseph Koshy error = 1; 464ebccf1e3SJoseph Koshy break; 465ebccf1e3SJoseph Koshy 466ebccf1e3SJoseph Koshy } 467ebccf1e3SJoseph Koshy 468ebccf1e3SJoseph Koshy if (command == PMCC_PRINT_USAGE) 469ebccf1e3SJoseph Koshy (void) errx(EX_USAGE, usage_message); 470ebccf1e3SJoseph Koshy 471ebccf1e3SJoseph Koshy if (error) 472ebccf1e3SJoseph Koshy exit(EX_USAGE); 473ebccf1e3SJoseph Koshy 474ebccf1e3SJoseph Koshy if (pmc_init() < 0) 475ebccf1e3SJoseph Koshy err(EX_UNAVAILABLE, 476ebccf1e3SJoseph Koshy "Initialization of the pmc(3) library failed"); 477ebccf1e3SJoseph Koshy 478ebccf1e3SJoseph Koshy switch (command) { 479ebccf1e3SJoseph Koshy case PMCC_LIST_STATE: 480ebccf1e3SJoseph Koshy error = pmcc_do_list_state(); 481ebccf1e3SJoseph Koshy break; 482ebccf1e3SJoseph Koshy case PMCC_PRINT_EVENTS: 483ebccf1e3SJoseph Koshy error = pmcc_do_list_events(); 484ebccf1e3SJoseph Koshy break; 485ebccf1e3SJoseph Koshy case PMCC_SHOW_STATISTICS: 486ebccf1e3SJoseph Koshy error = pmcc_show_statistics(); 487ebccf1e3SJoseph Koshy break; 488ebccf1e3SJoseph Koshy case PMCC_ENABLE_DISABLE: 489ebccf1e3SJoseph Koshy if (STAILQ_EMPTY(&head)) 490ebccf1e3SJoseph Koshy errx(EX_USAGE, "No PMCs specified to enable or disable"); 491ebccf1e3SJoseph Koshy error = pmcc_do_enable_disable(&head); 492ebccf1e3SJoseph Koshy break; 493ebccf1e3SJoseph Koshy default: 494ebccf1e3SJoseph Koshy assert(0); 495ebccf1e3SJoseph Koshy 496ebccf1e3SJoseph Koshy } 497ebccf1e3SJoseph Koshy 498ebccf1e3SJoseph Koshy if (error != 0) 499ebccf1e3SJoseph Koshy err(EX_OSERR, "Command failed"); 500ebccf1e3SJoseph Koshy exit(0); 501ebccf1e3SJoseph Koshy } 502