diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2007-09-12 18:18:28 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2007-09-12 18:18:28 +0000 |
commit | 17488250e79f8b7a08aebe845668195136658b4a (patch) | |
tree | eb569c6548305395496cf4a6e352826453e75634 /sys/arch/amd64 | |
parent | 19a8191e4ccf227d941b43256a897ebb2bd9fb57 (diff) |
port of i386 pctr code to amd64; Mike Belopuhov
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r-- | sys/arch/amd64/amd64/conf.c | 7 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/locore.S | 5 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/pctr.c | 169 | ||||
-rw-r--r-- | sys/arch/amd64/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/arch/amd64/conf/files.amd64 | 5 | ||||
-rw-r--r-- | sys/arch/amd64/include/conf.h | 5 | ||||
-rw-r--r-- | sys/arch/amd64/include/pctr.h | 78 |
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_ */ |