summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2007-10-17 02:30:27 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2007-10-17 02:30:27 +0000
commit50b7fa8fe5aa9486f8fada4e0dcbffb37eea55f2 (patch)
tree8bc086a16b979277effdafe153b6fc8d4c0d1466 /sys
parentf9dca81d94e6150016691976b1ed162697e92bc2 (diff)
replacement for the pctr codebase that can handle amd64 processors as
well (in fact, all 4 combinations of codebase and processor) written by Mike Belopuhov and Aleksey Lomovtsev
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/amd64/amd64/machdep.c4
-rw-r--r--sys/arch/amd64/amd64/pctr.c42
-rw-r--r--sys/arch/amd64/include/pctr.h84
-rw-r--r--sys/arch/i386/i386/pctr.c167
-rw-r--r--sys/arch/i386/include/pctr.h92
-rw-r--r--sys/arch/i386/include/specialreg.h10
6 files changed, 223 insertions, 176 deletions
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index e37a9b647ef..677b286a7cd 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.61 2007/08/26 18:54:37 kettenis Exp $ */
+/* $OpenBSD: machdep.c,v 1.62 2007/10/17 02:30:26 deraadt Exp $ */
/* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
/*-
@@ -536,6 +536,8 @@ cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
newp, newlen, p);
case CPU_CPUVENDOR:
return (sysctl_rdstring(oldp, oldlenp, newp, cpu_vendor));
+ case CPU_CPUID:
+ return (sysctl_rdint(oldp, oldlenp, newp, cpu_id));
case CPU_CPUFEATURE:
return (sysctl_rdint(oldp, oldlenp, newp, cpu_feature));
case CPU_KBDRESET:
diff --git a/sys/arch/amd64/amd64/pctr.c b/sys/arch/amd64/amd64/pctr.c
index 3efe16604cb..975a9d3e6a5 100644
--- a/sys/arch/amd64/amd64/pctr.c
+++ b/sys/arch/amd64/amd64/pctr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pctr.c,v 1.1 2007/09/12 18:18:27 deraadt Exp $ */
+/* $OpenBSD: pctr.c,v 1.2 2007/10/17 02:30:26 deraadt Exp $ */
/*
* Copyright (c) 2007 Mike Belopuhov
@@ -35,11 +35,14 @@
#include <machine/psl.h>
#include <machine/pctr.h>
#include <machine/cpu.h>
-#include <machine/cpufunc.h>
#include <machine/specialreg.h>
-/* Check for Model Specific Registers and RDMSR/WRMSR support */
-#define usepctr (cpu_feature & CPUID_MSR)
+#define PCTR_AMD_NUM PCTR_NUM
+#define PCTR_INTEL_NUM 2 /* Intel supports only 2 counters */
+
+#define usetsc (cpu_feature & CPUID_TSC)
+#define usepctr ((pctr_isamd || pctr_isintel) && \
+ ((cpu_id >> 8) & 15) >= 6)
u_int64_t pctr_idlcnt; /* Gets incremented in locore.S */
@@ -47,6 +50,7 @@ int pctr_isamd;
int pctr_isintel;
static void pctrrd(struct pctrst *);
+static int pctrsel(int, u_int32_t, u_int32_t);
static void
pctrrd(struct pctrst *st)
@@ -55,20 +59,12 @@ pctrrd(struct pctrst *st)
num = pctr_isamd ? PCTR_AMD_NUM : PCTR_INTEL_NUM;
reg = pctr_isamd ? MSR_K7_EVNTSEL0 : MSR_EVNTSEL0;
-
for (i = 0; i < num; i++)
st->pctr_fn[i] = rdmsr(reg + i);
-
- reg = pctr_isamd ? MSR_K7_PERFCTR0 : MSR_PERFCTR0;
-
__asm __volatile("cli");
-
st->pctr_tsc = rdtsc();
-
for (i = 0; i < num; i++)
- st->pctr_hwc[i] = rdmsr(reg + i);
- /*st->pctr_hwc[i] = rdpmc(i);*/
-
+ st->pctr_hwc[i] = rdpmc(i);
__asm __volatile("sti");
}
@@ -82,17 +78,22 @@ pctrattach(int num)
pctr_isamd = (strcmp(cpu_vendor, "AuthenticAMD") == 0);
if (!pctr_isamd)
pctr_isintel = (strcmp(cpu_vendor, "GenuineIntel") == 0);
- if (!pctr_isintel && !pctr_isamd)
- return;
- /* Enable RDTSC and RDPMC instructions from user-level. */
if (usepctr) {
+ /* Enable RDTSC and RDPMC instructions from user-level. */
__asm __volatile("movq %%cr4,%%rax\n"
"\tandq %0,%%rax\n"
"\torq %1,%%rax\n"
"\tmovq %%rax,%%cr4"
:: "i" (~CR4_TSD), "i" (CR4_PCE) : "rax");
printf("pctr: user-level performance counters enabled\n");
+ } else if (usetsc) {
+ /* Enable RDTSC instruction from user-level. */
+ __asm __volatile("movq %%cr4,%%rax\n"
+ "\tandq %0,%%rax\n"
+ "\tmovq %%rax,%%cr4"
+ :: "i" (~CR4_TSD) : "rax");
+ printf("pctr: user-level cycle counter enabled\n");
}
}
@@ -112,7 +113,7 @@ pctrclose(dev_t dev, int oflags, int devtype, struct proc *p)
return (0);
}
-int
+static int
pctrsel(int fflag, u_int32_t cmd, u_int32_t fn)
{
int msrsel, msrval;
@@ -143,9 +144,8 @@ pctrsel(int fflag, u_int32_t cmd, u_int32_t fn)
}
int
-pctrioctl(dev_t dev, u_int64_t cmd, caddr_t data, int fflag, struct proc *p)
+pctrioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
{
-
switch (cmd) {
case PCIOCRD:
{
@@ -153,6 +153,8 @@ pctrioctl(dev_t dev, u_int64_t cmd, caddr_t data, int fflag, struct proc *p)
if (usepctr)
pctrrd(st);
+ else if (usetsc)
+ st->pctr_tsc = rdtsc();
st->pctr_idl = pctr_idlcnt;
return (0);
}
@@ -161,7 +163,7 @@ pctrioctl(dev_t dev, u_int64_t cmd, caddr_t data, int fflag, struct proc *p)
case PCIOCS2:
case PCIOCS3:
if (usepctr)
- return (pctrsel(fflag, cmd, *(u_int32_t *)data));
+ return (pctrsel(fflag, cmd, *(u_int *)data));
return (ENODEV);
default:
return (EINVAL);
diff --git a/sys/arch/amd64/include/pctr.h b/sys/arch/amd64/include/pctr.h
index 35c651ebffd..18e7f6fc14e 100644
--- a/sys/arch/amd64/include/pctr.h
+++ b/sys/arch/amd64/include/pctr.h
@@ -1,20 +1,4 @@
-/* $OpenBSD: pctr.h,v 1.1 2007/09/12 18:18:27 deraadt Exp $ */
-
-/*
- * Copyright (c) 2007 Mike Belopuhov
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
+/* $OpenBSD: pctr.h,v 1.2 2007/10/17 02:30:26 deraadt Exp $ */
/*
* Pentium performance counter driver for OpenBSD.
@@ -30,15 +14,15 @@
#include <sys/ioccom.h>
+typedef u_int64_t pctrval;
+
#define PCTR_NUM 4
-#define PCTR_AMD_NUM PCTR_NUM
-#define PCTR_INTEL_NUM 2 /* Intel supports only 2 counters */
struct pctrst {
- u_int64_t pctr_hwc[PCTR_NUM]; /* Values of the hardware counters */
- u_int64_t pctr_tsc; /* Free-running 64-bit cycle counter */
- u_int64_t pctr_idl; /* Iterations of the idle loop */
- u_int32_t pctr_fn[PCTR_NUM]; /* Current settings of counters */
+ u_int pctr_fn[PCTR_NUM]; /* Current settings of counters */
+ pctrval pctr_tsc; /* Free-running 64-bit cycle counter */
+ pctrval pctr_hwc[PCTR_NUM]; /* Values of the hardware counters */
+ pctrval pctr_idl; /* Iterations of the idle loop */
};
/* Bit values in fn fields and PIOCS ioctl's */
@@ -48,16 +32,18 @@ struct pctrst {
#define PCTR_EN 0x400000 /* Enable counters (counter 0 only) */
#define PCTR_I 0x800000 /* Invert counter mask */
-/* Unit Mask bits */
-#define PCTR_UM_M 0x10 /* Modified cache lines */
-#define PCTR_UM_O 0x08 /* Owned cache lines */
-#define PCTR_UM_E 0x04 /* Exclusive cache lines */
-#define PCTR_UM_S 0x02 /* Shared cache lines */
-#define PCTR_UM_I 0x01 /* Invalid cache lines */
-#define PCTR_UM_MESI (PCTR_UM_O|PCTR_UM_E|PCTR_UM_S|PCTR_UM_I)
-#define PCTR_UM_MOESI (PCTR_UM_M|PCTR_UM_O|PCTR_UM_E|PCTR_UM_S|PCTR_UM_I)
+/* Unit Mask values to distinguish cache coherent states */
+#define PCTR_UM_M 0x0800 /* Modified cache lines */
+#define PCTR_UM_E 0x0400 /* Exclusive cache lines */
+#define PCTR_UM_S 0x0200 /* Shared cache lines */
+#define PCTR_UM_I 0x0100 /* Invalid cache lines */
+#define PCTR_UM_MESI (PCTR_UM_M|PCTR_UM_E|PCTR_UM_S|PCTR_UM_I)
+#define PCTR_UM_A 0x2000 /* Any initiator */
-/* ioctl to set which counter a device tracks. */
+#define PCTR_UM_SHIFT 8 /* Left shift for unit mask */
+#define PCTR_CM_SHIFT 24 /* Left shift for counter mask */
+
+/* ioctl to set which counter a device tracks */
#define PCIOCRD _IOR('c', 1, struct pctrst) /* Read counter value */
#define PCIOCS0 _IOW('c', 8, unsigned int) /* Set counter 0 function */
#define PCIOCS1 _IOW('c', 9, unsigned int) /* Set counter 1 function */
@@ -66,13 +52,43 @@ struct pctrst {
#define _PATH_PCTR "/dev/pctr"
+#define rdtsc() \
+({ \
+ u_int32_t hi, lo; \
+ __asm __volatile("rdtsc" : "=d" (hi), "=a" (lo)); \
+ ((u_int64_t)hi << 32) | (u_int64_t)lo; \
+})
+
+#define rdpmc(pmc) \
+({ \
+ u_int32_t hi, lo; \
+ __asm __volatile("rdpmc" \
+ : "=d" (hi), "=a" (lo) : "c" (pmc)); \
+ hi &= 0xffffff; \
+ (((u_int64_t)hi << 32) | (u_int64_t)lo); \
+})
+
#ifdef _KERNEL
+#define rdmsr(msr) \
+({ \
+ u_int32_t hi, lo; \
+ __asm __volatile("rdmsr" \
+ : "=d" (hi), "=a" (lo) : "c" (msr)); \
+ ((u_int64_t)hi << 32) | (u_int64_t) lo; \
+})
+
+#define wrmsr(msr, v) \
+({ \
+ __asm __volatile("wrmsr" : \
+ : "a" ((u_int64_t)v & 0xffffffff), \
+ "d" ((u_int64_t)v >> 32), "c" (msr)); \
+})
+
void pctrattach(int);
int pctropen(dev_t, int, int, struct proc *);
int pctrclose(dev_t, int, int, struct proc *);
-int pctrioctl(dev_t, u_int64_t, caddr_t, int, struct proc *);
-int pctrsel(int fflag, u_int32_t, u_int32_t);
+int pctrioctl(dev_t, u_long, caddr_t, int, struct proc *);
#endif /* _KERNEL */
#endif /* ! _AMD64_PCTR_H_ */
diff --git a/sys/arch/i386/i386/pctr.c b/sys/arch/i386/i386/pctr.c
index bc04c0cc5c8..3eb1f869026 100644
--- a/sys/arch/i386/i386/pctr.c
+++ b/sys/arch/i386/i386/pctr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pctr.c,v 1.22 2006/11/29 20:03:20 dim Exp $ */
+/* $OpenBSD: pctr.c,v 1.23 2007/10/17 02:30:25 deraadt Exp $ */
/*
* Pentium performance counter driver for OpenBSD.
@@ -22,87 +22,119 @@
#include <machine/cpu.h>
#include <machine/specialreg.h>
-pctrval pctr_idlcnt; /* Gets incremented in locore.s */
-
-int pctr_isintel;
+#define PCTR_AMD_NUM PCTR_NUM
+#define PCTR_INTEL_NUM 2 /* Intel supports only 2 counters */
#define usetsc (cpu_feature & CPUID_TSC)
#define usep5ctr (pctr_isintel && (((cpu_id >> 8) & 15) == 5) && \
(((cpu_id >> 4) & 15) > 0))
-#define usep6ctr (pctr_isintel && ((cpu_id >> 8) & 15) == 6)
+#define usepctr ((pctr_isamd || pctr_isintel) && \
+ ((cpu_id >> 8) & 15) >= 6)
+
+u_int64_t pctr_idlcnt; /* Gets incremented in locore.S */
+
+int pctr_isamd;
+int pctr_isintel;
+
+static int p5ctrsel(int fflag, u_int cmd, u_int fn);
+static int pctrsel(int fflag, u_int cmd, u_int fn);
+static void pctrrd(struct pctrst *);
+static void pctrrd(struct pctrst *);
+
+static void
+p5ctrrd(struct pctrst *st)
+{
+ u_int msr11;
+
+ msr11 = rdmsr(P5MSR_CTRSEL);
+ st->pctr_fn[0] = msr11 & 0xffff;
+ st->pctr_fn[1] = msr11 >> 16;
+ __asm __volatile("cli");
+ st->pctr_tsc = rdtsc();
+ st->pctr_hwc[0] = rdmsr(P5MSR_CTR0);
+ st->pctr_hwc[1] = rdmsr(P5MSR_CTR1);
+ __asm __volatile("sti");
+}
-void pctrattach(int);
-int pctropen(dev_t, int, int, struct proc *);
-int pctrclose(dev_t, int, int, struct proc *);
-int pctrioctl(dev_t, u_long, caddr_t, int, struct proc *);
-int p5ctrsel(int fflag, u_int cmd, u_int fn);
-static __inline void p5ctrrd(struct pctrst *st);
-int p6ctrsel(int fflag, u_int cmd, u_int fn);
-static __inline void p6ctrrd(struct pctrst *st);
+static void
+pctrrd(struct pctrst *st)
+{
+ int i, num, reg;
+
+ num = pctr_isamd ? PCTR_AMD_NUM : PCTR_INTEL_NUM;
+ reg = pctr_isamd ? MSR_K7_EVNTSEL0 : P6MSR_CTRSEL0;
+ for (i = 0; i < num; i++)
+ st->pctr_fn[i] = rdmsr(reg + i);
+ __asm __volatile("cli");
+ st->pctr_tsc = rdtsc();
+ for (i = 0; i < num; i++)
+ st->pctr_hwc[i] = rdpmc(i);
+ __asm __volatile("sti");
+}
void
pctrattach(int num)
{
+
if (num > 1)
return;
- pctr_isintel = (strcmp(cpu_vendor, "GenuineIntel") == 0);
+ pctr_isamd = (strcmp(cpu_vendor, "AuthenticAMD") == 0);
+ if (!pctr_isamd)
+ pctr_isintel = (strcmp(cpu_vendor, "GenuineIntel") == 0);
- if (usep6ctr)
+ if (usepctr) {
/* Enable RDTSC and RDPMC instructions from user-level. */
__asm __volatile ("movl %%cr4,%%eax\n"
"\tandl %0,%%eax\n"
"\torl %1,%%eax\n"
"\tmovl %%eax,%%cr4"
:: "i" (~CR4_TSD), "i" (CR4_PCE) : "eax");
- else if (usetsc)
+ printf("pctr: user-level performance counters enabled\n");
+ } else if (usetsc) {
/* Enable RDTSC instruction from user-level. */
__asm __volatile ("movl %%cr4,%%eax\n"
"\tandl %0,%%eax\n"
"\tmovl %%eax,%%cr4"
:: "i" (~CR4_TSD) : "eax");
-
- if (usep6ctr)
- printf("pctr: 686-class user-level performance counters enabled\n");
- else if (usep5ctr)
- printf("pctr: 586-class performance counters and user-level cycle counter enabled\n");
- else if (usetsc)
printf("pctr: user-level cycle counter enabled\n");
- else
- printf("pctr: no performance counters in CPU\n");
+ } else if (usep5ctr)
+ printf("pctr: 586-class performance counters and user-level "
+ " cycle counter enabled\n");
}
int
pctropen(dev_t dev, int oflags, int devtype, struct proc *p)
{
+
if (minor(dev))
- return ENXIO;
- return 0;
+ return (ENXIO);
+ return (0);
}
int
pctrclose(dev_t dev, int oflags, int devtype, struct proc *p)
{
- return 0;
+
+ return (0);
}
int
p5ctrsel(int fflag, u_int cmd, u_int fn)
{
pctrval msr11;
- int msr;
- int shift;
+ int msr, shift;
cmd -= PCIOCS0;
if (cmd > 1)
- return EINVAL;
+ return (EINVAL);
msr = P5MSR_CTR0 + cmd;
shift = cmd ? 0x10 : 0;
if (!(fflag & FWRITE))
- return EPERM;
+ return (EPERM);
if (fn >= 0x200)
- return EINVAL;
+ return (EINVAL);
msr11 = rdmsr(P5MSR_CTRSEL);
msr11 &= ~(0x1ffLL << shift);
@@ -110,70 +142,49 @@ p5ctrsel(int fflag, u_int cmd, u_int fn)
wrmsr(P5MSR_CTRSEL, msr11);
wrmsr(msr, 0);
- return 0;
-}
-
-static __inline void
-p5ctrrd(struct pctrst *st)
-{
- u_int msr11;
-
- msr11 = rdmsr(P5MSR_CTRSEL);
- st->pctr_fn[0] = msr11 & 0xffff;
- st->pctr_fn[1] = msr11 >> 16;
- __asm __volatile("cli");
- st->pctr_tsc = rdtsc();
- st->pctr_hwc[0] = rdmsr(P5MSR_CTR0);
- st->pctr_hwc[1] = rdmsr(P5MSR_CTR1);
- __asm __volatile("sti");
+ return (0);
}
int
-p6ctrsel(int fflag, u_int cmd, u_int fn)
+pctrsel(int fflag, u_int cmd, u_int fn)
{
int msrsel, msrval;
cmd -= PCIOCS0;
- if (cmd > 1)
- return EINVAL;
- msrsel = P6MSR_CTRSEL0 + cmd;
- msrval = P6MSR_CTR0 + cmd;
+ if (pctr_isamd) {
+ if (cmd > PCTR_AMD_NUM-1)
+ return (EINVAL);
+ msrsel = MSR_K7_EVNTSEL0 + cmd;
+ msrval = MSR_K7_PERFCTR0 + cmd;
+ } else {
+ if (cmd > PCTR_INTEL_NUM-1)
+ return (EINVAL);
+ msrsel = P6MSR_CTRSEL0 + cmd;
+ msrval = P6MSR_CTR0 + cmd;
+ }
if (!(fflag & FWRITE))
- return EPERM;
+ return (EPERM);
if (fn & 0x380000)
- return EINVAL;
+ return (EINVAL);
wrmsr(msrval, 0);
wrmsr(msrsel, fn);
wrmsr(msrval, 0);
- return 0;
-}
-
-static __inline void
-p6ctrrd(struct pctrst *st)
-{
- st->pctr_fn[0] = rdmsr(P6MSR_CTRSEL0);
- st->pctr_fn[1] = rdmsr(P6MSR_CTRSEL1);
- __asm __volatile("cli");
- st->pctr_tsc = rdtsc();
- st->pctr_hwc[0] = rdpmc(0);
- st->pctr_hwc[1] = rdpmc(1);
- __asm __volatile("sti");
+ return (0);
}
-
int
pctrioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
{
switch (cmd) {
case PCIOCRD:
{
- struct pctrst *st = (void *)data;
+ struct pctrst *st = (struct pctrst *)data;
- if (usep6ctr)
- p6ctrrd(st);
+ if (usepctr)
+ pctrrd(st);
else if (usep5ctr)
p5ctrrd(st);
else {
@@ -182,16 +193,16 @@ pctrioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
st->pctr_tsc = rdtsc();
}
st->pctr_idl = pctr_idlcnt;
- return 0;
+ return (0);
}
case PCIOCS0:
case PCIOCS1:
- if (usep6ctr)
- return p6ctrsel(fflag, cmd, *(u_int *) data);
+ if (usepctr)
+ return (pctrsel(fflag, cmd, *(u_int *)data));
if (usep5ctr)
- return p5ctrsel(fflag, cmd, *(u_int *) data);
- return ENODEV;
+ return (p5ctrsel(fflag, cmd, *(u_int *)data));
+ return (ENODEV);
default:
- return EINVAL;
+ return (EINVAL);
}
}
diff --git a/sys/arch/i386/include/pctr.h b/sys/arch/i386/include/pctr.h
index 3deb3e47582..d4f5b80d316 100644
--- a/sys/arch/i386/include/pctr.h
+++ b/sys/arch/i386/include/pctr.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pctr.h,v 1.12 2003/05/27 23:52:01 fgsch Exp $ */
+/* $OpenBSD: pctr.h,v 1.13 2007/10/17 02:30:25 deraadt Exp $ */
/*
* Pentium performance counter driver for OpenBSD.
@@ -14,73 +14,81 @@
#include <sys/ioccom.h>
-typedef u_quad_t pctrval;
+typedef u_int64_t pctrval;
-#define PCTR_NUM 2
+#define PCTR_NUM 4
struct pctrst {
- u_int pctr_fn[PCTR_NUM]; /* Current settings of hardware counters */
+ u_int pctr_fn[PCTR_NUM]; /* Current settings of counters */
pctrval pctr_tsc; /* Free-running 64-bit cycle counter */
- pctrval pctr_hwc[PCTR_NUM]; /* Values of the hardware counters */
+ pctrval pctr_hwc[PCTR_NUM]; /* Values of the hardware counters */
pctrval pctr_idl; /* Iterations of the idle loop */
};
/* Bit values in fn fields and PIOCS ioctl's */
-#define P5CTR_K 0x40 /* Monitor kernel-level events */
-#define P5CTR_U 0x80 /* Monitor user-level events */
-#define P5CTR_C 0x100 /* count cycles rather than events */
+#define P5CTR_K 0x40 /* Monitor kernel-level events */
+#define P5CTR_U 0x80 /* Monitor user-level events */
+#define P5CTR_C 0x100 /* count cycles rather than events */
-#define P6CTR_U 0x010000 /* Monitor user-level events */
-#define P6CTR_K 0x020000 /* Monitor kernel-level events */
-#define P6CTR_E 0x040000 /* Edge detect */
-#define P6CTR_EN 0x400000 /* Enable counters (counter 0 only) */
-#define P6CTR_I 0x800000 /* Invert counter mask */
+#define P6CTR_U 0x010000 /* Monitor user-level events */
+#define P6CTR_K 0x020000 /* Monitor kernel-level events */
+#define P6CTR_E 0x040000 /* Edge detect */
+#define P6CTR_EN 0x400000 /* Enable counters (counter 0 only) */
+#define P6CTR_I 0x800000 /* Invert counter mask */
/* Unit Mask bits */
-#define P6CTR_UM_M 0x0800 /* Modified cache lines */
-#define P6CTR_UM_E 0x0400 /* Exclusive cache lines */
-#define P6CTR_UM_S 0x0200 /* Shared cache lines */
-#define P6CTR_UM_I 0x0100 /* Invalid cache lines */
-#define P6CTR_UM_MESI (P6CTR_UM_M|P6CTR_UM_E|P6CTR_UM_S|P6CTR_UM_I)
-#define P6CTR_UM_A 0x2000 /* Any initiator (as opposed to self) */
-
-#define P6CTR_CM_SHIFT 24 /* Left shift for counter mask */
-
-/* ioctl to set which counter a device tracks. */
-#define PCIOCRD _IOR('c', 1, struct pctrst) /* Read counter value */
-#define PCIOCS0 _IOW('c', 8, unsigned int) /* Set counter 0 function */
-#define PCIOCS1 _IOW('c', 9, unsigned int) /* Set counter 1 function */
+#define P6CTR_UM_M 0x0800 /* Modified cache lines */
+#define P6CTR_UM_E 0x0400 /* Exclusive cache lines */
+#define P6CTR_UM_S 0x0200 /* Shared cache lines */
+#define P6CTR_UM_I 0x0100 /* Invalid cache lines */
+#define P6CTR_UM_MESI (P6CTR_UM_M|P6CTR_UM_E|P6CTR_UM_S|P6CTR_UM_I)
+#define P6CTR_UM_A 0x2000 /* Any initiator */
+
+#define P6CTR_UM_SHIFT 8 /* Left shift for unit mask */
+#define P6CTR_CM_SHIFT 24 /* Left shift for counter mask */
+
+/* ioctl to set which counter a device tracks */
+#define PCIOCRD _IOR('c', 1, struct pctrst) /* Read counter value */
+#define PCIOCS0 _IOW('c', 8, unsigned int) /* Set counter 0 function */
+#define PCIOCS1 _IOW('c', 9, unsigned int) /* Set counter 1 function */
+#define PCIOCS2 _IOW('c', 10, unsigned int) /* Set counter 0 function */
+#define PCIOCS3 _IOW('c', 11, unsigned int) /* Set counter 1 function */
#define _PATH_PCTR "/dev/pctr"
-#define rdtsc() \
-({ \
- pctrval v; \
- __asm __volatile ("rdtsc" : "=A" (v)); \
- v; \
+#define rdtsc() \
+({ \
+ pctrval v; \
+ __asm __volatile ("rdtsc" : "=A" (v)); \
+ v; \
})
/* Read the performance counters (Pentium Pro only) */
-#define rdpmc(ctr) \
-({ \
- pctrval v; \
- __asm __volatile ("rdpmc\n" \
- "\tandl $0xff, %%edx" \
- : "=A" (v) : "c" (ctr)); \
- v; \
+#define rdpmc(ctr) \
+({ \
+ pctrval v; \
+ __asm __volatile ("rdpmc\n" \
+ "\tandl $0xff, %%edx" \
+ : "=A" (v) : "c" (ctr)); \
+ v; \
})
#ifdef _KERNEL
#define rdmsr(msr) \
({ \
- pctrval v; \
- __asm __volatile ("rdmsr" : "=A" (v) : "c" (msr)); \
- v; \
+ pctrval v; \
+ __asm __volatile ("rdmsr" : "=A" (v) : "c" (msr)); \
+ v; \
})
#define wrmsr(msr, v) \
- __asm __volatile ("wrmsr" :: "A" ((u_quad_t) (v)), "c" (msr));
+ __asm __volatile ("wrmsr" :: "A" ((u_quad_t) (v)), "c" (msr));
+
+void pctrattach(int);
+int pctropen(dev_t, int, int, struct proc *);
+int pctrclose(dev_t, int, int, struct proc *);
+int pctrioctl(dev_t, u_long, caddr_t, int, struct proc *);
#endif /* _KERNEL */
#endif /* ! _I386_PCTR_H_ */
diff --git a/sys/arch/i386/include/specialreg.h b/sys/arch/i386/include/specialreg.h
index bc186de981f..7dc9f548496 100644
--- a/sys/arch/i386/include/specialreg.h
+++ b/sys/arch/i386/include/specialreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: specialreg.h,v 1.31 2007/05/29 21:01:56 tedu Exp $ */
+/* $OpenBSD: specialreg.h,v 1.32 2007/10/17 02:30:25 deraadt Exp $ */
/* $NetBSD: specialreg.h,v 1.7 1994/10/27 04:16:26 cgd Exp $ */
/*-
@@ -245,6 +245,14 @@
/* AMD MSRs */
#define MSR_K6_EPMR 0xc0000086
+#define MSR_K7_EVNTSEL0 0xc0010000
+#define MSR_K7_EVNTSEL1 0xc0010001
+#define MSR_K7_EVNTSEL2 0xc0010002
+#define MSR_K7_EVNTSEL3 0xc0010003
+#define MSR_K7_PERFCTR0 0xc0010004
+#define MSR_K7_PERFCTR1 0xc0010005
+#define MSR_K7_PERFCTR2 0xc0010006
+#define MSR_K7_PERFCTR3 0xc0010007
/*
* AMD K8 (Opteron) MSRs.