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" 90ebccf1e3SJoseph Koshy " " PMCC_PROGRAM_NAME " -l\n" 91ebccf1e3SJoseph Koshy " " PMCC_PROGRAM_NAME " -s\n" 92ebccf1e3SJoseph Koshy " " PMCC_PROGRAM_NAME " [-e pmc | -d pmc | -c cpu] ..."; 93ebccf1e3SJoseph Koshy 94ebccf1e3SJoseph Koshy #if DEBUG 95ebccf1e3SJoseph Koshy FILE *debug_stream = NULL; 96ebccf1e3SJoseph Koshy #endif 97ebccf1e3SJoseph Koshy 98ebccf1e3SJoseph Koshy #if DEBUG 99ebccf1e3SJoseph Koshy #define DEBUG_MSG(...) \ 100ebccf1e3SJoseph Koshy (void) fprintf(debug_stream, "[pmccontrol] " __VA_ARGS__); 101ebccf1e3SJoseph Koshy #else 102ebccf1e3SJoseph Koshy #define DEBUG_MSG(m) /* */ 103ebccf1e3SJoseph Koshy #endif /* !DEBUG */ 104ebccf1e3SJoseph Koshy 105ebccf1e3SJoseph Koshy int pmc_syscall = -1; 106ebccf1e3SJoseph Koshy 107ebccf1e3SJoseph Koshy #define PMC_CALL(cmd, params) \ 108ebccf1e3SJoseph Koshy if ((error = syscall(pmc_syscall, PMC_OP_##cmd, (params))) != 0) \ 109ebccf1e3SJoseph Koshy { \ 110ebccf1e3SJoseph Koshy DEBUG_MSG("ERROR: syscall [" #cmd "]"); \ 111ebccf1e3SJoseph Koshy exit(EX_OSERR); \ 112ebccf1e3SJoseph Koshy } 113ebccf1e3SJoseph Koshy 114ebccf1e3SJoseph Koshy #if DEBUG 115ebccf1e3SJoseph Koshy /* log debug messages to a separate file */ 116ebccf1e3SJoseph Koshy static void 117ebccf1e3SJoseph Koshy pmcc_init_debug(void) 118ebccf1e3SJoseph Koshy { 119ebccf1e3SJoseph Koshy char *fn; 120ebccf1e3SJoseph Koshy 121ebccf1e3SJoseph Koshy fn = getenv("PMCCONTROL_DEBUG"); 122ebccf1e3SJoseph Koshy if (fn != NULL) 123ebccf1e3SJoseph Koshy { 124ebccf1e3SJoseph Koshy debug_stream = fopen(fn, "w"); 125ebccf1e3SJoseph Koshy if (debug_stream == NULL) 126ebccf1e3SJoseph Koshy debug_stream = stderr; 127ebccf1e3SJoseph Koshy } else 128ebccf1e3SJoseph Koshy debug_stream = stderr; 129ebccf1e3SJoseph Koshy } 130ebccf1e3SJoseph Koshy #endif 131ebccf1e3SJoseph Koshy 132ebccf1e3SJoseph Koshy static int 133ebccf1e3SJoseph Koshy pmcc_do_enable_disable(struct pmcc_op_list *op_list) 134ebccf1e3SJoseph Koshy { 135ebccf1e3SJoseph Koshy unsigned char op; 136ebccf1e3SJoseph Koshy int c, error, i, j, ncpu, npmc, t; 137ebccf1e3SJoseph Koshy int cpu, pmc; 138ebccf1e3SJoseph Koshy struct pmcc_op *np; 139ebccf1e3SJoseph Koshy unsigned char *map; 140ebccf1e3SJoseph Koshy 141ebccf1e3SJoseph Koshy if ((ncpu = pmc_ncpu()) < 0) 142ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to determine the number of cpus"); 143ebccf1e3SJoseph Koshy 144ebccf1e3SJoseph Koshy /* determine the maximum number of PMCs in any CPU */ 145ebccf1e3SJoseph Koshy npmc = 0; 146ebccf1e3SJoseph Koshy for (c = 0; c < ncpu; c++) { 147ebccf1e3SJoseph Koshy if ((t = pmc_npmc(c)) < 0) 148ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to determine the number of PMCs in " 149ebccf1e3SJoseph Koshy "CPU %d", c); 150ebccf1e3SJoseph Koshy npmc = t > npmc ? t : npmc; 151ebccf1e3SJoseph Koshy } 152ebccf1e3SJoseph Koshy 153ebccf1e3SJoseph Koshy if (npmc == 0) 154ebccf1e3SJoseph Koshy errx(EX_CONFIG, "No PMCs found"); 155ebccf1e3SJoseph Koshy 156ebccf1e3SJoseph Koshy if ((map = malloc(npmc * ncpu)) == NULL) 157ebccf1e3SJoseph Koshy err(EX_SOFTWARE, "Out of memory"); 158ebccf1e3SJoseph Koshy 159ebccf1e3SJoseph Koshy (void) memset(map, PMCC_OP_IGNORE, npmc*ncpu); 160ebccf1e3SJoseph Koshy 161ebccf1e3SJoseph Koshy error = 0; 162ebccf1e3SJoseph Koshy STAILQ_FOREACH(np, op_list, op_next) { 163ebccf1e3SJoseph Koshy 164ebccf1e3SJoseph Koshy cpu = np->op_cpu; 165ebccf1e3SJoseph Koshy pmc = np->op_pmc; 166ebccf1e3SJoseph Koshy op = np->op_op; 167ebccf1e3SJoseph Koshy 168ebccf1e3SJoseph Koshy if (cpu >= ncpu) 169ebccf1e3SJoseph Koshy errx(EX_DATAERR, "CPU id too large: \"%d\"", cpu); 170ebccf1e3SJoseph Koshy 171ebccf1e3SJoseph Koshy if (pmc >= npmc) 172ebccf1e3SJoseph Koshy errx(EX_DATAERR, "PMC id too large: \"%d\"", pmc); 173ebccf1e3SJoseph Koshy 174ebccf1e3SJoseph Koshy #define MARKMAP(M,C,P,V) do { \ 175ebccf1e3SJoseph Koshy *((M) + (C)*npmc + (P)) = (V); \ 176ebccf1e3SJoseph Koshy } while (0) 177ebccf1e3SJoseph Koshy 178ebccf1e3SJoseph Koshy #define SET_PMCS(C,P,V) do { \ 179ebccf1e3SJoseph Koshy if ((P) == PMCC_PMC_ALL) { \ 180ebccf1e3SJoseph Koshy for (j = 0; j < npmc; j++) \ 181ebccf1e3SJoseph Koshy MARKMAP(map, (C), j, (V)); \ 182ebccf1e3SJoseph Koshy } else \ 183ebccf1e3SJoseph Koshy MARKMAP(map, (C), (P), (V)); \ 184ebccf1e3SJoseph Koshy } while (0) 185ebccf1e3SJoseph Koshy 186ebccf1e3SJoseph Koshy #define MAP(M,C,P) (*((M) + (C)*npmc + (P))) 187ebccf1e3SJoseph Koshy 188ebccf1e3SJoseph Koshy if (cpu == PMCC_CPU_ALL) 189ebccf1e3SJoseph Koshy for (i = 0; i < ncpu; i++) 190ebccf1e3SJoseph Koshy SET_PMCS(i, pmc, op); 191ebccf1e3SJoseph Koshy else 192ebccf1e3SJoseph Koshy SET_PMCS(cpu, pmc, op); 193ebccf1e3SJoseph Koshy } 194ebccf1e3SJoseph Koshy 195ebccf1e3SJoseph Koshy /* Configure PMCS */ 196ebccf1e3SJoseph Koshy for (i = 0; i < ncpu; i++) 197ebccf1e3SJoseph Koshy for (j = 0; j < npmc; j++) { 198ebccf1e3SJoseph Koshy unsigned char b; 199ebccf1e3SJoseph Koshy 200ebccf1e3SJoseph Koshy b = MAP(map, i, j); 201ebccf1e3SJoseph Koshy 202ebccf1e3SJoseph Koshy error = 0; 203ebccf1e3SJoseph Koshy 204ebccf1e3SJoseph Koshy if (b == PMCC_OP_ENABLE) 205ebccf1e3SJoseph Koshy error = pmc_enable(i, j); 206ebccf1e3SJoseph Koshy else if (b == PMCC_OP_DISABLE) 207ebccf1e3SJoseph Koshy error = pmc_disable(i, j); 208ebccf1e3SJoseph Koshy 209ebccf1e3SJoseph Koshy if (error < 0) 210ebccf1e3SJoseph Koshy err(EX_OSERR, "%s of PMC %d on CPU %d failed", 211ebccf1e3SJoseph Koshy b == PMCC_OP_ENABLE ? "Enable" : 212ebccf1e3SJoseph Koshy "Disable", j, i); 213ebccf1e3SJoseph Koshy } 214ebccf1e3SJoseph Koshy 215ebccf1e3SJoseph Koshy return error; 216ebccf1e3SJoseph Koshy } 217ebccf1e3SJoseph Koshy 218ebccf1e3SJoseph Koshy static int 219ebccf1e3SJoseph Koshy pmcc_do_list_state(void) 220ebccf1e3SJoseph Koshy { 221ebccf1e3SJoseph Koshy size_t dummy; 222ebccf1e3SJoseph Koshy int c, cpu, n, npmc, ncpu; 223ebccf1e3SJoseph Koshy unsigned int logical_cpus_mask; 224ebccf1e3SJoseph Koshy struct pmc_info *pd; 225ebccf1e3SJoseph Koshy struct pmc_op_getpmcinfo *pi; 226ebccf1e3SJoseph Koshy const struct pmc_op_getcpuinfo *pc; 227ebccf1e3SJoseph Koshy 228ebccf1e3SJoseph Koshy if (pmc_cpuinfo(&pc) != 0) 229ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to determine CPU information"); 230ebccf1e3SJoseph Koshy 231ebccf1e3SJoseph Koshy dummy = sizeof(logical_cpus_mask); 232ebccf1e3SJoseph Koshy if (sysctlbyname("machdep.logical_cpus_mask", &logical_cpus_mask, 233ebccf1e3SJoseph Koshy &dummy, NULL, 0) < 0) 234ebccf1e3SJoseph Koshy logical_cpus_mask = 0; 235ebccf1e3SJoseph Koshy 236ebccf1e3SJoseph Koshy ncpu = pc->pm_ncpu; 237ebccf1e3SJoseph Koshy 238ebccf1e3SJoseph Koshy for (c = cpu = 0; cpu < ncpu; cpu++) { 239ebccf1e3SJoseph Koshy #if i386 240ebccf1e3SJoseph Koshy if (pc->pm_cputype == PMC_CPU_INTEL_PIV && 241ebccf1e3SJoseph Koshy (logical_cpus_mask & (1 << cpu))) 242ebccf1e3SJoseph Koshy continue; /* skip P4-style 'logical' cpus */ 243ebccf1e3SJoseph Koshy #endif 244ebccf1e3SJoseph Koshy if (pmc_pmcinfo(cpu, &pi) < 0) 245ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to get PMC status for CPU %d", 246ebccf1e3SJoseph Koshy cpu); 247ebccf1e3SJoseph Koshy 248ebccf1e3SJoseph Koshy printf("#CPU %d:\n", c++); 249ebccf1e3SJoseph Koshy npmc = pmc_npmc(cpu); 250ebccf1e3SJoseph Koshy printf("#N NAME CLASS STATE ROW-DISP\n"); 251ebccf1e3SJoseph Koshy 252ebccf1e3SJoseph Koshy for (n = 0; n < npmc; n++) { 253ebccf1e3SJoseph Koshy pd = &pi->pm_pmcs[n]; 254ebccf1e3SJoseph Koshy 255ebccf1e3SJoseph Koshy printf(" %-2d %-16s %-6s %-8s %-10s", 256ebccf1e3SJoseph Koshy n, 257ebccf1e3SJoseph Koshy pd->pm_name, 258ebccf1e3SJoseph Koshy pmc_name_of_class(pd->pm_class), 259ebccf1e3SJoseph Koshy pd->pm_enabled ? "ENABLED" : "DISABLED", 260ebccf1e3SJoseph Koshy pmc_name_of_disposition(pd->pm_rowdisp)); 261ebccf1e3SJoseph Koshy 262ebccf1e3SJoseph Koshy if (pd->pm_ownerpid != -1) { 263ebccf1e3SJoseph Koshy printf(" (pid %d)", pd->pm_ownerpid); 264ebccf1e3SJoseph Koshy printf(" %-32s", 265ebccf1e3SJoseph Koshy pmc_name_of_event(pd->pm_event)); 266ebccf1e3SJoseph Koshy if (PMC_IS_SAMPLING_MODE(pd->pm_mode)) 267ebccf1e3SJoseph Koshy printf(" (reload count %jd)", 268ebccf1e3SJoseph Koshy pd->pm_reloadcount); 269ebccf1e3SJoseph Koshy } 270ebccf1e3SJoseph Koshy printf("\n"); 271ebccf1e3SJoseph Koshy } 272ebccf1e3SJoseph Koshy free(pi); 273ebccf1e3SJoseph Koshy } 274ebccf1e3SJoseph Koshy return 0; 275ebccf1e3SJoseph Koshy } 276ebccf1e3SJoseph Koshy 277ebccf1e3SJoseph Koshy static int 278ebccf1e3SJoseph Koshy pmcc_do_list_events(void) 279ebccf1e3SJoseph Koshy { 280ebccf1e3SJoseph Koshy enum pmc_class c; 281ebccf1e3SJoseph Koshy unsigned int i, j, nevents; 282ebccf1e3SJoseph Koshy const char **eventnamelist; 283ebccf1e3SJoseph Koshy const struct pmc_op_getcpuinfo *ci; 284ebccf1e3SJoseph Koshy 285ebccf1e3SJoseph Koshy if (pmc_cpuinfo(&ci) != 0) 286ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to determine CPU information"); 287ebccf1e3SJoseph Koshy 288ebccf1e3SJoseph Koshy eventnamelist = NULL; 289ebccf1e3SJoseph Koshy 290ebccf1e3SJoseph Koshy for (i = 0; i < ci->pm_nclass; i++) { 291ebccf1e3SJoseph Koshy c = ci->pm_classes[i]; 292ebccf1e3SJoseph Koshy 293ebccf1e3SJoseph Koshy printf("%s\n", pmc_name_of_class(c)); 294ebccf1e3SJoseph Koshy if (pmc_event_names_of_class(c, &eventnamelist, &nevents) < 0) 295ebccf1e3SJoseph Koshy err(EX_OSERR, "ERROR: Cannot find information for " 296ebccf1e3SJoseph Koshy "event class \"%s\"", pmc_name_of_class(c)); 297ebccf1e3SJoseph Koshy 298ebccf1e3SJoseph Koshy for (j = 0; j < nevents; j++) 299ebccf1e3SJoseph Koshy printf("\t%s\n", eventnamelist[j]); 300ebccf1e3SJoseph Koshy 301ebccf1e3SJoseph Koshy free(eventnamelist); 302ebccf1e3SJoseph Koshy } 303ebccf1e3SJoseph Koshy return 0; 304ebccf1e3SJoseph Koshy } 305ebccf1e3SJoseph Koshy 306ebccf1e3SJoseph Koshy static int 307ebccf1e3SJoseph Koshy pmcc_show_statistics(void) 308ebccf1e3SJoseph Koshy { 309ebccf1e3SJoseph Koshy 310ebccf1e3SJoseph Koshy struct pmc_op_getdriverstats gms; 311ebccf1e3SJoseph Koshy 312ebccf1e3SJoseph Koshy if (pmc_get_driver_stats(&gms) < 0) 313ebccf1e3SJoseph Koshy err(EX_OSERR, "ERROR: cannot retrieve driver statistics"); 314ebccf1e3SJoseph Koshy 315ebccf1e3SJoseph Koshy /* 316ebccf1e3SJoseph Koshy * Print statistics. 317ebccf1e3SJoseph Koshy */ 318ebccf1e3SJoseph Koshy 319ebccf1e3SJoseph Koshy #define PRINT(N,V) (void) printf("%20s %d\n", (N), gms.pm_##V) 320ebccf1e3SJoseph Koshy 321ebccf1e3SJoseph Koshy PRINT("interrupts-processed", intr_processed); 322ebccf1e3SJoseph Koshy PRINT("interrupts-ignored", intr_ignored); 323ebccf1e3SJoseph Koshy PRINT("system-calls", syscalls); 324ebccf1e3SJoseph Koshy PRINT("system-calls-with-errors", syscall_errors); 325ebccf1e3SJoseph Koshy 326ebccf1e3SJoseph Koshy return 0; 327ebccf1e3SJoseph Koshy } 328ebccf1e3SJoseph Koshy 329ebccf1e3SJoseph Koshy /* 330ebccf1e3SJoseph Koshy * Main 331ebccf1e3SJoseph Koshy */ 332ebccf1e3SJoseph Koshy 333ebccf1e3SJoseph Koshy int 334ebccf1e3SJoseph Koshy main(int argc, char **argv) 335ebccf1e3SJoseph Koshy { 336ebccf1e3SJoseph Koshy int error, command, currentcpu, option, pmc; 337ebccf1e3SJoseph Koshy char *dummy; 338ebccf1e3SJoseph Koshy struct pmcc_op *p; 339ebccf1e3SJoseph Koshy 340ebccf1e3SJoseph Koshy #if DEBUG 341ebccf1e3SJoseph Koshy pmcc_init_debug(); 342ebccf1e3SJoseph Koshy #endif 343ebccf1e3SJoseph Koshy 344ebccf1e3SJoseph Koshy /* parse args */ 345ebccf1e3SJoseph Koshy 346ebccf1e3SJoseph Koshy currentcpu = PMCC_CPU_ALL; 347ebccf1e3SJoseph Koshy command = PMCC_PRINT_USAGE; 348ebccf1e3SJoseph Koshy error = 0; 349ebccf1e3SJoseph Koshy 350ebccf1e3SJoseph Koshy STAILQ_INIT(&head); 351ebccf1e3SJoseph Koshy 352ebccf1e3SJoseph Koshy while ((option = getopt(argc, argv, ":c:d:e:lLs")) != -1) 353ebccf1e3SJoseph Koshy switch (option) { 354ebccf1e3SJoseph Koshy case 'L': 355ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE) { 356ebccf1e3SJoseph Koshy error = 1; 357ebccf1e3SJoseph Koshy break; 358ebccf1e3SJoseph Koshy } 359ebccf1e3SJoseph Koshy command = PMCC_PRINT_EVENTS; 360ebccf1e3SJoseph Koshy break; 361ebccf1e3SJoseph Koshy 362ebccf1e3SJoseph Koshy case 'c': 363ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE && 364ebccf1e3SJoseph Koshy command != PMCC_ENABLE_DISABLE) { 365ebccf1e3SJoseph Koshy error = 1; 366ebccf1e3SJoseph Koshy break; 367ebccf1e3SJoseph Koshy } 368ebccf1e3SJoseph Koshy command = PMCC_ENABLE_DISABLE; 369ebccf1e3SJoseph Koshy 370ebccf1e3SJoseph Koshy if (*optarg == PMCC_CPU_WILDCARD) 371ebccf1e3SJoseph Koshy currentcpu = PMCC_CPU_ALL; 372ebccf1e3SJoseph Koshy else { 373ebccf1e3SJoseph Koshy currentcpu = strtoul(optarg, &dummy, 0); 374ebccf1e3SJoseph Koshy if (*dummy != '\0' || currentcpu < 0) 375ebccf1e3SJoseph Koshy errx(EX_DATAERR, 376ebccf1e3SJoseph Koshy "\"%s\" is not a valid CPU id", 377ebccf1e3SJoseph Koshy optarg); 378ebccf1e3SJoseph Koshy } 379ebccf1e3SJoseph Koshy break; 380ebccf1e3SJoseph Koshy 381ebccf1e3SJoseph Koshy case 'd': 382ebccf1e3SJoseph Koshy case 'e': 383ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE && 384ebccf1e3SJoseph Koshy command != PMCC_ENABLE_DISABLE) { 385ebccf1e3SJoseph Koshy error = 1; 386ebccf1e3SJoseph Koshy break; 387ebccf1e3SJoseph Koshy } 388ebccf1e3SJoseph Koshy command = PMCC_ENABLE_DISABLE; 389ebccf1e3SJoseph Koshy 390ebccf1e3SJoseph Koshy if (*optarg == PMCC_PMC_WILDCARD) 391ebccf1e3SJoseph Koshy pmc = PMCC_PMC_ALL; 392ebccf1e3SJoseph Koshy else { 393ebccf1e3SJoseph Koshy pmc = strtoul(optarg, &dummy, 0); 394ebccf1e3SJoseph Koshy if (*dummy != '\0' || pmc < 0) 395ebccf1e3SJoseph Koshy errx(EX_DATAERR, 396ebccf1e3SJoseph Koshy "\"%s\" is not a valid PMC id", 397ebccf1e3SJoseph Koshy optarg); 398ebccf1e3SJoseph Koshy } 399ebccf1e3SJoseph Koshy 400ebccf1e3SJoseph Koshy if ((p = malloc(sizeof(*p))) == NULL) 401ebccf1e3SJoseph Koshy err(EX_SOFTWARE, "Out of memory"); 402ebccf1e3SJoseph Koshy 403ebccf1e3SJoseph Koshy p->op_cpu = currentcpu; 404ebccf1e3SJoseph Koshy p->op_pmc = pmc; 405ebccf1e3SJoseph Koshy p->op_op = option == 'd' ? PMCC_OP_DISABLE : 406ebccf1e3SJoseph Koshy PMCC_OP_ENABLE; 407ebccf1e3SJoseph Koshy 408ebccf1e3SJoseph Koshy STAILQ_INSERT_TAIL(&head, p, op_next); 409ebccf1e3SJoseph Koshy break; 410ebccf1e3SJoseph Koshy 411ebccf1e3SJoseph Koshy case 'l': 412ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE) { 413ebccf1e3SJoseph Koshy error = 1; 414ebccf1e3SJoseph Koshy break; 415ebccf1e3SJoseph Koshy } 416ebccf1e3SJoseph Koshy command = PMCC_LIST_STATE; 417ebccf1e3SJoseph Koshy break; 418ebccf1e3SJoseph Koshy 419ebccf1e3SJoseph Koshy case 's': 420ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE) { 421ebccf1e3SJoseph Koshy error = 1; 422ebccf1e3SJoseph Koshy break; 423ebccf1e3SJoseph Koshy } 424ebccf1e3SJoseph Koshy command = PMCC_SHOW_STATISTICS; 425ebccf1e3SJoseph Koshy break; 426ebccf1e3SJoseph Koshy 427ebccf1e3SJoseph Koshy case ':': 428ebccf1e3SJoseph Koshy errx(EX_USAGE, 429ebccf1e3SJoseph Koshy "Missing argument to option '-%c'", optopt); 430ebccf1e3SJoseph Koshy break; 431ebccf1e3SJoseph Koshy 432ebccf1e3SJoseph Koshy case '?': 433ebccf1e3SJoseph Koshy warnx("Unrecognized option \"-%c\"", optopt); 434ebccf1e3SJoseph Koshy errx(EX_USAGE, usage_message); 435ebccf1e3SJoseph Koshy break; 436ebccf1e3SJoseph Koshy 437ebccf1e3SJoseph Koshy default: 438ebccf1e3SJoseph Koshy error = 1; 439ebccf1e3SJoseph Koshy break; 440ebccf1e3SJoseph Koshy 441ebccf1e3SJoseph Koshy } 442ebccf1e3SJoseph Koshy 443ebccf1e3SJoseph Koshy if (command == PMCC_PRINT_USAGE) 444ebccf1e3SJoseph Koshy (void) errx(EX_USAGE, usage_message); 445ebccf1e3SJoseph Koshy 446ebccf1e3SJoseph Koshy if (error) 447ebccf1e3SJoseph Koshy exit(EX_USAGE); 448ebccf1e3SJoseph Koshy 449ebccf1e3SJoseph Koshy if (pmc_init() < 0) 450ebccf1e3SJoseph Koshy err(EX_UNAVAILABLE, 451ebccf1e3SJoseph Koshy "Initialization of the pmc(3) library failed"); 452ebccf1e3SJoseph Koshy 453ebccf1e3SJoseph Koshy switch (command) { 454ebccf1e3SJoseph Koshy case PMCC_LIST_STATE: 455ebccf1e3SJoseph Koshy error = pmcc_do_list_state(); 456ebccf1e3SJoseph Koshy break; 457ebccf1e3SJoseph Koshy case PMCC_PRINT_EVENTS: 458ebccf1e3SJoseph Koshy error = pmcc_do_list_events(); 459ebccf1e3SJoseph Koshy break; 460ebccf1e3SJoseph Koshy case PMCC_SHOW_STATISTICS: 461ebccf1e3SJoseph Koshy error = pmcc_show_statistics(); 462ebccf1e3SJoseph Koshy break; 463ebccf1e3SJoseph Koshy case PMCC_ENABLE_DISABLE: 464ebccf1e3SJoseph Koshy if (STAILQ_EMPTY(&head)) 465ebccf1e3SJoseph Koshy errx(EX_USAGE, "No PMCs specified to enable or disable"); 466ebccf1e3SJoseph Koshy error = pmcc_do_enable_disable(&head); 467ebccf1e3SJoseph Koshy break; 468ebccf1e3SJoseph Koshy default: 469ebccf1e3SJoseph Koshy assert(0); 470ebccf1e3SJoseph Koshy 471ebccf1e3SJoseph Koshy } 472ebccf1e3SJoseph Koshy 473ebccf1e3SJoseph Koshy if (error != 0) 474ebccf1e3SJoseph Koshy err(EX_OSERR, "Command failed"); 475ebccf1e3SJoseph Koshy exit(0); 476ebccf1e3SJoseph Koshy } 477