[BACK]Return to pctr.c CVS log [TXT][DIR] Up to [local] / sys / arch / i386 / i386

Annotation of sys/arch/i386/i386/pctr.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: pctr.c,v 1.22 2006/11/29 20:03:20 dim Exp $   */
        !             2:
        !             3: /*
        !             4:  * Pentium performance counter driver for OpenBSD.
        !             5:  * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
        !             6:  *
        !             7:  * Modification and redistribution in source and binary forms is
        !             8:  * permitted provided that due credit is given to the author and the
        !             9:  * OpenBSD project by leaving this copyright notice intact.
        !            10:  */
        !            11:
        !            12: #include <sys/param.h>
        !            13: #include <sys/types.h>
        !            14: #include <sys/errno.h>
        !            15: #include <sys/fcntl.h>
        !            16: #include <sys/ioccom.h>
        !            17: #include <sys/systm.h>
        !            18:
        !            19: #include <machine/cputypes.h>
        !            20: #include <machine/psl.h>
        !            21: #include <machine/pctr.h>
        !            22: #include <machine/cpu.h>
        !            23: #include <machine/specialreg.h>
        !            24:
        !            25: pctrval pctr_idlcnt;  /* Gets incremented in locore.s */
        !            26:
        !            27: int pctr_isintel;
        !            28:
        !            29: #define usetsc         (cpu_feature & CPUID_TSC)
        !            30: #define usep5ctr       (pctr_isintel && (((cpu_id >> 8) & 15) == 5) && \
        !            31:                                (((cpu_id >> 4) & 15) > 0))
        !            32: #define usep6ctr       (pctr_isintel && ((cpu_id >> 8) & 15) == 6)
        !            33:
        !            34: void pctrattach(int);
        !            35: int pctropen(dev_t, int, int, struct proc *);
        !            36: int pctrclose(dev_t, int, int, struct proc *);
        !            37: int pctrioctl(dev_t, u_long, caddr_t, int, struct proc *);
        !            38: int p5ctrsel(int fflag, u_int cmd, u_int fn);
        !            39: static __inline void p5ctrrd(struct pctrst *st);
        !            40: int p6ctrsel(int fflag, u_int cmd, u_int fn);
        !            41: static __inline void p6ctrrd(struct pctrst *st);
        !            42:
        !            43: void
        !            44: pctrattach(int num)
        !            45: {
        !            46:        if (num > 1)
        !            47:                return;
        !            48:
        !            49:        pctr_isintel = (strcmp(cpu_vendor, "GenuineIntel") == 0);
        !            50:
        !            51:        if (usep6ctr)
        !            52:                /* Enable RDTSC and RDPMC instructions from user-level. */
        !            53:                __asm __volatile ("movl %%cr4,%%eax\n"
        !            54:                                  "\tandl %0,%%eax\n"
        !            55:                                  "\torl %1,%%eax\n"
        !            56:                                  "\tmovl %%eax,%%cr4"
        !            57:                                  :: "i" (~CR4_TSD), "i" (CR4_PCE) : "eax");
        !            58:        else if (usetsc)
        !            59:                /* Enable RDTSC instruction from user-level. */
        !            60:                __asm __volatile ("movl %%cr4,%%eax\n"
        !            61:                                  "\tandl %0,%%eax\n"
        !            62:                                  "\tmovl %%eax,%%cr4"
        !            63:                                  :: "i" (~CR4_TSD) : "eax");
        !            64:
        !            65:        if (usep6ctr)
        !            66:                printf("pctr: 686-class user-level performance counters enabled\n");
        !            67:        else if (usep5ctr)
        !            68:                printf("pctr: 586-class performance counters and user-level cycle counter enabled\n");
        !            69:        else if (usetsc)
        !            70:                printf("pctr: user-level cycle counter enabled\n");
        !            71:        else
        !            72:                printf("pctr: no performance counters in CPU\n");
        !            73: }
        !            74:
        !            75: int
        !            76: pctropen(dev_t dev, int oflags, int devtype, struct proc *p)
        !            77: {
        !            78:        if (minor(dev))
        !            79:                return ENXIO;
        !            80:        return 0;
        !            81: }
        !            82:
        !            83: int
        !            84: pctrclose(dev_t dev, int oflags, int devtype, struct proc *p)
        !            85: {
        !            86:        return 0;
        !            87: }
        !            88:
        !            89: int
        !            90: p5ctrsel(int fflag, u_int cmd, u_int fn)
        !            91: {
        !            92:        pctrval msr11;
        !            93:        int msr;
        !            94:        int shift;
        !            95:
        !            96:        cmd -= PCIOCS0;
        !            97:        if (cmd > 1)
        !            98:                return EINVAL;
        !            99:        msr = P5MSR_CTR0 + cmd;
        !           100:        shift = cmd ? 0x10 : 0;
        !           101:
        !           102:        if (!(fflag & FWRITE))
        !           103:                return EPERM;
        !           104:        if (fn >= 0x200)
        !           105:                return EINVAL;
        !           106:
        !           107:        msr11 = rdmsr(P5MSR_CTRSEL);
        !           108:        msr11 &= ~(0x1ffLL << shift);
        !           109:        msr11 |= fn << shift;
        !           110:        wrmsr(P5MSR_CTRSEL, msr11);
        !           111:        wrmsr(msr, 0);
        !           112:
        !           113:        return 0;
        !           114: }
        !           115:
        !           116: static __inline void
        !           117: p5ctrrd(struct pctrst *st)
        !           118: {
        !           119:        u_int msr11;
        !           120:
        !           121:        msr11 = rdmsr(P5MSR_CTRSEL);
        !           122:        st->pctr_fn[0] = msr11 & 0xffff;
        !           123:        st->pctr_fn[1] = msr11 >> 16;
        !           124:        __asm __volatile("cli");
        !           125:        st->pctr_tsc = rdtsc();
        !           126:        st->pctr_hwc[0] = rdmsr(P5MSR_CTR0);
        !           127:        st->pctr_hwc[1] = rdmsr(P5MSR_CTR1);
        !           128:        __asm __volatile("sti");
        !           129: }
        !           130:
        !           131: int
        !           132: p6ctrsel(int fflag, u_int cmd, u_int fn)
        !           133: {
        !           134:        int msrsel, msrval;
        !           135:
        !           136:        cmd -= PCIOCS0;
        !           137:        if (cmd > 1)
        !           138:                return EINVAL;
        !           139:        msrsel = P6MSR_CTRSEL0 + cmd;
        !           140:        msrval = P6MSR_CTR0 + cmd;
        !           141:
        !           142:        if (!(fflag & FWRITE))
        !           143:                return EPERM;
        !           144:        if (fn & 0x380000)
        !           145:                return EINVAL;
        !           146:
        !           147:        wrmsr(msrval, 0);
        !           148:        wrmsr(msrsel, fn);
        !           149:        wrmsr(msrval, 0);
        !           150:
        !           151:        return 0;
        !           152: }
        !           153:
        !           154: static __inline void
        !           155: p6ctrrd(struct pctrst *st)
        !           156: {
        !           157:        st->pctr_fn[0] = rdmsr(P6MSR_CTRSEL0);
        !           158:        st->pctr_fn[1] = rdmsr(P6MSR_CTRSEL1);
        !           159:        __asm __volatile("cli");
        !           160:        st->pctr_tsc = rdtsc();
        !           161:        st->pctr_hwc[0] = rdpmc(0);
        !           162:        st->pctr_hwc[1] = rdpmc(1);
        !           163:        __asm __volatile("sti");
        !           164: }
        !           165:
        !           166:
        !           167: int
        !           168: pctrioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
        !           169: {
        !           170:        switch (cmd) {
        !           171:        case PCIOCRD:
        !           172:        {
        !           173:                struct pctrst *st = (void *)data;
        !           174:
        !           175:                if (usep6ctr)
        !           176:                        p6ctrrd(st);
        !           177:                else if (usep5ctr)
        !           178:                        p5ctrrd(st);
        !           179:                else {
        !           180:                        bzero(st, sizeof(*st));
        !           181:                        if (usetsc)
        !           182:                                st->pctr_tsc = rdtsc();
        !           183:                }
        !           184:                st->pctr_idl = pctr_idlcnt;
        !           185:                return 0;
        !           186:        }
        !           187:        case PCIOCS0:
        !           188:        case PCIOCS1:
        !           189:                if (usep6ctr)
        !           190:                        return p6ctrsel(fflag, cmd, *(u_int *) data);
        !           191:                if (usep5ctr)
        !           192:                        return p5ctrsel(fflag, cmd, *(u_int *) data);
        !           193:                return ENODEV;
        !           194:        default:
        !           195:                return EINVAL;
        !           196:        }
        !           197: }

CVSweb