114895Swollman/* 214895Swollman * Copyright 1996 Massachusetts Institute of Technology 314895Swollman * 414895Swollman * Permission to use, copy, modify, and distribute this software and 514895Swollman * its documentation for any purpose and without fee is hereby 614895Swollman * granted, provided that both the above copyright notice and this 714895Swollman * permission notice appear in all copies, that both the above 814895Swollman * copyright notice and this permission notice appear in all 914895Swollman * supporting documentation, and that the name of M.I.T. not be used 1014895Swollman * in advertising or publicity pertaining to distribution of the 1114895Swollman * software without specific, written prior permission. M.I.T. makes 1214895Swollman * no representations about the suitability of this software for any 1314895Swollman * purpose. It is provided "as is" without express or implied 1414895Swollman * warranty. 1514895Swollman * 1614895Swollman * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 1714895Swollman * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 1814895Swollman * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 1914895Swollman * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 2014895Swollman * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2114895Swollman * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2214895Swollman * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 2314895Swollman * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 2414895Swollman * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2514895Swollman * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 2614895Swollman * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2714895Swollman * SUCH DAMAGE. 2814895Swollman * 2950476Speter * $FreeBSD$ 3014895Swollman */ 3114895Swollman 3214895Swollman#include <sys/types.h> 3314895Swollman#include <sys/ioctl.h> 3414895Swollman 35253750Savg#include <machine/cpu.h> 3614895Swollman#include <machine/perfmon.h> 3714895Swollman 3814895Swollman#include <stdio.h> 3914895Swollman#include <stdlib.h> 4014895Swollman#include <string.h> 4114895Swollman#include <err.h> 4214895Swollman#include <unistd.h> 4314895Swollman#include <fcntl.h> 4414895Swollman#include <limits.h> 4514895Swollman#include <errno.h> 4614895Swollman 4714895Swollmanstatic int getnum(const char *, int, int); 4827085Sbdestatic void usage(const char *) __dead2; 4914895Swollman 5014895Swollmanint 5114895Swollmanmain(int argc, char **argv) 5214895Swollman{ 5314895Swollman int c, fd, num; 5414895Swollman int loops, i, sleeptime; 5527085Sbde char *cmd; 5614895Swollman struct pmc pmc; 5714895Swollman struct pmc_tstamp then, now; 5814895Swollman struct pmc_data value; 5914895Swollman quad_t *buf; 6014895Swollman double total; 6114895Swollman 6214895Swollman pmc.pmc_num = 0; 6314895Swollman pmc.pmc_event = 0; 6414895Swollman pmc.pmc_unit = 0; 6514895Swollman pmc.pmc_flags = 0; 6614895Swollman pmc.pmc_mask = 0; 6727085Sbde cmd = NULL; 6814895Swollman loops = 50; 6914895Swollman sleeptime = 0; 7014895Swollman 7127085Sbde while ((c = getopt(argc, argv, "s:l:uoeiU:m:c:")) != -1) { 7214895Swollman switch(c) { 7314895Swollman case 'u': 7414895Swollman pmc.pmc_flags |= PMCF_USR; 7514895Swollman break; 7614895Swollman case 'o': 7714895Swollman pmc.pmc_flags |= PMCF_OS; 7814895Swollman break; 7914895Swollman case 'e': 8014895Swollman pmc.pmc_flags |= PMCF_E; 8114895Swollman break; 8214895Swollman case 'i': 8314895Swollman pmc.pmc_flags |= PMCF_INV; 8414895Swollman break; 8514895Swollman case 'U': 8614895Swollman pmc.pmc_unit = getnum(optarg, 0, 256); 8714895Swollman break; 8814895Swollman case 'm': 8914895Swollman pmc.pmc_mask = getnum(optarg, 0, 256); 9014895Swollman break; 9114895Swollman case 'l': 9214895Swollman loops = getnum(optarg, 1, INT_MAX - 1); 9314895Swollman break; 9414895Swollman case 's': 9514895Swollman sleeptime = getnum(optarg, 0, INT_MAX - 1); 9614895Swollman break; 9727085Sbde case 'c': 9827085Sbde cmd = optarg; 9927085Sbde break; 10014895Swollman default: 10114895Swollman usage(argv[0]); 10214895Swollman } 10314895Swollman } 10414895Swollman 10514895Swollman if (argc - optind != 1) 10614895Swollman usage(argv[0]); 10714895Swollman 10814895Swollman pmc.pmc_event = getnum(argv[optind], 0, 255); 10914895Swollman 11014895Swollman buf = malloc((loops + 1) * sizeof *buf); 11114895Swollman if (!buf) 11214895Swollman err(1, "malloc(%lu)", (unsigned long)(loops +1) * sizeof *buf); 11314895Swollman 11414895Swollman fd = open(_PATH_PERFMON, O_RDWR, 0); 11514895Swollman if (fd < 0) 11614895Swollman err(1, "open: " _PATH_PERFMON); 11714895Swollman 11814895Swollman if (ioctl(fd, PMIOSETUP, &pmc) < 0) 11914895Swollman err(1, "ioctl(PMIOSETUP)"); 12014895Swollman 12114895Swollman if (ioctl(fd, PMIOTSTAMP, &then) < 0) 12214895Swollman err(1, "ioctl(PMIOTSTAMP)"); 12314895Swollman 12414895Swollman num = 0; 12514895Swollman if (ioctl(fd, PMIOSTART, &num) < 0) 12614895Swollman err(1, "ioctl(PMIOSTART)"); 12714895Swollman 12814895Swollman value.pmcd_num = 0; 12914895Swollman for (i = 0; i < loops; i++) { 13014895Swollman if (ioctl(fd, PMIOSTOP, &num) < 0) 13114895Swollman err(1, "ioctl(PMIOSTOP)"); 13214895Swollman if (ioctl(fd, PMIOREAD, &value) < 0) 13314895Swollman err(1, "ioctl(PMIOREAD)"); 13414895Swollman buf[i] = value.pmcd_value; 13514895Swollman if (ioctl(fd, PMIORESET, &value.pmcd_num) < 0) 13614895Swollman err(1, "ioctl(PMIORESET)"); 13714895Swollman if (ioctl(fd, PMIOSTART, &num) < 0) 13814895Swollman err(1, "ioctl(PMIOSTART)"); 13927085Sbde if (sleeptime) 14027085Sbde sleep(sleeptime); 14127085Sbde if (cmd) 14227085Sbde system(cmd); 14314895Swollman } 14414895Swollman 14514895Swollman if (ioctl(fd, PMIOSTOP, &num) < 0) 14614895Swollman err(1, "ioctl(PMIOSTOP)"); 14714895Swollman if (ioctl(fd, PMIOREAD, &value) < 0) 14814895Swollman err(1, "ioctl(PMIOREAD)"); 14914895Swollman buf[i] = value.pmcd_value; 15014895Swollman if (ioctl(fd, PMIOTSTAMP, &now) < 0) 15114895Swollman err(1, "ioctl(PMIOTSTAMP)"); 15214895Swollman 15314895Swollman total = 0; 15414895Swollman for (i = 1; i <= loops; i++) { 15514895Swollman printf("%d: %qd\n", i, buf[i]); 15614895Swollman total += buf[i]; 15714895Swollman } 15814895Swollman printf("total: %f\nmean: %f\n", total, total / loops); 15914895Swollman 16014895Swollman printf("clocks (at %d-MHz): %qd\n", now.pmct_rate, 16114895Swollman now.pmct_value - then.pmct_value); 16214895Swollman 16314895Swollman return 0; 16414895Swollman} 16514895Swollman 16614895Swollmanstatic int 16714895Swollmangetnum(const char *buf, int min, int max) 16814895Swollman{ 16914895Swollman char *ep; 17014895Swollman long l; 17114895Swollman 17214895Swollman errno = 0; 17314895Swollman l = strtol(buf, &ep, 0); 17414895Swollman if (*buf && !*ep && !errno) { 17514895Swollman if (l < min || l > max) { 176209455Skevlo errx(1, "%s: must be between %d and %d", 17714895Swollman buf, min, max); 17814895Swollman } 17914895Swollman return (int)l; 180209455Skevlo } 181209455Skevlo 182209455Skevlo errx(1, "%s: parameter must be an integer", buf); 18314895Swollman} 18414895Swollman 18514895Swollmanstatic void 18614895Swollmanusage(const char *pname) 18714895Swollman{ 18814895Swollman fprintf(stderr, 18927085Sbde "usage: %s [-eiou] [-c command] [-l nloops] [-m mask] [-s sleeptime]\n" 19027085Sbde " [-U unit] counter\n", 19127085Sbde pname); 19214895Swollman exit(1); 19314895Swollman} 194