[BACK]Return to pctrctl.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / pctrctl

Annotation of src/usr.bin/pctrctl/pctrctl.c, Revision 1.1

1.1     ! dm          1: /*     $OpenBSD$       */
        !             2: /*
        !             3:  * Pentium performance counter driver for OpenBSD.
        !             4:  * Author: David Mazieres <dm@lcs.mit.edu>
        !             5:  */
        !             6:
        !             7: #include <stdio.h>
        !             8: #include <stdlib.h>
        !             9: #include <string.h>
        !            10: #include <sys/types.h>
        !            11: #include <sys/stat.h>
        !            12: #include <sys/ioctl.h>
        !            13: #include <fcntl.h>
        !            14: #include <machine/pctr.h>
        !            15:
        !            16: char *progname;
        !            17:
        !            18: char *pctr_name[] = {
        !            19:   "Data read", /* 0 */
        !            20:   "Data write",
        !            21:   "Data TLB miss",
        !            22:   "Data read miss",
        !            23:   "Data write miss",
        !            24:   "Write (hit) to M or E state lines",
        !            25:   "Data cache lines written back",
        !            26:   "Data cache snoops",
        !            27:   "Data cache snoop hits", /* 8 */
        !            28:   "Memory accesses in both pipes",
        !            29:   "Bank conflicts",
        !            30:   "Misaligned data memory references",
        !            31:   "Code read",
        !            32:   "Code TLB miss",
        !            33:   "Code cache miss",
        !            34:   "Any segment register load",
        !            35:   NULL, /* 0x10 */
        !            36:   NULL,
        !            37:   "Branches",
        !            38:   "BTB hits",
        !            39:   "Taken branch or BTB hit",
        !            40:   "Pipeline flushes",
        !            41:   "Instructions executed",
        !            42:   "Instructions executed in the V-pipe",
        !            43:   "Bus utilization (clocks)", /* 0x18 */
        !            44:   "Pipeline stalled by write backup",
        !            45:   "Pipeline stalled by data memory read",
        !            46:   "Pipeline stalled by write to E or M line",
        !            47:   "Locked bus cycle",
        !            48:   "I/O read or write cycle",
        !            49:   "Noncacheable memory references",
        !            50:   "AGI (Address Generation Interlock)",
        !            51:   NULL, /* 0x20 */
        !            52:   NULL,
        !            53:   "Floating-point operations",
        !            54:   "Breakpoint 0 match",
        !            55:   "Breakpoint 1 match",
        !            56:   "Breakpoint 2 match",
        !            57:   "Breakpoint 3 match",
        !            58:   "Hardware interupts",
        !            59:   "Data read or data write", /* 0x28 */
        !            60:   "Data read miss or data write miss",
        !            61: };
        !            62:
        !            63: static const int pctr_name_size =  (sizeof (pctr_name) / sizeof (char *));
        !            64:
        !            65: /* Print all possible counter functions */
        !            66: static void
        !            67: list (void)
        !            68: {
        !            69:   int i;
        !            70:
        !            71:   printf ("Hardware counter event types:\n");
        !            72:   for (i = 0; i < pctr_name_size; i++)
        !            73:     printf ("  %02x  %s\n", i, pctr_name[i] ? pctr_name[i] : "invalid");
        !            74: }
        !            75:
        !            76: /* Print status of counters */
        !            77: static void
        !            78: readst (void)
        !            79: {
        !            80:   int fd, i;
        !            81:   struct pctrst st;
        !            82:
        !            83:   fd = open (_PATH_PCTR, O_RDONLY);
        !            84:   if (fd < 0) {
        !            85:     perror (_PATH_PCTR);
        !            86:     exit (1);
        !            87:   }
        !            88:   if (ioctl (fd, PCIOCRD, &st) < 0) {
        !            89:     perror ("PCIOCRD");
        !            90:     exit (1);
        !            91:   }
        !            92:   close (fd);
        !            93:
        !            94:   for (i = 0; i < PCTR_NUM; i++)
        !            95:     printf (" ctr%d = %16qd  [%c%c%c %02x (%s)]\n", i, st.pctr_hwc[i],
        !            96:            (st.pctr_fn[i] & PCTR_C) ? 'c' : 'e',
        !            97:            (st.pctr_fn[i] & PCTR_U) ? 'u' : '-',
        !            98:            (st.pctr_fn[i] & PCTR_K) ? 'k' : '-',
        !            99:            (st.pctr_fn[i] & 0x3f),
        !           100:            (((st.pctr_fn[i] & 0x3f) < pctr_name_size
        !           101:              && pctr_name[st.pctr_fn[i] & 0x3f])
        !           102:             ? pctr_name[st.pctr_fn[i] & 0x3f] : "invalid"));
        !           103:   printf ("  tsc = %16qd\n  idl = %16qd\n", st.pctr_tsc, st.pctr_idl);
        !           104: }
        !           105:
        !           106: static void
        !           107: setctr (int ctr, u_short val)
        !           108: {
        !           109:   int fd;
        !           110:
        !           111:   fd = open (_PATH_PCTR, O_WRONLY);
        !           112:   if (fd < 0) {
        !           113:     perror (_PATH_PCTR);
        !           114:     exit (1);
        !           115:   }
        !           116:   if (ioctl (fd, PCIOCS0 + ctr, &val) < 0) {
        !           117:     perror ("PCIOCSn");
        !           118:     exit (1);
        !           119:   }
        !           120:   close (fd);
        !           121: }
        !           122:
        !           123: static void
        !           124: usage (void)
        !           125: {
        !           126:   fprintf (stderr,
        !           127:           "usage: %s [-l | -s ctr [selstr] evtype]\n"
        !           128:           "     -l  list event types\n"
        !           129:           "     -s  set counter <ctr> to monitor events of type <evtype>\n"
        !           130:           "           <selstr> = [e|c][u][k]  (default euk)\n"
        !           131:           "              e - count number of events\n"
        !           132:           "              c - count number of cycles\n"
        !           133:           "              u - count events in user mode (ring 3)\n"
        !           134:           "              k - count events in kernel mode (rings 0-2)\n",
        !           135:           progname);
        !           136:   exit (1);
        !           137: }
        !           138:
        !           139:
        !           140: int
        !           141: main (int argc, char **argv)
        !           142: {
        !           143:   int fd;
        !           144:   u_int ctr;
        !           145:   char *cp;
        !           146:   u_short fn;
        !           147:
        !           148:   if (progname = strrchr (argv[0], '/'))
        !           149:     progname++;
        !           150:   else
        !           151:     progname = argv[0];
        !           152:
        !           153:   if (argc <= 1)
        !           154:     readst ();
        !           155:   else if (argc == 2 && !strcmp (argv[1], "-l"))
        !           156:     list ();
        !           157:   else if (!strcmp (argv[1], "-s") && argc >= 4) {
        !           158:     if (argc > 5)
        !           159:       usage ();
        !           160:     ctr = atoi (argv[2]);
        !           161:     if (ctr >= PCTR_NUM)
        !           162:       usage ();
        !           163:     if (argc == 5) {
        !           164:       fn = strtoul (argv[4], NULL, 16);
        !           165:       if (fn & ~0x3f)
        !           166:        usage ();
        !           167:       for (cp = argv[3]; *cp; cp++) {
        !           168:        switch (*cp) {
        !           169:        case 'c':
        !           170:          fn |= PCTR_C;
        !           171:          break;
        !           172:        case 'e':
        !           173:          fn &= ~PCTR_C;
        !           174:          break;
        !           175:        case 'k':
        !           176:          fn |= PCTR_K;
        !           177:          break;
        !           178:        case 'u':
        !           179:          fn |= PCTR_U;
        !           180:          break;
        !           181:        default:
        !           182:          usage ();
        !           183:        }
        !           184:       }
        !           185:     }
        !           186:     else {
        !           187:       fn = strtoul (argv[3], NULL, 16);
        !           188:       if (fn & ~0x3f)
        !           189:        usage ();
        !           190:       fn |= PCTR_K | PCTR_U;
        !           191:     }
        !           192:     setctr (ctr, fn);
        !           193:   }
        !           194:   else
        !           195:     usage ();
        !           196:
        !           197:   return 0;
        !           198: }