diff options
Diffstat (limited to 'sys/i386')
-rw-r--r-- | sys/i386/conf/files.i386 | 3 | ||||
-rw-r--r-- | sys/i386/conf/options.i386 | 2 | ||||
-rw-r--r-- | sys/i386/i386/machdep.c | 9 | ||||
-rw-r--r-- | sys/i386/i386/mem.c | 38 | ||||
-rw-r--r-- | sys/i386/i386/perfmon.c | 295 | ||||
-rw-r--r-- | sys/i386/include/cpufunc.h | 36 | ||||
-rw-r--r-- | sys/i386/include/perfmon.h | 261 |
7 files changed, 638 insertions, 6 deletions
diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386 index 5c40866..65f44f9 100644 --- a/sys/i386/conf/files.i386 +++ b/sys/i386/conf/files.i386 @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.i386,v 1.130 1996/03/02 19:37:34 peter Exp $ +# $Id: files.i386,v 1.131 1996/03/15 07:49:02 peter Exp $ # aic7xxx_asm optional ahc device-driver \ dependency "$S/dev/aic7xxx/aic7xxx_asm.c" \ @@ -50,6 +50,7 @@ i386/i386/math_emulate.c optional math_emulate i386/i386/mem.c standard i386/i386/microtime.s standard i386/i386/ns_cksum.c optional ns +i386/i386/perfmon.c optional perfmon i386/i386/pmap.c standard i386/i386/procfs_machdep.c standard i386/i386/support.s standard diff --git a/sys/i386/conf/options.i386 b/sys/i386/conf/options.i386 index eb474eb..42ab489 100644 --- a/sys/i386/conf/options.i386 +++ b/sys/i386/conf/options.i386 @@ -1,3 +1,4 @@ +# $Id$ BOUNCEPAGES opt_bounce.h USER_LDT MATH_EMULATE opt_math_emulate.h @@ -9,3 +10,4 @@ PANIC_REBOOT_WAIT_TIME opt_machdep.h LARGEMEM opt_machdep.h MAXMEM opt_machdep.h LINUX opt_linux.h +PERFMON opt_perfmon.h diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 014d3fb..e2f7699 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.177 1996/03/03 01:57:43 jkh Exp $ + * $Id: machdep.c,v 1.178 1996/03/11 02:21:42 hsu Exp $ */ #include "npx.h" @@ -44,6 +44,7 @@ #include "opt_ddb.h" #include "opt_bounce.h" #include "opt_machdep.h" +#include "opt_perfmon.h" #include <sys/param.h> #include <sys/systm.h> @@ -109,6 +110,9 @@ #include <machine/devconf.h> #include <machine/bootinfo.h> #include <machine/md_var.h> +#ifdef PERFMON +#include <machine/perfmon.h> +#endif #include <i386/isa/isa.h> #include <i386/isa/isa_device.h> @@ -649,6 +653,9 @@ identifycpu() default: break; } +#ifdef PERFMON + perfmon_init(); +#endif dev_attach(&kdc_cpu0); } diff --git a/sys/i386/i386/mem.c b/sys/i386/i386/mem.c index 1439398..e60c99e 100644 --- a/sys/i386/i386/mem.c +++ b/sys/i386/i386/mem.c @@ -38,13 +38,15 @@ * * from: Utah $Hdr: mem.c 1.13 89/10/08$ * from: @(#)mem.c 7.2 (Berkeley) 5/9/91 - * $Id: mem.c,v 1.28 1995/12/27 11:18:29 markm Exp $ + * $Id: mem.c,v 1.29 1995/12/31 09:32:16 joerg Exp $ */ /* * Memory special file */ +#include "opt_perfmon.h" + #include <sys/param.h> #include <sys/conf.h> #include <sys/buf.h> @@ -60,6 +62,9 @@ #include <machine/cpu.h> #include <machine/random.h> #include <machine/psl.h> +#ifdef PERFMON +#include <machine/perfmon.h> +#endif #include <vm/vm.h> #include <vm/vm_param.h> @@ -90,6 +95,9 @@ static void *random_devfs_token; static void *urandom_devfs_token; static void *zero_devfs_token; static void *io_devfs_token; +#ifdef PERFMON +static void *perfmon_devfs_token; +#endif static void memdevfs_init __P((void)); @@ -111,6 +119,10 @@ memdevfs_init() "/", "zero", &mem_cdevsw, 12, DV_CHR, 0, 0, 0666); io_devfs_token = devfs_add_devsw( "/", "io", &mem_cdevsw, 14, DV_CHR, 0, 0, 0600); +#ifdef PERFMON + perfmon_devfs_token = devfs_add_devsw( + "/", "perfmon", &mem_cdevsw, 32, DV_CHR, 0, 0, 0666); +#endif /* PERFMON */ } #endif /* DEVFS */ @@ -126,6 +138,10 @@ mmclose(dev, flags, fmt, p) struct trapframe *fp; switch (minor(dev)) { +#ifdef PERFMON + case 32: + return perfmon_close(dev, flags, fmt, p); +#endif case 14: fp = (struct trapframe *)curproc->p_md.md_regs; fp->tf_eflags &= ~PSL_IOPL; @@ -146,6 +162,12 @@ mmopen(dev, flags, fmt, p) struct trapframe *fp; switch (minor(dev)) { + case 32: +#ifdef PERFMON + return perfmon_open(dev, flags, fmt, p); +#else + return ENODEV; +#endif case 14: fp = (struct trapframe *)curproc->p_md.md_regs; fp->tf_eflags |= PSL_IOPL; @@ -378,8 +400,18 @@ mmioctl(dev, cmd, cmdarg, flags, p) u_int16_t interrupt_mask; int error; - if (minor(dev) != 3 && minor(dev) != 4) - return (ENODEV); + switch(minor(dev)) { + case 3: + case 4: + break; + +#ifdef PERFMON + case 32: + return perfmon_ioctl(dev, cmd, cmdarg, flags, p); +#endif + default: + return ENODEV; + } if (*(u_int16_t *)cmdarg >= 16) return (EINVAL); diff --git a/sys/i386/i386/perfmon.c b/sys/i386/i386/perfmon.c new file mode 100644 index 0000000..290d339 --- /dev/null +++ b/sys/i386/i386/perfmon.c @@ -0,0 +1,295 @@ +/* + * Copyright 1996 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/fcntl.h> +#include <sys/ioccom.h> + +#include <machine/cpu.h> +#include <machine/cputypes.h> +#include <machine/clock.h> +#include <machine/perfmon.h> + +static int perfmon_inuse; +static int perfmon_cpuok; +static int msr_ctl[NPMC]; +static int msr_pmc[NPMC]; + +/* + * Must be called after cpu_class is set up. + */ +void +perfmon_init(void) +{ + switch(cpu_class) { + case CPUCLASS_586: /* assume it's the same for now */ + case CPUCLASS_686: + perfmon_cpuok = 1; + msr_ctl[0] = 0x186; + msr_ctl[1] = 0x187; + msr_pmc[0] = 0xc1; + msr_pmc[1] = 0xc2; + break; + + default: + perfmon_cpuok = 0; + break; + } +} + +int +perfmon_avail(void) +{ + return perfmon_cpuok; +} + +int +perfmon_setup(int pmc, unsigned int control) +{ + if (pmc < 0 || pmc >= NPMC) + return EINVAL; + + perfmon_inuse |= (1 << pmc); + control &= ~(PMCF_SYS_FLAGS << 16); + wrmsr(msr_ctl[pmc], control); + wrmsr(msr_pmc[pmc], 0); + return 0; +} + +int +perfmon_get(int pmc, unsigned int *control) +{ + if (pmc < 0 || pmc >= NPMC) + return EINVAL; + + if (perfmon_inuse & (1 << pmc)) { + *control = rdmsr(msr_ctl[pmc]); + return 0; + } + return EBUSY; /* XXX reversed sense */ +} + +int +perfmon_fini(int pmc) +{ + if (pmc < 0 || pmc >= NPMC) + return EINVAL; + + if (perfmon_inuse & (1 << pmc)) { + perfmon_stop(pmc); + perfmon_inuse &= ~(1 << pmc); + return 0; + } + return EBUSY; /* XXX reversed sense */ +} + +int +perfmon_start(int pmc) +{ + /* + * XXX - Current Intel design does not allow counters to be enabled + * independently. + */ + if (pmc != PMC_ALL) + return EINVAL; + +#if 0 + if (perfmon_inuse & (1 << pmc)) { + wrmsr(msr_ctl[pmc], rdmsr(msr_ctl[pmc]) | (PMCF_EN << 16)); + return 0; + } +#else + if (perfmon_inuse) { + wrmsr(msr_ctl[0], rdmsr(msr_ctl[0]) | (PMCF_EN << 16)); + return 0; + } +#endif + return EBUSY; +} + +int +perfmon_stop(int pmc) +{ + /* + * XXX - Current Intel design does not allow counters to be enabled + * independently. + */ + if (pmc != PMC_ALL) + return EINVAL; + +#if 0 + if (perfmon_inuse & (1 << pmc)) { + wrmsr(msr_ctl[pmc], rdmsr(msr_ctl[pmc]) & ~(PMCF_EN << 16)); + return 0; + } +#else + if (perfmon_inuse) { + wrmsr(msr_ctl[0], rdmsr(msr_ctl[0]) & ~(PMCF_EN << 16)); + return 0; + } +#endif + return EBUSY; +} + +int +perfmon_read(int pmc, quad_t *val) +{ + if (pmc < 0 || pmc >= NPMC) + return EINVAL; + + if (perfmon_inuse & (1 << pmc)) { + *val = rdmsr(msr_pmc[pmc]); + return 0; + } + + return EBUSY; +} + +int +perfmon_reset(int pmc) +{ + if (pmc < 0 || pmc >= NPMC) + return EINVAL; + + if (perfmon_inuse & (1 << pmc)) { + wrmsr(msr_pmc[pmc], 0); + return 0; + } + return EBUSY; +} + +/* + * Now the user-mode interface, called from a subdevice of mem.c. + */ +static int writer; +static int writerpmc; + +int +perfmon_open(dev_t dev, int flags, int fmt, struct proc *p) +{ + if (!perfmon_cpuok) + return ENXIO; + + if (flags & FWRITE) { + if (writer) { + return EBUSY; + } else { + writer = 1; + writerpmc = 0; + } + } + return 0; +} + +int +perfmon_close(dev_t dev, int flags, int fmt, struct proc *p) +{ + if (flags & FWRITE) { + int i; + + for (i = 0; i < NPMC; i++) { + if (writerpmc & (1 << i)) + perfmon_fini(i); + } + writer = 0; + } + return 0; +} + +int +perfmon_ioctl(dev_t dev, int cmd, caddr_t param, int flags, struct proc *p) +{ + struct pmc *pmc; + struct pmc_data *pmcd; + struct pmc_tstamp *pmct; + int *ip; + int rv; + + switch(cmd) { + case PMIOSETUP: + if (!(flags & FWRITE)) + return EPERM; + pmc = (struct pmc *)param; + + rv = perfmon_setup(pmc->pmc_num, pmc->pmc_val); + if (!rv) { + writerpmc |= (1 << pmc->pmc_num); + } + break; + + case PMIOGET: + pmc = (struct pmc *)param; + rv = perfmon_get(pmc->pmc_num, &pmc->pmc_val); + break; + + case PMIOSTART: + if (!(flags & FWRITE)) + return EPERM; + + ip = (int *)param; + rv = perfmon_start(*ip); + break; + + case PMIOSTOP: + if (!(flags & FWRITE)) + return EPERM; + + ip = (int *)param; + rv = perfmon_stop(*ip); + break; + + case PMIORESET: + if (!(flags & FWRITE)) + return EPERM; + + ip = (int *)param; + rv = perfmon_reset(*ip); + break; + + case PMIOREAD: + pmcd = (struct pmc_data *)param; + rv = perfmon_read(pmcd->pmcd_num, &pmcd->pmcd_value); + break; + + case PMIOTSTAMP: + pmct = (struct pmc_tstamp *)param; + pmct->pmct_rate = i586_ctr_rate >> I586_CTR_RATE_SHIFT; + pmct->pmct_value = rdtsc(); + rv = 0; + break; + + default: + rv = ENOTTY; + } + + return rv; +} diff --git a/sys/i386/include/cpufunc.h b/sys/i386/include/cpufunc.h index ecb7e00..6a1235a 100644 --- a/sys/i386/include/cpufunc.h +++ b/sys/i386/include/cpufunc.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: cpufunc.h,v 1.44 1995/12/28 23:34:17 davidg Exp $ + * $Id: cpufunc.h,v 1.45 1996/01/16 07:42:08 bde Exp $ */ /* @@ -296,6 +296,36 @@ write_eflags(u_long ef) __asm __volatile("pushl %0; popfl" : : "r" (ef)); } +static __inline long long +rdmsr(unsigned msr) +{ + long long rv; + __asm __volatile(".byte 0x0f, 0x32" : "=A" (rv) : "c" (msr)); + return rv; +} + +static __inline long long +rdtsc(void) +{ + long long rv; + __asm __volatile(".byte 0x0f, 0x31" : "=A" (rv)); + return rv; +} + +static __inline long long +rdpmc(unsigned pmc) +{ + long long rv; + __asm __volatile(".byte 0x0f, 0x33" : "=A" (rv) : "c" (pmc)); + return rv; +} + +static __inline void +wrmsr(unsigned msr, long long newval) +{ + __asm __volatile(".byte 0x0f, 0x33" : : "A" (newval), "c" (msr)); +} + #else /* !__GNUC__ */ int bdb __P((void)); @@ -318,6 +348,10 @@ void pmap_update __P((void)); u_long read_eflags __P((void)); u_long rcr2 __P((void)); void write_eflags __P((u_long ef)); +quad_t rdmsr __P((unsigned msr)); +quad_t rdtsc __P((void)); +quad_t rdpmc __P((unsigned pmc)); +void wrmsr __P((unsigned msr, quad_t newval)); #endif /* __GNUC__ */ diff --git a/sys/i386/include/perfmon.h b/sys/i386/include/perfmon.h new file mode 100644 index 0000000..8aec6df --- /dev/null +++ b/sys/i386/include/perfmon.h @@ -0,0 +1,261 @@ +/* + * Copyright 1996 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +/* + * Interface to performance-monitoring counters for Intel Pentium and + * Pentium Pro CPUs. + */ + +#ifndef _MACHINE_PERFMON_H_ +#define _MACHINE_PERFMON_H_ 1 + +#ifndef KERNEL +#include <sys/ioccom.h> +#endif + +#define NPMC 2 + +#define PMIOSETUP _IOW('5', 1, struct pmc) +#define PMIOGET _IOWR('5', 7, struct pmc) +#define PMIOSTART _IOW('5', 2, int) +#define PMIOSTOP _IOW('5', 3, int) +#define PMIOREAD _IOWR('5', 4, struct pmc_data) +#define PMIORESET _IOW('5', 5, int) +#define PMIOTSTAMP _IOR('5', 6, struct pmc_tstamp) + +struct pmc { + int pmc_num; + union { + struct { + unsigned char pmcus_event; + unsigned char pmcus_unit; + unsigned char pmcus_flags; + unsigned char pmcus_mask; + } pmcu_s; + unsigned int pmcu_val; + } pmc_pmcu; +}; + +#define PMC_ALL (-1) + +#define pmc_event pmc_pmcu.pmcu_s.pmcus_event +#define pmc_unit pmc_pmcu.pmcu_s.pmcus_unit +#define pmc_flags pmc_pmcu.pmcu_s.pmcus_flags +#define pmc_mask pmc_pmcu.pmcu_s.pmcus_mask +#define pmc_val pmc_pmcu.pmcu_val + +#define PMCF_USR 0x01 /* count events in user mode */ +#define PMCF_OS 0x02 /* count events in kernel mode */ +#define PMCF_E 0x04 /* use edge-detection mode */ +#define PMCF_PC 0x08 /* PMx output pin control */ +#define PMCF_INT 0x10 /* APIC interrupt enable (do not use) */ +#define PMCF_EN 0x40 /* enable counters */ +#define PMCF_INV 0x80 /* invert counter mask comparison */ + +#define PMCF_SYS_FLAGS (PMCF_INT | PMCF_EN) /* user cannot set */ + +struct pmc_data { + int pmcd_num; + quad_t pmcd_value; +}; + +struct pmc_tstamp { + int pmct_rate; + quad_t pmct_value; +}; + +#ifndef KERNEL + +#define _PATH_PERFMON "/dev/perfmon" + +#else + +/* + * Intra-kernel interface to performance monitoring counters + */ +void perfmon_init __P((void)); +int perfmon_avail __P((void)); +int perfmon_setup __P((int, unsigned int)); +int perfmon_get __P((int, unsigned int *)); +int perfmon_fini __P((int)); +int perfmon_start __P((int)); +int perfmon_stop __P((int)); +int perfmon_read __P((int, quad_t *)); +int perfmon_reset __P((int)); + +/* + * We pass the device down this interface because in the future + * the different counters might be accessed through separate devices. + */ +int perfmon_close __P((dev_t, int, int, struct proc *)); +int perfmon_open __P((dev_t, int, int, struct proc *)); +int perfmon_ioctl __P((dev_t, int, caddr_t, int, struct proc *)); +#endif /* KERNEL */ + +/* + * Pentium Pro performance counters, from Appendix B. + */ +/* Data Cache Unit */ +#define PMC6_DATA_MEM_REFS 0x43 +#define PMC6_DCU_LINES_IN 0x45 +#define PMC6_DCU_M_LINES_IN 0x46 +#define PMC6_DCU_M_LINES_OUT 0x47 +#define PMC6_DCU_MISS_OUTSTANDING 0x48 + +/* Instruction Fetch Unit */ +#define PMC6_IFU_IFETCH 0x80 +#define PMC6_IFU_IFETCH_MISS 0x81 +#define PMC6_ITLB_MISS 0x85 +#define PMC6_IFU_MEM_STALL 0x86 +#define PMC6_ILD_STALL 0x87 + +/* L2 Cache */ +#define PMC6_L2_IFETCH 0x28 /* MESI */ +#define PMC6_L2_LD 0x29 /* MESI */ +#define PMC6_L2_ST 0x2a /* MESI */ +#define PMC6_L2_LINES_IN 0x24 +#define PMC6_L2_LINES_OUT 0x26 +#define PMC6_L2_M_LINES_INM 0x25 +#define PMC6_L2_M_LINES_OUTM 0x27 +#define PMC6_L2_RQSTS 0x2e /* MESI */ +#define PMC6_L2_ADS 0x21 +#define PMC6_L2_DBUS_BUSY 0x22 +#define PMC6_L2_DBUS_BUSY_RD 0x23 + +/* External Bus Logic */ +#define PMC6_BUS_DRDY_CLOCKS 0x62 +#define PMC6_BUS_LOCK_CLOCKS 0x63 +#define PMC6_BUS_REQ_OUTSTANDING 0x60 +#define PMC6_BUS_TRAN_BRD 0x65 +#define PMC6_BUS_TRAN_RFO 0x66 +#define PMC6_BUS_TRAN_WB 0x67 +#define PMC6_BUS_TRAN_IFETCH 0x68 +#define PMC6_BUS_TRAN_INVAL 0x69 +#define PMC6_BUS_TRAN_PWR 0x6a +#define PMC6_BUS_TRAN_P 0x6b +#define PMC6_BUS_TRAN_IO 0x6c +#define PMC6_BUS_TRAN_DEF 0x6d +#define PMC6_BUS_TRAN_BURST 0x6e +#define PMC6_BUS_TRAN_ANY 0x70 +#define PMC6_BUS_TRAN_MEM 0x6f +#define PMC6_BUS_DATA_RCV 0x64 +#define PMC6_BUS_BNR_DRV 0x61 +#define PMC6_BUS_HIT_DRV 0x7a +#define PMC6_BUS_HITM_DRV 0x7b +#define PMC6_BUS_SNOOP_STALL 0x7e + +/* Floating Point Unit */ +#define PMC6_FLOPS 0xc1 /* counter 0 only */ +#define PMC6_FP_COMP_OPS_EXE 0x10 /* counter 0 only */ +#define PMC6_FP_ASSIST 0x11 /* counter 1 only */ +#define PMC6_MUL 0x12 /* counter 1 only */ +#define PMC6_DIV 0x13 /* counter 1 only */ +#define PMC6_CYCLES_DIV_BUSY 0x14 /* counter 0 only */ + +/* Memory Ordering */ +#define PMC6_LD_BLOCKS 0x03 +#define PMC6_SB_DRAINS 0x04 +#define PMC6_MISALIGN_MEM_REF 0x05 + +/* Instruction Decoding and Retirement */ +#define PMC6_INST_RETIRED 0xc0 +#define PMC6_UOPS_RETIRED 0xc2 +#define PMC6_INST_DECODER 0xd0 /* (sic) */ + +/* Interrupts */ +#define PMC6_HW_INT_RX 0xc8 +#define PMC6_CYCLES_INT_MASKED 0xc6 +#define PMC6_CYCLES_INT_PENDING_AND_MASKED 0xc7 + +/* Branches */ +#define PMC6_BR_INST_RETIRED 0xc4 +#define PMC6_BR_MISS_PRED_RETIRED 0xc5 +#define PMC6_BR_TAKEN_RETIRED 0xc9 +#define PMC6_BR_MISS_PRED_TAKEN_RET 0xca +#define PMC6_BR_INST_DECODED 0xe0 +#define PMC6_BTB_MISSES 0xe2 +#define PMC6_BR_BOGUS 0xe4 +#define PMC6_BACLEARS 0xe6 + +/* Stalls */ +#define PMC6_RESOURCE_STALLS 0xa2 +#define PMC6_PARTIAL_RAT_STALLS 0xd2 + +/* Segment Register Loads */ +#define PMC6_SEGMENT_REG_LOADS 0x06 + +/* Clocks */ +#define PMC6_CPU_CLK_UNHALTED 0x79 + +/* + * Pentium Performance Counters + * This list comes from the Harvard people, not Intel. + */ +#define PMC5_DATA_READ 0 +#define PMC5_DATA_WRITE 1 +#define PMC5_DATA_TLB_MISS 2 +#define PMC5_DATA_READ_MISS 3 +#define PMC5_DATA_WRITE_MISS 4 +#define PMC5_WRITE_M_E 5 +#define PMC5_DATA_LINES_WBACK 6 +#define PMC5_DATA_CACHE_SNOOP 7 +#define PMC5_DATA_CACHE_SNOOP_HIT 8 +#define PMC5_MEM_ACCESS_BOTH 9 +#define PMC5_BANK_CONFLICTS 10 +#define PMC5_MISALIGNED_DATA 11 +#define PMC5_INST_READ 12 +#define PMC5_INST_TLB_MISS 13 +#define PMC5_INST_CACHE_MISS 14 +#define PMC5_SEGMENT_REG_LOAD 15 +#define PMC5_BRANCHES 18 +#define PMC5_BTB_HITS 19 +#define PMC5_BRANCH_TAKEN 20 +#define PMC5_PIPELINE_FLUSH 21 +#define PMC5_INST_EXECUTED 22 +#define PMC5_INST_EXECUTED_V 23 +#define PMC5_BUS_UTILIZATION 24 +#define PMC5_WRITE_BACKUP_STALL 25 +#define PMC5_DATA_READ_STALL 26 +#define PMC5_WRITE_E_M_STALL 27 +#define PMC5_LOCKED_BUS 28 +#define PMC5_IO_CYCLE 29 +#define PMC5_NONCACHE_MEMORY 30 +#define PMC5_ADDR_GEN_INTERLOCK 31 +#define PMC5_FLOPS 34 +#define PMC5_BP0_MATCH 35 +#define PMC5_BP1_MATCH 36 +#define PMC5_BP2_MATCH 37 +#define PMC5_BP3_MATCH 38 +#define PMC5_HW_INTR 39 +#define PMC5_DATA_RW 40 +#define PMC5_DATA_RW_MISS 41 + +#endif /* _MACHINE_PERFMON_H_ */ |