svn commit: r184835 - user/kmacy/HEAD_fast_multi_xmit/sys/dev/hwpmc

Kip Macy kmacy at FreeBSD.org
Tue Nov 11 00:04:27 PST 2008


Author: kmacy
Date: Tue Nov 11 08:04:27 2008
New Revision: 184835
URL: http://svn.freebsd.org/changeset/base/184835

Log:
  Add actual ipm driver files

Added:
  user/kmacy/HEAD_fast_multi_xmit/sys/dev/hwpmc/hwpmc_ipm.c   (contents, props changed)
  user/kmacy/HEAD_fast_multi_xmit/sys/dev/hwpmc/hwpmc_ipm.h   (contents, props changed)

Added: user/kmacy/HEAD_fast_multi_xmit/sys/dev/hwpmc/hwpmc_ipm.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/kmacy/HEAD_fast_multi_xmit/sys/dev/hwpmc/hwpmc_ipm.c	Tue Nov 11 08:04:27 2008	(r184835)
@@ -0,0 +1,1593 @@
+/*-
+ * Copyright (c) 2003-2005 Joseph Koshy
+ * Copyright (c) 2007-2008 Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 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.
+ */
+
+/*
+ * Add Performance Monitoring (PM) support for the processor based on Intel's 
+ * Core Solo/Duo architecture and Intel Core microarchitecture.
+ * This CPUs support Intel's Architectural PM Version 1/2 functionality.
+ * Intel(R) 64 and IA-32 Architectures Software Developer's Manual: 
+ * System Programming Guide: Volue 3B: Section 18.12
+ *
+ * Intel Core Solo/Duo processors introduced architectural PM. 
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/pmc.h>
+#include <sys/pmckern.h>
+#include <sys/smp.h>
+#include <sys/systm.h>
+
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/md_var.h>
+#include <machine/pmc_mdep.h>
+#include <machine/specialreg.h>
+
+/*
+ * I had not had so much trouble coding as giving sensible names.
+ * I am sticking to 'ipm' prefix (Intel Performance Monitoring).
+ * Where it really makes difference it will further be qualified by
+ * 'ipm_v1' or 'ipm_v2'.
+ * Bear with me.
+ */
+
+/*
+ * Globals set from the initialization routine based on the 
+ * CPU type
+ */
+static enum pmc_cputype ipm_cputype;
+static const struct ipm_event_descr *ipm_events = NULL;
+static const struct ipm_pmc_descr *ipm_pmc_desc;
+static int ipm_nevents = 0;
+static int ipm_npmcs = 0;
+
+#define	IPM_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | PMC_CAP_SYSTEM | \
+    PMC_CAP_EDGE | PMC_CAP_THRESHOLD | PMC_CAP_READ | PMC_CAP_WRITE |	 \
+    PMC_CAP_INVERT | PMC_CAP_QUALIFIER)
+
+#define	IPM_FIXEDPMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \
+    PMC_CAP_SYSTEM | PMC_CAP_READ | PMC_CAP_WRITE)
+
+static inline int
+ipm_v2_pmc_has_overflowed(uint64_t ovf_status, int ri)
+{
+	return ((ri < 3) ?
+	    (ovf_status & (0x1LL << (ri - 1))) :
+	    (ovf_status & (0x100000000LL << (ri - 3))));
+}
+
+
+static inline uint64_t
+ipm_v2_pmc_ri_to_msr_en_bit(int ri) 
+{
+	return ((ri < 3) ?
+	    (0x1LL << (ri - 1)) : 
+	    (0x100000000LL << (ri - 3)));
+}
+
+struct ipm_pmc_descr {
+	struct pmc_descr pm_descr; /* common information */
+	uint32_t	pm_pmc_msr;
+	uint32_t	pm_evsel_msr;
+};
+
+static const struct ipm_pmc_descr ipm_pmc_desc_v1[IPM_NPMCS_V1] = {
+	/* TSC */
+	{
+		.pm_descr =
+		{
+			.pd_name  = "TSC",
+			.pd_class = PMC_CLASS_TSC,
+			.pd_caps  = PMC_CAP_READ,
+			.pd_width = 64
+		},
+		.pm_pmc_msr   = 0x10,
+		.pm_evsel_msr = ~0
+	},
+
+	/* PMC 0 */
+	{
+		.pm_descr =
+		{
+			.pd_name  = "IPM-PMC-1",
+			.pd_class = PMC_CLASS_IAP1,
+			.pd_caps  = IPM_PMC_CAPS,
+			.pd_width = 40
+		},
+		.pm_pmc_msr   = IPM_MSR_PERFCTR0,
+		.pm_evsel_msr = IPM_MSR_EVSEL0
+	},
+
+	/* PMC 1 */
+	{
+		.pm_descr =
+		{
+			.pd_name  = "IPM-PMC-2",
+			.pd_class = PMC_CLASS_IAP1,
+			.pd_caps  = IPM_PMC_CAPS,
+			.pd_width = 40
+		},
+		.pm_pmc_msr   = IPM_MSR_PERFCTR1,
+		.pm_evsel_msr = IPM_MSR_EVSEL1
+	},
+};
+
+static const struct ipm_pmc_descr ipm_pmc_desc_v2[IPM_NPMCS_V2] = {
+	/* TSC */
+	{
+		.pm_descr =
+		{
+			.pd_name  = "TSC",
+			.pd_class = PMC_CLASS_TSC,
+			.pd_caps  = PMC_CAP_READ,
+			.pd_width = 64
+		},
+		.pm_pmc_msr   = 0x10,
+		.pm_evsel_msr = ~0
+	},
+
+	/* PMC 0 */
+	{
+		.pm_descr =
+		{
+			.pd_name  = "IPM-PMC-1",
+			.pd_caps  = IPM_PMC_CAPS,
+			.pd_class = PMC_CLASS_IAP2,
+			.pd_width = 40
+		},
+		.pm_pmc_msr   = IPM_MSR_PERFCTR0,
+		.pm_evsel_msr = IPM_MSR_EVSEL0
+	},
+
+	/* PMC 1 */
+	{
+		.pm_descr =
+		{
+			.pd_name  = "IPM-PMC-2",
+			.pd_class = PMC_CLASS_IAP2,
+			.pd_caps  = IPM_PMC_CAPS,
+			.pd_width = 40
+		},
+		.pm_pmc_msr   = IPM_MSR_PERFCTR1,
+		.pm_evsel_msr = IPM_MSR_EVSEL1
+	},
+
+	/*
+	 * Following 3 fixed function performance counters are only available
+	 * in processors supporting PM version 2 facilities
+	 */
+	/* Fixed function PMC 1 */
+	{
+		.pm_descr = 
+		{
+			.pd_name  = "IPM-FIXED-PMC-1",
+			.pd_class = PMC_CLASS_IAF,
+			.pd_caps =  IPM_FIXEDPMC_CAPS,
+			.pd_width = 40
+		},
+		.pm_pmc_msr	= IPM_MSR_PERFFIXEDCTR0,
+		.pm_evsel_msr	= IPM_MSR_PERFFIXEDCTR_CTRL
+	},
+
+	/* Fixed function PMC 2 */
+	{
+		.pm_descr = 
+		{
+			.pd_name  = "IPM-FIXED-PMC-2",
+			.pd_class = PMC_CLASS_IAF,
+			.pd_caps =  IPM_FIXEDPMC_CAPS,
+			.pd_width = 40
+		},
+		.pm_pmc_msr	= IPM_MSR_PERFFIXEDCTR1,
+		.pm_evsel_msr	= IPM_MSR_PERFFIXEDCTR_CTRL
+	},
+
+	/* Fixed function PMC 3 */
+	{
+		.pm_descr = 
+		{
+			.pd_name  = "IPM-FIXED-PMC-3",
+			.pd_class = PMC_CLASS_IAF,
+			.pd_caps =  IPM_FIXEDPMC_CAPS,
+			.pd_width = 40
+		},
+		.pm_pmc_msr	= IPM_MSR_PERFFIXEDCTR2,
+		.pm_evsel_msr	= IPM_MSR_PERFFIXEDCTR_CTRL
+	}
+};
+
+/*
+ * Event descriptors
+ */
+struct ipm_event_descr {
+	const enum pmc_event pm_event;
+	uint32_t	     pm_evsel;
+	uint32_t	     pm_umask;
+	uint32_t	     pm_umask_allowed;
+};
+
+/*
+ * Fixed function PM events. Processors based on Intel Core Microarchitecture
+ * have 3 fixed function PMCs. The following 3 PM events can only be 
+ * programmed on fixed function PMCs
+ */
+static const struct ipm_event_descr ipm_events_fixed[] = {
+#define	IPM_EVDESCR(NAME, EVSEL, UMASK)			\
+	{						\
+		.pm_event = PMC_EV_IAF_##NAME,	\
+		.pm_evsel = (EVSEL),			\
+		.pm_umask = (UMASK),			\
+		.pm_umask_allowed = 0			\
+	}
+
+IPM_EVDESCR(INSTRUCTIONS_RETIRED,		0xC0,	0x00),
+IPM_EVDESCR(UNHALTED_CORE_CYCLES,		0x3C,	0x00),
+IPM_EVDESCR(UNHALTED_REFERENCE_CYCLES,		0x3C,	0x01),
+
+#undef	IPM_EVDESCR
+};
+#define	IPM_NEVENTS_FIXED	3
+
+/*
+ * The following events can be programmed on IA32_PMC0/1 of processors based
+ * on Intel Core Solo/Duo processors.
+ */
+static const struct ipm_event_descr ipm_events_v1[] = {
+#define	IPM_EVDESCR(NAME, EVSEL, UMASK, ALLOW)		\
+	{						\
+		.pm_event = PMC_EV_IAP1_##NAME,	\
+		.pm_evsel = (EVSEL),			\
+		.pm_umask = (UMASK),			\
+		.pm_umask_allowed = (ALLOW)		\
+	}
+IPM_EVDESCR(INSTRUCTIONS_RETIRED,		0xC0,	0x00,	0),
+IPM_EVDESCR(UNHALTED_CORE_CYCLES,		0x3C,	0x00,	0),
+IPM_EVDESCR(UNHALTED_REFERENCE_CYCLES,		0x3C,	0x01,	0),
+IPM_EVDESCR(LLC_REFERENCE,			0x2E,	0x4F,	0),
+IPM_EVDESCR(LLC_MISSES,				0x2E,	0x41,	0),
+IPM_EVDESCR(BRANCH_INSTRUCTION_RETIRED,		0xC4,	0x00,	0),
+IPM_EVDESCR(BRANCH_MISSES_RETIRED,		0xC5,	0x00,	0),
+
+IPM_EVDESCR(LD_BLOCKS,				0x03,	0x00,	0),
+IPM_EVDESCR(SD_DRAINS, 				0x04,	0x00,	0),
+IPM_EVDESCR(MISALIGN_MEM_REF, 			0x05,	0x00,	0),
+IPM_EVDESCR(SEG_REG_LOADS, 			0x06,	0x00,	0),
+IPM_EVDESCR(SSE_PREFNTA_RET, 			0x07,	0x00,	0),
+IPM_EVDESCR(SSE_PREFT1_RET, 			0x07,	0x01,	0),	
+IPM_EVDESCR(SSE_PREFT2_RET, 			0x07,	0x02,	0),
+IPM_EVDESCR(SSE_NTSTORES_RET, 			0x07,	0x03,	0),
+IPM_EVDESCR(FP_COMPS_OP_EXE, 			0x10,	0x00,	0),
+IPM_EVDESCR(FP_ASSIST, 				0x11,	0x00,	0),
+IPM_EVDESCR(MUL, 				0x12,	0x00,	0),
+IPM_EVDESCR(DIV, 				0x13,	0x00,	0),
+IPM_EVDESCR(CYCLES_DIV_BUSY, 			0x14,	0x00,	0),
+IPM_EVDESCR(L2_ADS,				0x21,	0xC0,	1),
+IPM_EVDESCR(DBUS_BUSY, 				0x22,	0xC0,	1),
+IPM_EVDESCR(DBUS_BUSY_RD, 			0x23,	0xC0,	1),
+IPM_EVDESCR(L2_LINES_IN, 			0x24,	0XF0,	1),
+IPM_EVDESCR(L2_M_LINES_IN, 			0x25,	0xC0,	1),
+IPM_EVDESCR(L2_LINES_OUT, 			0x26,	0xF0,	1),
+IPM_EVDESCR(L2_M_LINES_OUT, 			0x27,	0xF0,	1),
+IPM_EVDESCR(L2_IFETCH, 				0x28,	0xC0,	1),
+IPM_EVDESCR(L2_LD, 				0x29,	0xC0,	1),
+IPM_EVDESCR(L2_ST, 				0x2A,	0xC0,	1),
+IPM_EVDESCR(L2_RQSTS, 				0x2E,	0xF0,	1),
+IPM_EVDESCR(L2_REJECT_CYCLES, 			0x30,	0xF0,	1),
+IPM_EVDESCR(L2_NO_REQUEST_CYCLES, 		0x32,	0xF0,	1),
+IPM_EVDESCR(EST_TRANS_ALL, 			0x3A,	0x00,	0),
+IPM_EVDESCR(EST_TRANS_FREQ, 			0x3A,	0x10,	0),
+IPM_EVDESCR(THERMAL_TRIP, 			0x3B,	0xC0,	0),
+IPM_EVDESCR(NONHLT_REF_CYCLES, 			0x3C,	0x01,	0),
+IPM_EVDESCR(SERIAL_EXECUTION_CYCLES, 		0x3C,	0x02,	0),
+IPM_EVDESCR(DCACHE_CACHE_LD, 			0x40,	0x0F,	1),
+IPM_EVDESCR(DCACHE_CACHE_ST, 			0x41,	0x0F,	1),
+IPM_EVDESCR(DCACHE_CACHE_LOCK, 			0x42,	0x0F,	1),
+IPM_EVDESCR(DATA_MEM_REF, 			0x43,	0x01,	0),
+IPM_EVDESCR(DATA_MEM_CACHE_REF, 		0x44,	0x02,	0),
+IPM_EVDESCR(DCACHE_REPL, 			0x45,	0x0F,	0),
+IPM_EVDESCR(DCACHE_M_REPL, 			0x46,	0x00,	0),
+IPM_EVDESCR(DCACHE_M_EVICT, 			0x47,	0x00,	0),
+IPM_EVDESCR(DCACHE_PEND_MISS, 			0x48,	0x00,	0),
+IPM_EVDESCR(DTLB_MISS, 				0x49,	0x00,	0),
+IPM_EVDESCR(SSE_PREFNTA_MISS, 			0x4B,	0x00,	0),
+IPM_EVDESCR(SSE_PREFT1_MISS, 			0x4B,	0x01,	0),
+IPM_EVDESCR(SSE_PREFT2_MISS, 			0x4B,	0x02,	0),
+IPM_EVDESCR(SSE_NTSTORES_MISS, 			0x4B,	0x03,	0),
+IPM_EVDESCR(L1_PREF_REQ, 			0x4F,	0x00,	0),
+IPM_EVDESCR(BUS_REQ_OUTSTANDING, 		0x60,	0xE0,	1),
+IPM_EVDESCR(BUS_BNR_CLOCKS, 			0x61,	0x00,	0),
+IPM_EVDESCR(BUS_DRDY_CLOCKS, 			0x62,	0x20,	1),
+IPM_EVDESCR(BUS_LOCK_CLOCKS, 			0x63,	0xC0,	1),
+IPM_EVDESCR(BUS_DATA_RCV, 			0x64,	0x40,	0),
+IPM_EVDESCR(BUS_TRANS_BRD, 			0x65,	0xC0,	1),
+IPM_EVDESCR(BUS_TRANS_RFO, 			0x66,	0xE0,	1),
+IPM_EVDESCR(BUS_TRANS_IFETCH, 			0x68,	0xE0,	1),
+IPM_EVDESCR(BUS_TRANS_INVAL, 			0x69,	0xE0,	1),
+IPM_EVDESCR(BUS_TRANS_PWR, 			0x6A,	0xE0,	1),
+IPM_EVDESCR(BUS_TRANS_P, 			0x6B,	0xE0,	1),
+IPM_EVDESCR(BUS_TRANS_IO, 			0x6C,	0xE0,	1),
+IPM_EVDESCR(BUS_TRANS_DEF, 			0x6D,	0xE0,	1),
+IPM_EVDESCR(BUS_TRANS_WB, 			0x67,	0xE0,	1),
+IPM_EVDESCR(BUS_TRANS_BURST, 			0x6E,	0xE0,	1),
+IPM_EVDESCR(BUS_TRANS_MEM, 			0x6F,	0xE0,	1),
+IPM_EVDESCR(BUS_TRANS_ANY, 			0x70,	0xE0,	1),
+IPM_EVDESCR(BUS_SNOOPS, 			0x77,	0x2F,	1),
+IPM_EVDESCR(DCU_SNOOP_TO_SHARE, 		0x78,	0xC1,	1),
+IPM_EVDESCR(BUS_NOT_IN_USE, 			0x7D,	0xC0,	1),
+IPM_EVDESCR(BUS_SNOOP_STALL, 			0x7E,	0x00,	0),
+IPM_EVDESCR(ICACHE_READS, 			0x80,	0x00,	0),
+IPM_EVDESCR(ICACHE_MISSES, 			0x81,	0x00,	0),
+IPM_EVDESCR(ITLB_MISSES, 			0x85,	0x00,	0),
+IPM_EVDESCR(IFU_MEM_STALL, 			0x86,	0x00,	0),
+IPM_EVDESCR(ILD_STALL, 				0x87,	0x00,	0),
+IPM_EVDESCR(BR_INST_EXEC, 			0x88,	0x00,	0),
+IPM_EVDESCR(BR_MISSP_EXEC, 			0x89,	0x00,	0),
+IPM_EVDESCR(BR_BAC_MISSP_EXEC, 			0x8A,	0x00,	0),
+IPM_EVDESCR(BR_CND_EXEC, 			0x8B,	0x00,	0),
+IPM_EVDESCR(BR_CND_MISSP_EXEC, 			0x8C,	0x00,	0),
+IPM_EVDESCR(BR_IND_EXEC, 			0x8D,	0x00,	0),
+IPM_EVDESCR(BR_IND_MISSP_EXEC, 			0x8E,	0x00,	0),
+IPM_EVDESCR(BR_RET_EXEC, 			0x8F,	0x00,	0),
+IPM_EVDESCR(BR_RET_MISSP_EXEC, 			0x90,	0x00,	0),
+IPM_EVDESCR(BR_RET_BAC_MISSP_EXEC,	 	0x91,	0x00,	0),
+IPM_EVDESCR(BR_CALL_EXEC, 			0x92,	0x00,	0),
+IPM_EVDESCR(BR_CALL_MISSP_EXEC, 		0x93,	0x00,	0),
+IPM_EVDESCR(BR_IND_CALL_EXEC, 			0x94,	0x00,	0),
+IPM_EVDESCR(RESOURCE_STALL, 			0xA2,	0x00,	0),
+IPM_EVDESCR(MMX_INSTR_EXEC, 			0xB0,	0x00,	0),
+IPM_EVDESCR(SIMD_INT_SAT_EXEC, 			0xB1,	0x00,	0),
+IPM_EVDESCR(SIMD_INT_PMUL_EXEC, 		0xB3,	0x01,	0),
+IPM_EVDESCR(SIMD_INT_PSFT_EXEC, 		0xB3,	0x02,	0),
+IPM_EVDESCR(SIMD_INT_PCK_EXEC, 			0xB3,	0x04,	0),
+IPM_EVDESCR(SIMD_INT_UPCK_EXEC, 		0xB3,	0x08,	0),
+IPM_EVDESCR(SIMD_INT_PLOG_EXEC, 		0xB3,	0x10,	0),
+IPM_EVDESCR(SIMD_INT_PARI_EXEC, 		0xB3,	0x20,	0),
+IPM_EVDESCR(INSTR_RET, 				0xC0,	0x00,	0),
+IPM_EVDESCR(FP_COMP_INSTR_RET, 			0xC1,	0x00,	0),
+IPM_EVDESCR(UOPS_RET, 				0xC2,	0x00,	0),
+IPM_EVDESCR(SMC_DETECTED, 			0xC3,	0x00,	0),
+IPM_EVDESCR(BR_INSTR_RET, 			0xC4,	0x00,	0),
+IPM_EVDESCR(BR_MISPRED_RET, 			0xC5,	0x00,	0),
+IPM_EVDESCR(CYCLES_INT_MASKED, 			0xC6,	0x00,	0),
+IPM_EVDESCR(CYCLES_INT_PENDING_MASKED, 		0xC7,	0x00,	0),
+IPM_EVDESCR(HW_INT_RX, 				0xC8,	0x00,	0),
+IPM_EVDESCR(BR_TAKEN_RET, 			0xC9,	0x00,	0),
+IPM_EVDESCR(BR_MISPRED_TAKEN_RET, 		0xCA,	0x00,	0),
+IPM_EVDESCR(MMX_FP_TRANS, 			0xCC,	0x00,	0),
+IPM_EVDESCR(FP_MMX_TRANS, 			0xCC,	0x01,	0),
+IPM_EVDESCR(MMX_ASSIST, 			0xCD,	0x00,	0),
+IPM_EVDESCR(MMX_INST_RET, 			0xCE,	0x00,	0),
+IPM_EVDESCR(INSTR_DECODED, 			0xD0,	0x00,	0),
+IPM_EVDESCR(ESP_UOPS, 				0xD7,	0x00,	0),
+IPM_EVDESCR(SIMD_FP_SP_RET, 			0xD8,	0x00,	0),
+IPM_EVDESCR(SIMD_FP_SP_S_RET, 			0xD8,	0x01,	0),
+IPM_EVDESCR(SIMD_FP_DP_P_RET, 			0xD8,	0x02,	0),
+IPM_EVDESCR(SIMD_FP_DP_S_RET, 			0xD8,	0x03,	0),
+IPM_EVDESCR(SIMD_INT_128_RET, 			0xD8,	0x04,	0),
+IPM_EVDESCR(SIMD_FP_SP_P_COMP_RET, 		0xD9,	0x00,	0),
+IPM_EVDESCR(SIMD_FP_SP_S_COMP_RET, 		0xD9,	0x01,	0),
+IPM_EVDESCR(SIMD_FP_DP_P_COMP_RET,	 	0xD9,	0x02,	0),
+IPM_EVDESCR(SIMD_FP_SP_S_COMP_RET,	 	0xD9,	0x03,	0),
+IPM_EVDESCR(FUSED_UOPS_RET, 			0xDA,	0x00,	0),
+IPM_EVDESCR(FUSED_LD_UOPS_RET, 			0xDA,	0x01,	0),
+IPM_EVDESCR(FUSED_ST_UOPS_RET, 			0xDA,	0x02,	0),
+IPM_EVDESCR(UNFUSION, 				0xDB,	0x00,	0),
+IPM_EVDESCR(BR_INSTR_DECODED, 			0xE0,	0x00,	0),
+IPM_EVDESCR(BTB_MISSES, 			0xE2,	0x00,	0),
+IPM_EVDESCR(BR_BOGUS, 				0xE4,	0x00,	0),
+IPM_EVDESCR(BACLEARS, 				0xE6,	0x00,	0),
+IPM_EVDESCR(PREF_RQSTS_UP, 			0xF0,	0x00,	0),
+IPM_EVDESCR(PREF_RQSTS_DN,	 		0xF8,	0x00,	0),
+
+#undef IPM_EVDESCR
+};
+#define	IPM_NEVENTS_V1	(PMC_EV_IAP1_LAST - PMC_EV_IAP1_FIRST + 1)
+
+/*
+ * The following events can be programmed on IA32_PMC0/1 of processors based
+ * on Intel Core microarchitecture.
+ */
+static const struct ipm_event_descr ipm_events_v2[] = {
+#define	IPM_EVDESCR(NAME, EVSEL, UMASK, ALLOW)		\
+	{						\
+		.pm_event = PMC_EV_IAP2_##NAME,	\
+		.pm_evsel = (EVSEL),			\
+		.pm_umask = (UMASK),			\
+		.pm_umask_allowed = (ALLOW)		\
+	}
+IPM_EVDESCR(INSTRUCTIONS_RETIRED,		0xC0,	0x00,	0),
+IPM_EVDESCR(UNHALTED_CORE_CYCLES,		0x3C,	0x00,	0),
+IPM_EVDESCR(UNHALTED_REFERENCE_CYCLES,		0x3C,	0x01,	0),
+IPM_EVDESCR(LLC_REFERENCE,			0x2E,	0x4F,	0),
+IPM_EVDESCR(LLC_MISSES,				0x2E,	0x41,	0),
+IPM_EVDESCR(BRANCH_INSTRUCTION_RETIRED,		0xC4,	0x00,	0),
+IPM_EVDESCR(BRANCH_MISSES_RETIRED,		0xC5,	0x00,	0),
+
+IPM_EVDESCR(LOAD_BLOCK_STA,			0x03, 	0x02,	0), 
+IPM_EVDESCR(LOAD_BLOCK_STD, 			0x03, 	0x04, 	0),
+IPM_EVDESCR(LOAD_BLOCK_OVERLAP_STORE, 		0x03, 	0x08, 	0),
+IPM_EVDESCR(LOAD_BLOCK_UNTIL_RETIRE, 		0x03, 	0x10, 	0),
+IPM_EVDESCR(LOAD_BLOCK_L1D, 			0x03, 	0x20, 	0),
+IPM_EVDESCR(SB_DRAIN_CYCLES, 			0x04, 	0x01, 	0),
+IPM_EVDESCR(STORE_BLOCK_ORDER, 			0x04, 	0x02, 	0),
+IPM_EVDESCR(STORE_BLOCK_SNOOP, 			0x04,	0x08,	0),
+IPM_EVDESCR(MISALIGN_MEM_REF, 			0x05,	0x00,	0),
+IPM_EVDESCR(SEGMENT_REG_LOADS, 			0x06,	0x00,	0),
+IPM_EVDESCR(SSE_PRE_EXEC_NTA, 			0x07,	0x00,	0),
+IPM_EVDESCR(SSE_PRE_EXEC_L1, 			0x07,	0x01,	0),
+IPM_EVDESCR(SSE_PRE_EXEC_L2, 			0x07,	0x02,	0),
+IPM_EVDESCR(SSE_PRE_EXEC_STORES, 		0x07,	0x03,	0),
+IPM_EVDESCR(DTLB_MISSES_ANY, 			0x08,	0x01,	0),
+IPM_EVDESCR(DTLB_MISSES_MISS_LD, 		0x08,	0x02,	0),
+IPM_EVDESCR(L0_DTLB_MISSES_MISS_LD, 		0x08,	0x04,	0),
+IPM_EVDESCR(DTLB_MISSES_MISS_ST, 		0x08,	0x08,	0),
+IPM_EVDESCR(MEMORY_DISAMBIGUATION_RESET, 	0x09,	0x01,	0),
+IPM_EVDESCR(MEMORY_DISAMBIGUATION_SUCCESS,	0x09,	0x02,	0),
+IPM_EVDESCR(PAGE_WALKS_COUNT, 			0x0C,	0x01,	0),
+IPM_EVDESCR(PAGE_WALKS_CYCLES, 			0x0C,	0x02,	0),
+IPM_EVDESCR(FP_COMP_OPS_EXE, 			0x10,	0x00,	0),
+IPM_EVDESCR(FP_ASSIST, 				0x11,	0x00,	0),
+IPM_EVDESCR(MUL, 				0x12,	0x00,	0),
+IPM_EVDESCR(DIV, 				0x13,	0x00,	0),
+IPM_EVDESCR(CYCLES_DIV_BUSY, 			0x14,	0x00,	0),
+IPM_EVDESCR(IDLE_DURING_DIV, 			0x18,	0x00,	0),
+IPM_EVDESCR(DELAYED_BYPASS_FP, 			0x19,	0x00,	0),
+IPM_EVDESCR(DELAYED_BYPASS_SIMD, 		0x19,	0x01,	0),
+IPM_EVDESCR(DELAYED_BYPASS_LOAD, 		0x19,	0x02,	0),
+IPM_EVDESCR(L2_ADS, 				0x21,	0xC0,	1),
+IPM_EVDESCR(L2_DBUS_BUSY_RD, 			0x23,	0xC0,	1),
+IPM_EVDESCR(L2_LINES_IN, 			0x24,	0xF0,	1),
+IPM_EVDESCR(L2_M_LINES_IN, 			0x25,	0xC0,	1),
+IPM_EVDESCR(L2_LINES_OUT, 			0x26,	0xF0,	1),
+IPM_EVDESCR(L2_M_LINES_OUT, 			0x27,	0xF0,	1),
+IPM_EVDESCR(L2_IFETCH, 				0x28,	0xCF,	1),
+IPM_EVDESCR(L2_LD, 				0x29,	0xFF,	1),
+IPM_EVDESCR(L2_ST, 				0x2A,	0xCF,	1),
+IPM_EVDESCR(L2_LOCK, 				0x2B,	0xCF,	1),
+IPM_EVDESCR(L2_RQSTS, 				0x2E,	0xFF,	1),
+IPM_EVDESCR(L2_RQSTS_SELF_DEMAND_I_STATE,	0x2E,	0x41,	0),
+IPM_EVDESCR(L2_RQSTS_SELF_DEMAND_MESI,		0x2E,	0x4F,	0),
+IPM_EVDESCR(L2_REJECT_BUSQ, 			0x30,	0xFF,	1),
+IPM_EVDESCR(L2_NO_REQ, 				0x32,	0xC0,	1),
+IPM_EVDESCR(EIST_TRANS, 			0x3A,	0x00,	0),
+IPM_EVDESCR(THERMAL_TRIP,			0x3B,	0xC0,	0),
+IPM_EVDESCR(CPU_CLK_UNHALTED_CORE, 		0x3C,	0x00,	0),
+IPM_EVDESCR(CPU_CLK_UNHALTED_BUS, 		0x3C,	0x01,	0),
+IPM_EVDESCR(CPU_CLK_UNHALTED_NO_OTHER, 		0x3C,	0x02,	0),
+IPM_EVDESCR(L1D_CACHE_LD, 			0x40,	0x0F,	1),
+IPM_EVDESCR(L1D_CACHE_ST, 			0x40,	0x0F,	1),
+IPM_EVDESCR(L1D_CACHE_LOCK, 			0x42,	0x0F,	1),
+IPM_EVDESCR(L1D_CACHE_LOCK_DURATION, 		0x42,	0x10,	0),
+IPM_EVDESCR(L1D_ALL_REF, 			0x43,	0x10,	0),
+IPM_EVDESCR(L1D_ALL_CACHE_REF, 			0x43,	0x02,	0),
+IPM_EVDESCR(L1D_REPL, 				0x45,	0x0F,	0),
+IPM_EVDESCR(L1D_M_REPL, 			0x46,	0x00,	0),
+IPM_EVDESCR(L1D_M_EVICT, 			0x47,	0x00,	0),
+IPM_EVDESCR(L1D_PEND_MISS, 			0x48,	0x00,	0),
+IPM_EVDESCR(L1D_SPLIT_LOADS, 			0x49,	0x01,	0),
+IPM_EVDESCR(L1D_SPLIT_STORES, 			0x49,	0x02,	0),
+IPM_EVDESCR(SSE_PRE_MISS_NTA, 			0x4B,	0x00,	0),
+IPM_EVDESCR(SSE_PRE_MISS_L1, 			0x4B,	0x01,	0),
+IPM_EVDESCR(SSE_PRE_MISS_L2, 			0x4B,	0x02,	0),
+IPM_EVDESCR(LOAD_HIT_PRE, 			0x4C,	0x00,	0),
+IPM_EVDESCR(L1D_PREFETCH_REQUESTS, 		0x4E,	0x10,	0),
+IPM_EVDESCR(BUS_REQUEST_OUTSTANDING, 		0x60,	0xE0,	1),
+IPM_EVDESCR(BUS_BNR_DRV, 			0x61,	0x20,	1),
+IPM_EVDESCR(BUS_DRDY_CLOCKS, 			0x62,	0x20,	1),
+IPM_EVDESCR(BUS_LOCK_CLOCKS, 			0x63,	0xE0,	1),
+IPM_EVDESCR(BUS_DATA_RCV, 			0x64,	0xC0,	1),
+IPM_EVDESCR(BUS_TRANS_BRD, 			0x65,	0xC0,	1),
+IPM_EVDESCR(BUS_TRANS_RFO, 			0x66,	0xC0,	1),
+IPM_EVDESCR(BUS_TRANS_WB, 			0x67,	0xC0,	1),
+IPM_EVDESCR(BUS_TRANS_IFETCH, 			0x68,	0xC0,	1),
+IPM_EVDESCR(BUS_TRANS_INVAL, 			0x69,	0xC0,	1),
+IPM_EVDESCR(BUS_TRANS_PWR, 			0x6A,	0xC0,	1),
+IPM_EVDESCR(BUS_TRANS_P,			0x6B,	0xC0,	1),
+IPM_EVDESCR(BUS_TRANS_IO, 			0x6C,	0xC0,	1),
+IPM_EVDESCR(BUS_TRANS_DEF, 			0x6D,	0xC0,	1),
+IPM_EVDESCR(BUS_TRANS_BURST, 			0x6E,	0xC0,	1),
+IPM_EVDESCR(BUS_TRANS_MEM, 			0x6F,	0xC0,	1),
+IPM_EVDESCR(BUS_TRANS_ANY, 			0x70,	0xC0,	1),
+IPM_EVDESCR(EXT_SNOOP, 				0x77,	0xCB,	1),
+IPM_EVDESCR(CMP_SNOOP, 				0x78,	0xC3,	1),
+IPM_EVDESCR(BUS_HIT_DRV, 			0x7A,	0x20,	1),
+IPM_EVDESCR(BUS_HITM_DRV, 			0x7B,	0x20,	1),
+IPM_EVDESCR(BUSQ_EMPTY, 			0x7D,	0xC0,	1),
+IPM_EVDESCR(SNOOP_STALL_DRV, 			0x7E,	0xE0,	1),
+IPM_EVDESCR(BUS_IO_WAIT, 			0x7F,	0xC0,	1),
+IPM_EVDESCR(L1I_READS, 				0x80,	0x00,	0),
+IPM_EVDESCR(L1I_MISSES, 			0x81,	0x00,	0),
+IPM_EVDESCR(ITLB_SMALL_MISS, 			0x82,	0x02,	0),
+IPM_EVDESCR(ITLB_LARGE_MISS, 			0x82,	0x10,	0),
+IPM_EVDESCR(ITLB_FLUSH, 			0x82,	0x40,	0),
+IPM_EVDESCR(ITLB_MISSES, 			0x82,	0x12,	0),
+IPM_EVDESCR(INST_QUEUE_FULL, 			0x83,	0x02,	0),
+IPM_EVDESCR(CYCLES_L1I_MEM_STALLED, 		0x86,	0x00,	0),
+IPM_EVDESCR(ILD_STALL, 				0x87,	0x00,	0),
+IPM_EVDESCR(BR_INST_EXEC, 			0x88,	0x00,	0),
+IPM_EVDESCR(BR_MISSP_EXEC, 			0x89,	0x00,	0),
+IPM_EVDESCR(BR_BAC_MISSP_EXEC, 			0x8A,	0x00,	0),
+IPM_EVDESCR(BR_CND_EXEC, 			0x8B,	0x00,	0),
+IPM_EVDESCR(BR_CND_MISSP_EXEC, 			0x8C,	0x00,	0),
+IPM_EVDESCR(BR_IND_EXEC, 			0x8D,	0x00,	0),
+IPM_EVDESCR(BR_IND_MISSP_EXEC, 			0x8E,	0x00,	0),
+IPM_EVDESCR(BR_RET_EXEC, 			0x8F,	0x00,	0),
+IPM_EVDESCR(BR_RET_MISSP_EXEC, 			0x90,	0x00,	0),
+IPM_EVDESCR(BR_RET_BAC_MISSP_EXEC, 		0x91,	0x00,	0),
+IPM_EVDESCR(BR_CALL_EXEC, 			0x92,	0x00,	0),
+IPM_EVDESCR(BR_CALL_MISSP_EXEC, 		0x93,	0x00,	0),
+IPM_EVDESCR(BR_IND_CALL_EXEC, 			0x94,	0x00,	0),
+IPM_EVDESCR(BR_TKN_BUBBLE_1, 			0x97,	0x00,	0),
+IPM_EVDESCR(BR_TKN_BUBBLE_2, 			0x98,	0x00,	0),
+IPM_EVDESCR(RS_UOPS_DISPATCHED, 		0xA0,	0x00,	0),
+IPM_EVDESCR(RS_UOPS_DISPATCHED_PORT0, 		0xA0,	0x01,	0),
+IPM_EVDESCR(RS_UOPS_DISPATCHED_PORT1, 		0xA0,	0x02,	0),
+IPM_EVDESCR(RS_UOPS_DISPATCHED_PORT2, 		0xA0,	0x04,	0),
+IPM_EVDESCR(RS_UOPS_DISPATCHED_PORT3, 		0xA0,	0x08,	0),
+IPM_EVDESCR(RS_UOPS_DISPATCHED_PORT4, 		0xA0,	0x10,	0),
+IPM_EVDESCR(RS_UOPS_DISPATCHED_PORT5, 		0xA0,	0x20,	0),
+IPM_EVDESCR(MACRO_INSTS_DECODED, 		0xA1,	0x01,	0),
+IPM_EVDESCR(MACRO_INSTS_CISC_DECODED,		0xA1,	0x08,	0),
+IPM_EVDESCR(ESP_SYNCH, 				0xAB,	0x01,	0),
+IPM_EVDESCR(ESP_ADDITIONS, 			0xAB,	0x02,	0),
+IPM_EVDESCR(SIMD_UOPS_EXEC, 			0xB0,	0x00,	0),
+IPM_EVDESCR(SIMD_SAT_UOP_EXEC, 			0xB1,	0x00,	0),
+IPM_EVDESCR(SIMD_UOP_TYPE_EXEC_MUL, 		0xB3,	0x01,	0),
+IPM_EVDESCR(SIMD_UOP_TYPE_EXEC_SHIFT,		0xB3,	0x02,	0),
+IPM_EVDESCR(SIMD_UOP_TYPE_EXEC_PACK,		0xB3,	0x04,	0),
+IPM_EVDESCR(SIMD_UOP_TYPE_EXEC_UNPACK,		0xB3,	0x08,	0),
+IPM_EVDESCR(SIMD_UOP_TYPE_EXEC_LOGICAL,		0xB3,	0x10,	0),
+IPM_EVDESCR(SIMD_UOP_TYPE_EXEC_ARITHMETIC,	0xB3,	0x20,	0),
+IPM_EVDESCR(INST_RETIRED_ANY_P, 		0xC0,	0x00,	0),
+IPM_EVDESCR(INST_RETIRED_LOADS, 		0xC0,	0x01,	0),
+IPM_EVDESCR(INST_RETIRED_STORES, 		0xC0,	0x02,	0),
+IPM_EVDESCR(INST_RETIRED_OTHER, 		0xC0,	0x04,	0),
+IPM_EVDESCR(X87_OPS_RETIRED_FXCH, 		0xC1,	0x01,	0),
+IPM_EVDESCR(X87_OPS_RETIRED_ANY, 		0xC1,	0xFE,	0),
+IPM_EVDESCR(UOPS_RETIRED_L2_IND_BR, 		0xC2,	0x01,	0),
+IPM_EVDESCR(UOPS_RETIRED_STD_STA, 		0xC2,	0x02,	0),
+IPM_EVDESCR(UOPS_RETIRED_MACRO_FUSION,		0xC2,	0x04,	0),
+IPM_EVDESCR(UOPS_RETIRED_FUSED, 		0xC2,	0x07,	0),
+IPM_EVDESCR(UOPS_RETIRED_NON_FUSED, 		0xC2,	0x08,	0),
+IPM_EVDESCR(UOPS_RETIRED_ANY, 			0xC2,	0x0F,	0),
+IPM_EVDESCR(MACHINE_NUKES_SMC, 			0xC3,	0x01,	0),
+IPM_EVDESCR(MACHINE_NUKES_MEM_ORDER,		0xC3,	0x04,	0),
+IPM_EVDESCR(BR_INST_RETIRED_ANY, 		0xC4,	0x00,	0),
+IPM_EVDESCR(BR_INST_RETIRED_PRED_NOT_TAKEN,	0xC4,	0x01,	0),
+IPM_EVDESCR(BR_INST_RETIRED_MISPRED_NOT_TAKEN,	0xC4,	0x02,	0),
+IPM_EVDESCR(BR_INST_RETIRED_PRED_TAKEN,		0xC4,	0x04,	0),
+IPM_EVDESCR(BR_INST_RETIRED_MISPRED_TAKEN,	0xC4,	0x08,	0),
+IPM_EVDESCR(BR_INST_RETIRED_TAKEN, 		0xC4,	0x0C,	0),
+IPM_EVDESCR(BR_INST_RETIRED_MISPRED,		0xC5,	0x00,	0),
+IPM_EVDESCR(CYCLES_INT_MASKED, 			0xC6,	0x01,	0),
+IPM_EVDESCR(CYCLES_INT_PENDING_AND_MASKED,	0xC6,	0x02,	0),
+IPM_EVDESCR(SIMD_INST_RETIRED_PACKED_SINGLE, 	0xC7,	0x01,	0),
+IPM_EVDESCR(SIMD_INST_RETIRED_SCALAR_SINGLE, 	0xC7,	0x02,	0),
+IPM_EVDESCR(SIMD_INST_RETIRED_PACKED_DOUBLE, 	0xC7,	0x04,	0),
+IPM_EVDESCR(SIMD_INST_RETIRED_SCALAR_DOUBLE, 	0xC7,	0x08,	0),
+IPM_EVDESCR(SIMD_INST_RETIRED_VECTOR, 	 	0xC7,	0x10,	0),
+IPM_EVDESCR(SIMD_INST_RETIRED_ANY, 		0xC7,	0x1F,	0),
+IPM_EVDESCR(HW_INT_RCV, 			0xC8,	0x00,	0),
+IPM_EVDESCR(ITLB_MISS_RETIRED, 			0xC9,	0x00,	0),
+IPM_EVDESCR(SIMD_COMP_INST_RETIRED_PACKED_SINGLE,	0xCA,	0x01,	0),
+IPM_EVDESCR(SIMD_COMP_INST_RETIRED_SCALAR_SINGLE, 	0xCA,	0x02,	0),
+IPM_EVDESCR(SIMD_COMP_INST_RETIRED_PACKED_DOUBLE, 	0xCA,	0x04,	0),
+IPM_EVDESCR(SIMD_COMP_INST_RETIRED_SCALAR_DOUBLE,	0xCA,	0x08,	0),
+IPM_EVDESCR(MEM_LOAD_RETIRED_L1D_MISS,		0xCB,	0x01,	0),
+IPM_EVDESCR(MEM_LOAD_RETIRED_L1D_LINE_MISS,	0xCB,	0x02,	0),
+IPM_EVDESCR(MEM_LOAD_RETIRED_L2_MISS, 		0xCB,	0x04,	0),
+IPM_EVDESCR(MEM_LOAD_RETIRED_L2_LINE_MISS,	0xCB,	0x08,	0),
+IPM_EVDESCR(MEM_LOAD_RETIRED_DTLB_MISS, 	0xCB,	0x10,	0),
+IPM_EVDESCR(FP_MMX_TRANS_TO_MMX, 		0xCC,	0x01,	0),
+IPM_EVDESCR(FP_MMX_TRANS_TO_FP, 		0xCC,	0x02,	0),
+IPM_EVDESCR(SIMD_ASSIST, 			0xCD,	0x00,	0),
+IPM_EVDESCR(SIMD_INST_RETIRED, 			0xCE,	0x00,	0),
+IPM_EVDESCR(SIMD_SAT_INST_RETIRED, 		0xCF,	0x00,	0),
+IPM_EVDESCR(RAT_STALLS_ROB_READ_PORT,		0xD2,	0x01,	0),
+IPM_EVDESCR(RAT_STALLS_PARTIAL_CYCLES,		0xD2,	0x02,	0),
+IPM_EVDESCR(RAT_STALLS_FLAGS, 			0xD2,	0x04,	0),
+IPM_EVDESCR(RAT_STALLS_FPSW, 			0xD2,	0x08,	0),
+IPM_EVDESCR(RAT_STALLS_ANY, 			0xD2,	0x0F,	0),
+IPM_EVDESCR(SEG_RENAME_STALLS_ES, 		0xD4,	0x01,	0),
+IPM_EVDESCR(SEG_RENAME_STALLS_DS, 		0xD4,	0x02,	0),
+IPM_EVDESCR(SEG_RENAME_STALLS_FS, 		0xD4,	0x04,	0),
+IPM_EVDESCR(SEG_RENAME_STALLS_GS, 		0xD4,	0x08,	0),
+IPM_EVDESCR(SEG_RENAME_STALLS_ANY, 		0xD4,	0x0F,	0),
+IPM_EVDESCR(SEG_REG_RENAME_ES, 			0xD4,	0x01,	0),
+IPM_EVDESCR(SEG_REG_RENAME_DS, 			0xD5,	0x02,	0),
+IPM_EVDESCR(SEG_REG_RENAME_FS, 			0xD5,	0x04,	0),
+IPM_EVDESCR(SEG_REG_RENAME_GS, 			0xD5,	0x08,	0),
+IPM_EVDESCR(SEG_REG_RENAME_ANY, 		0xD5,	0x0F,	0),
+IPM_EVDESCR(RESOURCE_STALLS_ROB_FULL, 		0xDC,	0x01,	0),
+IPM_EVDESCR(RESOURCE_STALLS_RS_FULL, 		0xDC,	0x02,	0),
+IPM_EVDESCR(RESOURCE_STALLS_LD_ST, 		0xDC,	0x04,	0),
+IPM_EVDESCR(RESOURCE_STALLS_FPCW, 		0xDC,	0x08,	0),
+IPM_EVDESCR(RESOURCE_STALLS_BR_MISS_CLEAR,	0xDC,	0x10,	0),
+IPM_EVDESCR(RESOURCE_STALLS_ANY, 		0xDC,	0x1F,	0),
+IPM_EVDESCR(BR_INST_DECODED, 			0xE0,	0x00,	0),
+IPM_EVDESCR(BOGUS_BR, 				0xE4,	0x00,	0),
+IPM_EVDESCR(BACLEARS, 				0xE6,	0x00,	0),
+IPM_EVDESCR(PREF_RQSTS_UP, 			0xF0,	0x00,	0),
+IPM_EVDESCR(PREF_RQSTS_DN, 			0xF8,	0x00,	0)
+
+#undef	IPM_EVDESCR
+};
+#define	IPM_NEVENTS_V2	(PMC_EV_IAP2_LAST - PMC_EV_IAP2_FIRST + 1)
+
+/*
+ * Events defined here can only be programmed on the specified raw index
+ */
+struct ipm_ev_pmc_mapping {
+	const enum pmc_event	pm_event;
+	const int 		pm_ri;
+};
+
+static const struct ipm_ev_pmc_mapping ipm_ev_pmc_mappings_v1[] = {
+#define	IPM_EV_PMC_MAPPING(NAME, RI)			\
+	{						\
+		.pm_event = PMC_EV_IAP1_##NAME,	\
+		.pm_ri	  = (RI),			\
+	}
+IPM_EV_PMC_MAPPING(FP_ASSIST,			2),
+IPM_EV_PMC_MAPPING(MUL,				2),
+IPM_EV_PMC_MAPPING(DIV,				2),
+IPM_EV_PMC_MAPPING(CYCLES_DIV_BUSY,		1),
+IPM_EV_PMC_MAPPING(FP_COMP_INSTR_RET,		1),
+
+#undef	IPM_EV_PMC_MAPPING
+};
+#define	IAP1_NMAPPINGS		5
+
+static const struct ipm_ev_pmc_mapping ipm_ev_pmc_mappings_v2[] = {
+#define	IPM_EV_PMC_MAPPING(NAME, RI)			\
+	{						\
+		.pm_event = PMC_EV_IAP2_##NAME,	\
+		.pm_ri	  = (RI),			\
+	}
+IPM_EV_PMC_MAPPING(FP_COMP_OPS_EXE,		1),
+IPM_EV_PMC_MAPPING(FP_ASSIST,			2),
+IPM_EV_PMC_MAPPING(MUL,				2),
+IPM_EV_PMC_MAPPING(DIV,				2),
+IPM_EV_PMC_MAPPING(CYCLES_DIV_BUSY,		1),
+IPM_EV_PMC_MAPPING(IDLE_DURING_DIV,		1),
+IPM_EV_PMC_MAPPING(DELAYED_BYPASS_FP,		2),
+IPM_EV_PMC_MAPPING(DELAYED_BYPASS_SIMD,		2),
+IPM_EV_PMC_MAPPING(DELAYED_BYPASS_LOAD,		2),
+IPM_EV_PMC_MAPPING(RS_UOPS_DISPATCHED_PORT0,	1),
+IPM_EV_PMC_MAPPING(RS_UOPS_DISPATCHED_PORT1,	1),
+IPM_EV_PMC_MAPPING(RS_UOPS_DISPATCHED_PORT2,	1),
+IPM_EV_PMC_MAPPING(RS_UOPS_DISPATCHED_PORT3,	1),
+IPM_EV_PMC_MAPPING(RS_UOPS_DISPATCHED_PORT4,	1),
+IPM_EV_PMC_MAPPING(RS_UOPS_DISPATCHED_PORT5,	1),
+IPM_EV_PMC_MAPPING(MEM_LOAD_RETIRED_L1D_MISS,	1),
+IPM_EV_PMC_MAPPING(MEM_LOAD_RETIRED_L1D_LINE_MISS,	1),
+IPM_EV_PMC_MAPPING(MEM_LOAD_RETIRED_L2_MISS,	1),
+IPM_EV_PMC_MAPPING(MEM_LOAD_RETIRED_L2_LINE_MISS,	1),
+IPM_EV_PMC_MAPPING(MEM_LOAD_RETIRED_DTLB_MISS,	1),
+
+#undef	IPM_EV_PMC_MAPPING
+};
+#define	IAP2_NMAPPINGS		20
+
+static const struct ipm_ev_pmc_mapping *ipm_ev_pmc_mappings = NULL;
+static int ipm_nmappings = 0;
+
+static inline int 
+ipm_ev_valid_for_pmc(enum pmc_event ev, int ri)
+{
+	int valid = 1;
+	int i = 0;
+
+	for (; i < ipm_nmappings; i++) {
+		if (ev == ipm_ev_pmc_mappings[i].pm_event &&
+		    ri != ipm_ev_pmc_mappings[i].pm_ri)
+			valid = 0;
+	}
+
+	return (valid);
+}
+
+
+static const struct ipm_event_descr *
+ipm_find_event(enum pmc_event ev)
+{
+	int n;
+
+	if (ipm_cputype == PMC_CPU_INTEL_CORE ||
+	    ipm_cputype == PMC_CPU_INTEL_CORE2 ||
+    	    ipm_cputype == PMC_CPU_INTEL_ATOM) {
+		for (n = 0; n < IPM_NEVENTS_FIXED; n++) 
+			if (ipm_events_fixed[n].pm_event == ev)
+				return (&ipm_events_fixed[n]);
+	}
+
+	for (n = 0; n < ipm_nevents; n++) {
+		if (ipm_events[n].pm_event == ev)
+			return (&ipm_events[n]);
+	}
+
+	return (NULL);
+}
+
+/*
+ * Per-CPU data structure for Intel Core Solo/Duo class CPUs
+ *
+ * [common stuff]
+ * [flags for maintaining PMC start/stop state]
+ * [3 struct pmc_hw pointers]
+ * [3 struct pmc_hw structures]
+ */
+struct ipm_cpu {
+	struct pmc_cpu	pc_common;
+	struct pmc_hw	*pc_hwpmcs[IPM_NPMCS];
+	struct pmc_hw	pc_ipm_pmcs[IPM_NPMCS];
+	uint32_t	pc_state;
+};
+
+#define	IPM_PMC_MARK_STARTED(PC,RI) do {			\
+		(PC)->pc_state |= (1 << ((RI)-1));		\
+	} while (0)
+
+#define	IPM_PMC_MARK_STOPPED(PC,RI) do {			\
+		(PC)->pc_state &= ~(1<< ((RI)-1));		\
+	} while (0)
+
+#define	IPM_PMC_STOPPED(PC,RI)	(((PC)->pc_state & (1 << ((RI)-1))) == 0)
+#define IPM_PMC_STARTED(PC,RI)	(((PC)->pc_state & (1 << ((RI)-1))) == 1)
+
+static int
+ipm_init(int cpu)
+{
+	int n;
+	struct ipm_cpu *pcs;
+	struct pmc_hw *phw;
+
+	KASSERT(cpu >= 0 && cpu < mp_ncpus,
+	    ("[ipm,%d] bad cpu %d", __LINE__, cpu));
+
+	PMCDBG(MDP,INI,0,"ipm-init cpu=%d", cpu);
+
+	MALLOC(pcs, struct ipm_cpu *, sizeof(struct ipm_cpu), M_PMC,
+	    M_WAITOK|M_ZERO);
+
+	phw = pcs->pc_ipm_pmcs;
+
+	for (n = 0; n < ipm_npmcs; n++, phw++) {
+		phw->phw_state	  = PMC_PHW_FLAG_IS_ENABLED |
+		    PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(n);
+		phw->phw_pmc      = NULL;
+		pcs->pc_hwpmcs[n] = phw;
+	}
+
+	/* Mark the TSC as shareable */
+	pcs->pc_hwpmcs[0]->phw_state |= PMC_PHW_FLAG_IS_SHAREABLE;
+
+	pmc_pcpu[cpu] = (struct pmc_cpu *) pcs;
+
+	return (0);
+}
+
+static int
+ipm_cleanup(int cpu)
+{
+	struct pmc_cpu *pcs;
+
+	KASSERT(cpu >= 0 && cpu < mp_ncpus,
+	    ("[ipm,%d] bad cpu %d", __LINE__, cpu));
+
+	PMCDBG(MDP,INI,0,"ipm-cleanup cpu=%d", cpu);
+
+	if ((pcs = pmc_pcpu[cpu]) != NULL)
+		FREE(pcs, M_PMC);
+	pmc_pcpu[cpu] = NULL;
+
+	return (0);
+}
+
+static int
+ipm_switch_in(struct pmc_cpu *pc, struct pmc_process *pp)
+{
+	(void) pc;
+
+	PMCDBG(MDP,SWI,1, "pc=%p pp=%p enable-msr=%d", pc, pp,
+	    pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS);
+
+	/* allow the RDPMC instruction if needed */
+	if (pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS)
+		load_cr4(rcr4() | CR4_PCE);
+
+	PMCDBG(MDP,SWI,1, "cr4=0x%x", rcr4());
+
+	return (0);
+}
+
+static int
+ipm_switch_out(struct pmc_cpu *pc, struct pmc_process *pp)
+{
+	(void) pc;
+	(void) pp;		/* can be NULL */
+
+	PMCDBG(MDP,SWO,1, "pc=%p pp=%p cr4=0x%x", pc, pp, rcr4());
+
+	/* always turn off the RDPMC instruction */
+ 	load_cr4(rcr4() & ~CR4_PCE);
+
+	return (0);
+}
+
+static int
+ipm_read_pmc(int cpu, int ri, pmc_value_t *v)
+{
+	struct pmc_hw *phw;
+	struct pmc *pm;
+	const struct ipm_pmc_descr *pd;
+	pmc_value_t tmp;
+
+	phw = pmc_pcpu[cpu]->pc_hwpmcs[ri];
+	pm  = phw->phw_pmc;
+	pd  = &ipm_pmc_desc[ri];
+
+	KASSERT(pm,
+	    ("[ipm,%d] cpu %d ri %d pmc not configured", 
+	    __LINE__, cpu, ri));
+
+	if (pd->pm_descr.pd_class == PMC_CLASS_TSC) {
+		*v = rdtsc();
+		return (0);
+	}
+
+	tmp = rdmsr(pd->pm_pmc_msr) & IPM_PERFCTR_READ_MASK;
+	if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+		*v = IPM_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp);
+	else
+		*v = tmp;
+
+	PMCDBG(MDP,REA,1, "ipm-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri,
+	    pd->pm_pmc_msr, *v);
+
+	return (0);
+}
+
+static int
+ipm_write_pmc(int cpu, int ri, pmc_value_t v)
+{
+	struct pmc_hw *phw;
+	struct pmc *pm;
+	const struct ipm_pmc_descr *pd;
+	uint64_t ctrl_msr;
+
+	phw = pmc_pcpu[cpu]->pc_hwpmcs[ri];
+	pm  = phw->phw_pmc;
+	pd  = &ipm_pmc_desc[ri];
+
+	KASSERT(pm,
+	    ("[ipm,%d] cpu %d ri %d pmc not configured", 
+	    __LINE__, cpu, ri));
+
+	if (pd->pm_descr.pd_class == PMC_CLASS_TSC)
+		return (0);
+
+	PMCDBG(MDP,WRI,1, "ipm-write cpu=%d ri=%d msr=0x%x v=%jx", cpu, ri,
+	    pd->pm_pmc_msr, v);
+	
+	/*
+	 * Stop the PMC first
+	 */
+	switch (ipm_cputype) {
+	case PMC_CPU_INTEL_CORE:
+		wrmsr(pd->pm_evsel_msr, 
+		    pm->pm_md.pm_ipm.pm_ipm_evsel & (~IPM_EVSEL_EN));
+		break;
+
+	case PMC_CPU_INTEL_CORE2:
+		ctrl_msr = rdmsr(IPM_MSR_PERFCTR_CTRL);
+		ctrl_msr &= ~(ipm_v2_pmc_ri_to_msr_en_bit(ri));
+		wrmsr(IPM_MSR_PERFCTR_CTRL, ctrl_msr);
+		break;
+		
+	default:
+		break;
+	}
+
+	
+	if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+		v = IPM_RELOAD_COUNT_TO_PERFCTR_VALUE(v);
+	wrmsr(pd->pm_pmc_msr, v & IPM_PERFCTR_WRITE_MASK);
+	
+	/*
+	 * Start the PMC
+	 */
+	switch (ipm_cputype) {
+	case PMC_CPU_INTEL_CORE:
+		wrmsr(pd->pm_evsel_msr,
+		    pm->pm_md.pm_ipm.pm_ipm_evsel | IPM_EVSEL_EN);
+		break;
+
+	case PMC_CPU_INTEL_CORE2:
+		ctrl_msr = rdmsr(IPM_MSR_PERFCTR_CTRL);
+		ctrl_msr |= ipm_v2_pmc_ri_to_msr_en_bit(ri);
+		wrmsr(IPM_MSR_PERFCTR_CTRL, ctrl_msr);
+		break;
+
+	default:
+		break;
+	}
+
+	return (0);
+}
+
+static int
+ipm_config_pmc(int cpu, int ri, struct pmc *pm)
+{
+	struct pmc_hw *phw;
+
+	PMCDBG(MDP,CFG,1, "ipm-config cpu=%d ri=%d pm=%p", cpu, ri, pm);
+
+	phw = pmc_pcpu[cpu]->pc_hwpmcs[ri];
+	phw->phw_pmc = pm;
+
+	return (0);
+}
+
+/*
+ * Retrieve a configured PMC pointer from hardware state.
+ */
+static int
+ipm_get_config(int cpu, int ri, struct pmc **ppm)
+{
+	*ppm = pmc_pcpu[cpu]->pc_hwpmcs[ri]->phw_pmc;
+
+	return (0);
+}
+
+static int
+ipm_allocate_fixed_pmc(int cpu, int ri, uint32_t caps,
+    struct pmc *pm, const struct ipm_event_descr *pevent)
+{
+	uint32_t config, counter;
+
+	counter = ri - 3;
+	
+	/*
+	 * Event and fixed function counter has one to one mapping
+	 * and the event is only valid for the counter with same
+	 * index
+	 */
+	if ((pevent->pm_event == PMC_EV_IAF_INSTRUCTIONS_RETIRED &&
+	    counter == 0) ||
+	    (pevent->pm_event == PMC_EV_IAF_UNHALTED_CORE_CYCLES &&
+	    counter == 1) ||
+	    (pevent->pm_event == PMC_EV_IAF_UNHALTED_REFERENCE_CYCLES 
+	     && counter == 2)) {
+		config = 0;
+	} else {
+		return (EINVAL);
+	}
+
+	if (caps & PMC_CAP_SYSTEM)
+		config |= IPM_FIXEDCTR_PL_OS;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-user mailing list