summaryrefslogtreecommitdiff
path: root/sys/arch/amd64
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2007-09-12 18:18:28 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2007-09-12 18:18:28 +0000
commit17488250e79f8b7a08aebe845668195136658b4a (patch)
treeeb569c6548305395496cf4a6e352826453e75634 /sys/arch/amd64
parent19a8191e4ccf227d941b43256a897ebb2bd9fb57 (diff)
port of i386 pctr code to amd64; Mike Belopuhov
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r--sys/arch/amd64/amd64/conf.c7
-rw-r--r--sys/arch/amd64/amd64/locore.S5
-rw-r--r--sys/arch/amd64/amd64/pctr.c169
-rw-r--r--sys/arch/amd64/conf/GENERIC3
-rw-r--r--sys/arch/amd64/conf/files.amd645
-rw-r--r--sys/arch/amd64/include/conf.h5
-rw-r--r--sys/arch/amd64/include/pctr.h78
7 files changed, 265 insertions, 7 deletions
diff --git a/sys/arch/amd64/amd64/conf.c b/sys/arch/amd64/amd64/conf.c
index c29ff624841..9f1323cb280 100644
--- a/sys/arch/amd64/amd64/conf.c
+++ b/sys/arch/amd64/amd64/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.15 2007/08/02 16:40:27 deraadt Exp $ */
+/* $OpenBSD: conf.c,v 1.16 2007/09/12 18:18:27 deraadt Exp $ */
/*
* Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
@@ -100,7 +100,7 @@ int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]);
#define cdev_ocis_init(c,n) { \
dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
(dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
- (dev_type_stop((*))) enodev, 0, dev_init(c,n,select), \
+ (dev_type_stop((*))) enodev, 0, dev_init(c,n,poll), \
(dev_type_mmap((*))) enodev, 0 }
/* open, close, read */
@@ -151,6 +151,7 @@ cdev_decl(mcd);
cdev_decl(music);
#include "acpi.h"
#include "bthub.h"
+#include "pctr.h"
#include "iop.h"
#ifdef XFS
#include <xfs/nxfs.h>
@@ -241,7 +242,7 @@ struct cdevsw cdevsw[] =
#endif
cdev_notdef(), /* 44 */
cdev_random_init(1,random), /* 45: random data source */
- cdev_notdef(), /* 46 */
+ cdev_ocis_init(NPCTR,pctr), /* 46: performance counters */
cdev_disk_init(NRD,rd), /* 47: ram disk driver */
cdev_notdef(), /* 48 */
cdev_bktr_init(NBKTR,bktr), /* 49: Bt848 video capture device */
diff --git a/sys/arch/amd64/amd64/locore.S b/sys/arch/amd64/amd64/locore.S
index ae0d1245563..e44923662e8 100644
--- a/sys/arch/amd64/amd64/locore.S
+++ b/sys/arch/amd64/amd64/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.22 2007/05/27 08:58:31 art Exp $ */
+/* $OpenBSD: locore.S,v 1.23 2007/09/12 18:18:27 deraadt Exp $ */
/* $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $ */
/*
@@ -866,6 +866,9 @@ idle_zero:
cmpl $0,_C_LABEL(whichqs)(%rip)
jnz idle_exit
idle_loop:
+#if NPCTR > 0
+ incq _C_LABEL(pctr_idlcnt)
+#endif
/* Try to zero some pages. */
movl _C_LABEL(uvm)+UVM_PAGE_IDLE_ZERO(%rip),%ecx
testl %ecx,%ecx
diff --git a/sys/arch/amd64/amd64/pctr.c b/sys/arch/amd64/amd64/pctr.c
new file mode 100644
index 00000000000..3efe16604cb
--- /dev/null
+++ b/sys/arch/amd64/amd64/pctr.c
@@ -0,0 +1,169 @@
+/* $OpenBSD: pctr.c,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.
+ */
+
+/*
+ * Pentium performance counter driver for OpenBSD.
+ * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
+ *
+ * Modification and redistribution in source and binary forms is
+ * permitted provided that due credit is given to the author and the
+ * OpenBSD project by leaving this copyright notice intact.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+#include <sys/ioccom.h>
+#include <sys/systm.h>
+
+#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)
+
+u_int64_t pctr_idlcnt; /* Gets incremented in locore.S */
+
+int pctr_isamd;
+int pctr_isintel;
+
+static void pctrrd(struct pctrst *);
+
+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 : 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);*/
+
+ __asm __volatile("sti");
+}
+
+void
+pctrattach(int num)
+{
+
+ if (num > 1)
+ return;
+
+ 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) {
+ __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");
+ }
+}
+
+int
+pctropen(dev_t dev, int oflags, int devtype, struct proc *p)
+{
+
+ if (minor(dev))
+ return (ENXIO);
+ return (0);
+}
+
+int
+pctrclose(dev_t dev, int oflags, int devtype, struct proc *p)
+{
+
+ return (0);
+}
+
+int
+pctrsel(int fflag, u_int32_t cmd, u_int32_t fn)
+{
+ int msrsel, msrval;
+
+ cmd -= PCIOCS0;
+ 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 = MSR_EVNTSEL0 + cmd;
+ msrval = MSR_PERFCTR0 + cmd;
+ }
+
+ if (!(fflag & FWRITE))
+ return (EPERM);
+ if (fn & 0x380000)
+ return (EINVAL);
+
+ wrmsr(msrval, 0);
+ wrmsr(msrsel, fn);
+ wrmsr(msrval, 0);
+
+ return (0);
+}
+
+int
+pctrioctl(dev_t dev, u_int64_t cmd, caddr_t data, int fflag, struct proc *p)
+{
+
+ switch (cmd) {
+ case PCIOCRD:
+ {
+ struct pctrst *st = (struct pctrst *)data;
+
+ if (usepctr)
+ pctrrd(st);
+ st->pctr_idl = pctr_idlcnt;
+ return (0);
+ }
+ case PCIOCS0:
+ case PCIOCS1:
+ case PCIOCS2:
+ case PCIOCS3:
+ if (usepctr)
+ return (pctrsel(fflag, cmd, *(u_int32_t *)data));
+ return (ENODEV);
+ default:
+ return (EINVAL);
+ }
+}
diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC
index e4beedab336..55a7d16bfcf 100644
--- a/sys/arch/amd64/conf/GENERIC
+++ b/sys/arch/amd64/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.195 2007/09/09 01:37:28 jsg Exp $
+# $OpenBSD: GENERIC,v 1.196 2007/09/12 18:18:27 deraadt Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
@@ -531,6 +531,7 @@ owid* at onewire? # ID
owsbm* at onewire? # Smart Battery Monitor
owtemp* at onewire? # Temperature
+pseudo-device pctr 1
pseudo-device nvram 1
pseudo-device sequencer 1
#pseudo-device raid 4 # RAIDframe disk driver
diff --git a/sys/arch/amd64/conf/files.amd64 b/sys/arch/amd64/conf/files.amd64
index 4ce1947ae75..bb14e4e4ae7 100644
--- a/sys/arch/amd64/conf/files.amd64
+++ b/sys/arch/amd64/conf/files.amd64
@@ -1,4 +1,4 @@
-# $OpenBSD: files.amd64,v 1.33 2007/08/02 16:40:27 deraadt Exp $
+# $OpenBSD: files.amd64,v 1.34 2007/09/12 18:18:27 deraadt Exp $
maxpartitions 16
maxusers 2 16 128
@@ -164,6 +164,9 @@ device fd: disk, isa_dma
attach fd at fdc
file dev/isa/fd.c fd needs-flag
+pseudo-device pctr
+file arch/amd64/amd64/pctr.c pctr needs-flag
+
pseudo-device nvram
file arch/amd64/amd64/nvram.c nvram needs-flag
diff --git a/sys/arch/amd64/include/conf.h b/sys/arch/amd64/include/conf.h
index 960b06eae53..ced984a5b7f 100644
--- a/sys/arch/amd64/include/conf.h
+++ b/sys/arch/amd64/include/conf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.h,v 1.3 2005/12/31 21:22:32 miod Exp $ */
+/* $OpenBSD: conf.h,v 1.4 2007/09/12 18:18:27 deraadt Exp $ */
/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */
/*
@@ -50,3 +50,6 @@ cdev_decl(bios);
(dev_type_stop((*))) enodev, 0, (dev_type_poll((*))) enodev, \
(dev_type_mmap((*))) enodev, 0, D_KQFILTER, dev_init(c,n,kqfilter) }
cdev_decl(acpi);
+
+#define pctrpoll seltrue
+cdev_decl(pctr);
diff --git a/sys/arch/amd64/include/pctr.h b/sys/arch/amd64/include/pctr.h
new file mode 100644
index 00000000000..35c651ebffd
--- /dev/null
+++ b/sys/arch/amd64/include/pctr.h
@@ -0,0 +1,78 @@
+/* $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.
+ */
+
+/*
+ * Pentium performance counter driver for OpenBSD.
+ * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
+ *
+ * Modification and redistribution in source and binary forms is
+ * permitted provided that due credit is given to the author and the
+ * OpenBSD project by leaving this copyright notice intact.
+ */
+
+#ifndef _AMD64_PCTR_H_
+#define _AMD64_PCTR_H_
+
+#include <sys/ioccom.h>
+
+#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 */
+};
+
+/* Bit values in fn fields and PIOCS ioctl's */
+#define PCTR_U 0x010000 /* Monitor user-level events */
+#define PCTR_K 0x020000 /* Monitor kernel-level events */
+#define PCTR_E 0x040000 /* Edge detect */
+#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)
+
+/* 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 2 function */
+#define PCIOCS3 _IOW('c', 11, unsigned int) /* Set counter 3 function */
+
+#define _PATH_PCTR "/dev/pctr"
+
+#ifdef _KERNEL
+
+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);
+
+#endif /* _KERNEL */
+#endif /* ! _AMD64_PCTR_H_ */