xref: /onnv-gate/usr/src/uts/intel/pcbe/core_pcbe.c (revision 13070:87f89233b883)
16840Skk208521 /*
26840Skk208521  * CDDL HEADER START
36840Skk208521  *
46840Skk208521  * The contents of this file are subject to the terms of the
56840Skk208521  * Common Development and Distribution License (the "License").
66840Skk208521  * You may not use this file except in compliance with the License.
76840Skk208521  *
86840Skk208521  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96840Skk208521  * or http://www.opensolaris.org/os/licensing.
106840Skk208521  * See the License for the specific language governing permissions
116840Skk208521  * and limitations under the License.
126840Skk208521  *
136840Skk208521  * When distributing Covered Code, include this CDDL HEADER in each
146840Skk208521  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156840Skk208521  * If applicable, add the following below this CDDL HEADER, with the
166840Skk208521  * fields enclosed by brackets "[]" replaced with your own identifying
176840Skk208521  * information: Portions Copyright [yyyy] [name of copyright owner]
186840Skk208521  *
196840Skk208521  * CDDL HEADER END
206840Skk208521  */
216840Skk208521 /*
2212759SAdrian.Frost@Sun.COM  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
236840Skk208521  */
246840Skk208521 
256840Skk208521 /*
2611261SKuriakose.Kuruvilla@Sun.COM  * This file contains preset event names from the Performance Application
2711261SKuriakose.Kuruvilla@Sun.COM  * Programming Interface v3.5 which included the following notice:
2811261SKuriakose.Kuruvilla@Sun.COM  *
2911261SKuriakose.Kuruvilla@Sun.COM  *                             Copyright (c) 2005,6
3011261SKuriakose.Kuruvilla@Sun.COM  *                           Innovative Computing Labs
3111261SKuriakose.Kuruvilla@Sun.COM  *                         Computer Science Department,
3211261SKuriakose.Kuruvilla@Sun.COM  *                            University of Tennessee,
3311261SKuriakose.Kuruvilla@Sun.COM  *                                 Knoxville, TN.
3411261SKuriakose.Kuruvilla@Sun.COM  *                              All Rights Reserved.
3511261SKuriakose.Kuruvilla@Sun.COM  *
3611261SKuriakose.Kuruvilla@Sun.COM  *
3711261SKuriakose.Kuruvilla@Sun.COM  * Redistribution and use in source and binary forms, with or without
3811261SKuriakose.Kuruvilla@Sun.COM  * modification, are permitted provided that the following conditions are met:
3911261SKuriakose.Kuruvilla@Sun.COM  *
4011261SKuriakose.Kuruvilla@Sun.COM  *    * Redistributions of source code must retain the above copyright notice,
4111261SKuriakose.Kuruvilla@Sun.COM  *      this list of conditions and the following disclaimer.
4211261SKuriakose.Kuruvilla@Sun.COM  *    * Redistributions in binary form must reproduce the above copyright
4311261SKuriakose.Kuruvilla@Sun.COM  *      notice, this list of conditions and the following disclaimer in the
4411261SKuriakose.Kuruvilla@Sun.COM  *      documentation and/or other materials provided with the distribution.
4511261SKuriakose.Kuruvilla@Sun.COM  *    * Neither the name of the University of Tennessee nor the names of its
4611261SKuriakose.Kuruvilla@Sun.COM  *      contributors may be used to endorse or promote products derived from
4711261SKuriakose.Kuruvilla@Sun.COM  *      this software without specific prior written permission.
4811261SKuriakose.Kuruvilla@Sun.COM  *
4911261SKuriakose.Kuruvilla@Sun.COM  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
5011261SKuriakose.Kuruvilla@Sun.COM  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5111261SKuriakose.Kuruvilla@Sun.COM  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5211261SKuriakose.Kuruvilla@Sun.COM  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
5311261SKuriakose.Kuruvilla@Sun.COM  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5411261SKuriakose.Kuruvilla@Sun.COM  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5511261SKuriakose.Kuruvilla@Sun.COM  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
5611261SKuriakose.Kuruvilla@Sun.COM  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
5711261SKuriakose.Kuruvilla@Sun.COM  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5811261SKuriakose.Kuruvilla@Sun.COM  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
5911261SKuriakose.Kuruvilla@Sun.COM  * POSSIBILITY OF SUCH DAMAGE.
6011261SKuriakose.Kuruvilla@Sun.COM  *
6111261SKuriakose.Kuruvilla@Sun.COM  *
6211261SKuriakose.Kuruvilla@Sun.COM  * This open source software license conforms to the BSD License template.
6311261SKuriakose.Kuruvilla@Sun.COM  */
6411261SKuriakose.Kuruvilla@Sun.COM 
6511261SKuriakose.Kuruvilla@Sun.COM 
6611261SKuriakose.Kuruvilla@Sun.COM /*
678720SKuriakose.Kuruvilla@Sun.COM  * Performance Counter Back-End for Intel processors supporting Architectural
688720SKuriakose.Kuruvilla@Sun.COM  * Performance Monitoring.
696840Skk208521  */
706840Skk208521 
716840Skk208521 #include <sys/cpuvar.h>
726840Skk208521 #include <sys/param.h>
736840Skk208521 #include <sys/cpc_impl.h>
746840Skk208521 #include <sys/cpc_pcbe.h>
756840Skk208521 #include <sys/modctl.h>
766840Skk208521 #include <sys/inttypes.h>
776840Skk208521 #include <sys/systm.h>
786840Skk208521 #include <sys/cmn_err.h>
796840Skk208521 #include <sys/x86_archext.h>
806840Skk208521 #include <sys/sdt.h>
816840Skk208521 #include <sys/archsystm.h>
826840Skk208521 #include <sys/privregs.h>
836840Skk208521 #include <sys/ddi.h>
846840Skk208521 #include <sys/sunddi.h>
856840Skk208521 #include <sys/cred.h>
866840Skk208521 #include <sys/policy.h>
876840Skk208521 
886840Skk208521 static int core_pcbe_init(void);
896840Skk208521 static uint_t core_pcbe_ncounters(void);
906840Skk208521 static const char *core_pcbe_impl_name(void);
916840Skk208521 static const char *core_pcbe_cpuref(void);
926840Skk208521 static char *core_pcbe_list_events(uint_t picnum);
936840Skk208521 static char *core_pcbe_list_attrs(void);
946840Skk208521 static uint64_t core_pcbe_event_coverage(char *event);
956840Skk208521 static uint64_t core_pcbe_overflow_bitmap(void);
966840Skk208521 static int core_pcbe_configure(uint_t picnum, char *event, uint64_t preset,
976840Skk208521     uint32_t flags, uint_t nattrs, kcpc_attr_t *attrs, void **data,
986840Skk208521     void *token);
996840Skk208521 static void core_pcbe_program(void *token);
1006840Skk208521 static void core_pcbe_allstop(void);
1016840Skk208521 static void core_pcbe_sample(void *token);
1026840Skk208521 static void core_pcbe_free(void *config);
1036840Skk208521 
1046840Skk208521 #define	FALSE	0
1056840Skk208521 #define	TRUE	1
1066840Skk208521 
1076840Skk208521 /* Counter Type */
1086840Skk208521 #define	CORE_GPC	0	/* General-Purpose Counter (GPC) */
1096840Skk208521 #define	CORE_FFC	1	/* Fixed-Function Counter (FFC) */
1106840Skk208521 
1116840Skk208521 /* MSR Addresses */
1126840Skk208521 #define	GPC_BASE_PMC		0x00c1	/* First GPC */
1136840Skk208521 #define	GPC_BASE_PES		0x0186	/* First GPC Event Select register */
1146840Skk208521 #define	FFC_BASE_PMC		0x0309	/* First FFC */
1156840Skk208521 #define	PERF_FIXED_CTR_CTRL	0x038d	/* Used to enable/disable FFCs */
1166840Skk208521 #define	PERF_GLOBAL_STATUS	0x038e	/* Overflow status register */
1176840Skk208521 #define	PERF_GLOBAL_CTRL	0x038f	/* Used to enable/disable counting */
1186840Skk208521 #define	PERF_GLOBAL_OVF_CTRL	0x0390	/* Used to clear overflow status */
1196840Skk208521 
1206840Skk208521 /*
1216840Skk208521  * Processor Event Select register fields
1226840Skk208521  */
1236840Skk208521 #define	CORE_USR	(1ULL << 16)	/* Count while not in ring 0 */
1246840Skk208521 #define	CORE_OS		(1ULL << 17)	/* Count while in ring 0 */
1256840Skk208521 #define	CORE_EDGE	(1ULL << 18)	/* Enable edge detection */
1266840Skk208521 #define	CORE_PC		(1ULL << 19)	/* Enable pin control */
1276840Skk208521 #define	CORE_INT	(1ULL << 20)	/* Enable interrupt on overflow */
1286840Skk208521 #define	CORE_EN		(1ULL << 22)	/* Enable counting */
1296840Skk208521 #define	CORE_INV	(1ULL << 23)	/* Invert the CMASK */
1307728SKuriakose.Kuruvilla@Sun.COM #define	CORE_ANYTHR	(1ULL << 21)	/* Count event for any thread on core */
1316840Skk208521 
1326840Skk208521 #define	CORE_UMASK_SHIFT	8
1336840Skk208521 #define	CORE_UMASK_MASK		0xffu
1346840Skk208521 #define	CORE_CMASK_SHIFT	24
1356840Skk208521 #define	CORE_CMASK_MASK		0xffu
1366840Skk208521 
1376840Skk208521 /*
1386840Skk208521  * Fixed-function counter attributes
1396840Skk208521  */
1406840Skk208521 #define	CORE_FFC_OS_EN	(1ULL << 0)	/* Count while not in ring 0 */
1416840Skk208521 #define	CORE_FFC_USR_EN	(1ULL << 1)	/* Count while in ring 1 */
1427728SKuriakose.Kuruvilla@Sun.COM #define	CORE_FFC_ANYTHR	(1ULL << 2)	/* Count event for any thread on core */
1436840Skk208521 #define	CORE_FFC_PMI	(1ULL << 3)	/* Enable interrupt on overflow */
1446840Skk208521 
1456840Skk208521 /*
1466840Skk208521  * Number of bits for specifying each FFC's attributes in the control register
1476840Skk208521  */
1486840Skk208521 #define	CORE_FFC_ATTR_SIZE	4
1496840Skk208521 
1506840Skk208521 /*
1516840Skk208521  * CondChgd and OvfBuffer fields of global status and overflow control registers
1526840Skk208521  */
1536840Skk208521 #define	CONDCHGD	(1ULL << 63)
1546840Skk208521 #define	OVFBUFFER	(1ULL << 62)
1556840Skk208521 #define	MASK_CONDCHGD_OVFBUFFER	(CONDCHGD | OVFBUFFER)
1566840Skk208521 
1576840Skk208521 #define	ALL_STOPPED	0ULL
1586840Skk208521 
1596840Skk208521 #define	BITMASK_XBITS(x)	((1ull << (x)) - 1ull)
1606840Skk208521 
1616840Skk208521 /*
1626840Skk208521  * Only the lower 32-bits can be written to in the general-purpose
1636840Skk208521  * counters.  The higher bits are extended from bit 31; all ones if
1646840Skk208521  * bit 31 is one and all zeros otherwise.
1656840Skk208521  *
1666840Skk208521  * The fixed-function counters do not have this restriction.
1676840Skk208521  */
1686840Skk208521 #define	BITS_EXTENDED_FROM_31	(BITMASK_XBITS(width_gpc) & ~BITMASK_XBITS(31))
1696840Skk208521 
1706840Skk208521 #define	WRMSR(msr, value)						\
1716840Skk208521 	wrmsr((msr), (value));						\
1726840Skk208521 	DTRACE_PROBE2(wrmsr, uint64_t, (msr), uint64_t, (value));
1736840Skk208521 
1746840Skk208521 #define	RDMSR(msr, value)						\
1756840Skk208521 	(value) = rdmsr((msr));						\
1766840Skk208521 	DTRACE_PROBE2(rdmsr, uint64_t, (msr), uint64_t, (value));
1776840Skk208521 
1786840Skk208521 typedef struct core_pcbe_config {
1796840Skk208521 	uint64_t	core_rawpic;
1806840Skk208521 	uint64_t	core_ctl;	/* Event Select bits */
1816840Skk208521 	uint64_t	core_pmc;	/* Counter register address */
1826840Skk208521 	uint64_t	core_pes;	/* Event Select register address */
1836840Skk208521 	uint_t		core_picno;
1846840Skk208521 	uint8_t		core_pictype;	/* CORE_GPC or CORE_FFC */
1856840Skk208521 } core_pcbe_config_t;
1866840Skk208521 
1876840Skk208521 pcbe_ops_t core_pcbe_ops = {
1886840Skk208521 	PCBE_VER_1,			/* pcbe_ver */
1896840Skk208521 	CPC_CAP_OVERFLOW_INTERRUPT | CPC_CAP_OVERFLOW_PRECISE,	/* pcbe_caps */
1906840Skk208521 	core_pcbe_ncounters,		/* pcbe_ncounters */
1916840Skk208521 	core_pcbe_impl_name,		/* pcbe_impl_name */
1926840Skk208521 	core_pcbe_cpuref,		/* pcbe_cpuref */
1936840Skk208521 	core_pcbe_list_events,		/* pcbe_list_events */
1946840Skk208521 	core_pcbe_list_attrs,		/* pcbe_list_attrs */
1956840Skk208521 	core_pcbe_event_coverage,	/* pcbe_event_coverage */
1966840Skk208521 	core_pcbe_overflow_bitmap,	/* pcbe_overflow_bitmap */
1976840Skk208521 	core_pcbe_configure,		/* pcbe_configure */
1986840Skk208521 	core_pcbe_program,		/* pcbe_program */
1996840Skk208521 	core_pcbe_allstop,		/* pcbe_allstop */
2006840Skk208521 	core_pcbe_sample,		/* pcbe_sample */
2016840Skk208521 	core_pcbe_free			/* pcbe_free */
2026840Skk208521 };
2036840Skk208521 
2048720SKuriakose.Kuruvilla@Sun.COM struct nametable_core_uarch {
2056840Skk208521 	const char	*name;
2066840Skk208521 	uint64_t	restricted_bits;
2076840Skk208521 	uint8_t		event_num;
2086840Skk208521 };
2096840Skk208521 
2106840Skk208521 #define	NT_END	0xFF
2116840Skk208521 
2126840Skk208521 /*
2136840Skk208521  * Counting an event for all cores or all bus agents requires cpc_cpu privileges
2146840Skk208521  */
2156840Skk208521 #define	ALL_CORES	(1ULL << 15)
2166840Skk208521 #define	ALL_AGENTS	(1ULL << 13)
2176840Skk208521 
21811261SKuriakose.Kuruvilla@Sun.COM struct generic_events {
21911261SKuriakose.Kuruvilla@Sun.COM 	const char	*name;
22011261SKuriakose.Kuruvilla@Sun.COM 	uint8_t		event_num;
22111261SKuriakose.Kuruvilla@Sun.COM 	uint8_t		umask;
22211261SKuriakose.Kuruvilla@Sun.COM };
22311261SKuriakose.Kuruvilla@Sun.COM 
22411261SKuriakose.Kuruvilla@Sun.COM static const struct generic_events cmn_generic_events[] = {
22511261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_tot_cyc", 0x3c, 0x00 }, /* cpu_clk_unhalted.thread_p/core */
22611261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_tot_ins", 0xc0, 0x00 }, /* inst_retired.any_p		  */
22711261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_br_ins",  0xc4, 0x0c }, /* br_inst_retired.taken	  */
22811261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_br_msp",  0xc5, 0x00 }, /* br_inst_retired.mispred	  */
22911261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_br_ntk",  0xc4, 0x03 },
23011261SKuriakose.Kuruvilla@Sun.COM 				/* br_inst_retired.pred_not_taken|pred_taken */
23111261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_br_prc",  0xc4, 0x05 },
23211261SKuriakose.Kuruvilla@Sun.COM 				/* br_inst_retired.pred_not_taken|pred_taken */
23311261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_hw_int",  0xc8, 0x00 }, /* hw_int_rvc			  */
23411261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_tot_iis", 0xaa, 0x01 }, /* macro_insts.decoded		  */
23511261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_l1_dca",  0x43, 0x01 }, /* l1d_all_ref			  */
23611261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_l1_icm",  0x81, 0x00 }, /* l1i_misses			  */
23711261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_l1_icr",  0x80, 0x00 }, /* l1i_reads			  */
23811261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_l1_tcw",  0x41, 0x0f }, /* l1d_cache_st.mesi		  */
23911261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_l2_stm",  0x2a, 0x41 }, /* l2_st.self.i_state		  */
24011261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_l2_tca",  0x2e, 0x4f }, /* l2_rqsts.self.demand.mesi	  */
24111261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_l2_tch",  0x2e, 0x4e }, /* l2_rqsts.mes			  */
24211261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_l2_tcm",  0x2e, 0x41 }, /* l2_rqsts.self.demand.i_state   */
24311261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_l2_tcw",  0x2a, 0x4f }, /* l2_st.self.mesi		  */
24411261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_ld_ins",  0xc0, 0x01 }, /* inst_retired.loads		  */
24511261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_lst_ins", 0xc0, 0x03 }, /* inst_retired.loads|stores	  */
24611261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_sr_ins",  0xc0, 0x02 }, /* inst_retired.stores		  */
24711261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_tlb_dm",  0x08, 0x01 }, /* dtlb_misses.any		  */
24811261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_tlb_im",  0x82, 0x12 }, /* itlb.small_miss|large_miss	  */
24911261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_tlb_tl",  0x0c, 0x03 }, /* page_walks			  */
25011261SKuriakose.Kuruvilla@Sun.COM 	{ "",		  NT_END, 0  }
25111261SKuriakose.Kuruvilla@Sun.COM };
25211261SKuriakose.Kuruvilla@Sun.COM 
25311261SKuriakose.Kuruvilla@Sun.COM static const struct generic_events generic_events_pic0[] = {
25411261SKuriakose.Kuruvilla@Sun.COM 	{ "PAPI_l1_dcm",  0xcb, 0x01 }, /* mem_load_retired.l1d_miss */
25511261SKuriakose.Kuruvilla@Sun.COM 	{ "",		  NT_END, 0  }
25611261SKuriakose.Kuruvilla@Sun.COM };
25711261SKuriakose.Kuruvilla@Sun.COM 
2587728SKuriakose.Kuruvilla@Sun.COM /*
2597728SKuriakose.Kuruvilla@Sun.COM  * The events listed in the following table can be counted on all
2608720SKuriakose.Kuruvilla@Sun.COM  * general-purpose counters on processors that are of Penryn and Merom Family
2617728SKuriakose.Kuruvilla@Sun.COM  */
2628720SKuriakose.Kuruvilla@Sun.COM static const struct nametable_core_uarch cmn_gpc_events_core_uarch[] = {
2636840Skk208521 	/* Alphabetical order of event name */
2646840Skk208521 
2656840Skk208521 	{ "baclears",			0x0,	0xe6 },
2666840Skk208521 	{ "bogus_br",			0x0,	0xe4 },
2676840Skk208521 	{ "br_bac_missp_exec",		0x0,	0x8a },
2686840Skk208521 
2696840Skk208521 	{ "br_call_exec",		0x0,	0x92 },
2706840Skk208521 	{ "br_call_missp_exec",		0x0,	0x93 },
2716840Skk208521 	{ "br_cnd_exec",		0x0,	0x8b },
2726840Skk208521 
2736840Skk208521 	{ "br_cnd_missp_exec",		0x0,	0x8c },
2746840Skk208521 	{ "br_ind_call_exec",		0x0,	0x94 },
2756840Skk208521 	{ "br_ind_exec",		0x0,	0x8d },
2766840Skk208521 
2776840Skk208521 	{ "br_ind_missp_exec",		0x0,	0x8e },
2786840Skk208521 	{ "br_inst_decoded",		0x0,	0xe0 },
2796840Skk208521 	{ "br_inst_exec",		0x0,	0x88 },
2806840Skk208521 
2816840Skk208521 	{ "br_inst_retired",		0x0,	0xc4 },
2826840Skk208521 	{ "br_inst_retired_mispred",	0x0,	0xc5 },
2836840Skk208521 	{ "br_missp_exec",		0x0,	0x89 },
2846840Skk208521 
2856840Skk208521 	{ "br_ret_bac_missp_exec",	0x0,	0x91 },
2866840Skk208521 	{ "br_ret_exec",		0x0,	0x8f },
2876840Skk208521 	{ "br_ret_missp_exec",		0x0,	0x90 },
2886840Skk208521 
2896840Skk208521 	{ "br_tkn_bubble_1",		0x0,	0x97 },
2906840Skk208521 	{ "br_tkn_bubble_2",		0x0,	0x98 },
2916840Skk208521 	{ "bus_bnr_drv",		ALL_AGENTS,	0x61 },
2926840Skk208521 
2936840Skk208521 	{ "bus_data_rcv",		ALL_CORES,	0x64 },
2946840Skk208521 	{ "bus_drdy_clocks",		ALL_AGENTS,	0x62 },
2956840Skk208521 	{ "bus_hit_drv",		ALL_AGENTS,	0x7a },
2966840Skk208521 
2976840Skk208521 	{ "bus_hitm_drv",		ALL_AGENTS,	0x7b },
2986840Skk208521 	{ "bus_io_wait",		ALL_CORES,	0x7f },
2996840Skk208521 	{ "bus_lock_clocks",		ALL_CORES | ALL_AGENTS,	0x63 },
3006840Skk208521 
3016840Skk208521 	{ "bus_request_outstanding",	ALL_CORES | ALL_AGENTS,	0x60 },
3026840Skk208521 	{ "bus_trans_any",		ALL_CORES | ALL_AGENTS,	0x70 },
3036840Skk208521 	{ "bus_trans_brd",		ALL_CORES | ALL_AGENTS,	0x65 },
3046840Skk208521 
3056840Skk208521 	{ "bus_trans_burst",		ALL_CORES | ALL_AGENTS,	0x6e },
3066840Skk208521 	{ "bus_trans_def",		ALL_CORES | ALL_AGENTS,	0x6d },
3076840Skk208521 	{ "bus_trans_ifetch",		ALL_CORES | ALL_AGENTS,	0x68 },
3086840Skk208521 
3096840Skk208521 	{ "bus_trans_inval",		ALL_CORES | ALL_AGENTS,	0x69 },
3106840Skk208521 	{ "bus_trans_io",		ALL_CORES | ALL_AGENTS,	0x6c },
3116840Skk208521 	{ "bus_trans_mem",		ALL_CORES | ALL_AGENTS,	0x6f },
3126840Skk208521 
3136840Skk208521 	{ "bus_trans_p",		ALL_CORES | ALL_AGENTS,	0x6b },
3146840Skk208521 	{ "bus_trans_pwr",		ALL_CORES | ALL_AGENTS,	0x6a },
3156840Skk208521 	{ "bus_trans_rfo",		ALL_CORES | ALL_AGENTS,	0x66 },
3166840Skk208521 
3176840Skk208521 	{ "bus_trans_wb",		ALL_CORES | ALL_AGENTS,	0x67 },
3186840Skk208521 	{ "busq_empty",			ALL_CORES,	0x7d },
3196840Skk208521 	{ "cmp_snoop",			ALL_CORES,	0x78 },
3206840Skk208521 
3216840Skk208521 	{ "cpu_clk_unhalted",		0x0,	0x3c },
3226840Skk208521 	{ "cycles_int",			0x0,	0xc6 },
3236840Skk208521 	{ "cycles_l1i_mem_stalled",	0x0,	0x86 },
3246840Skk208521 
3256840Skk208521 	{ "dtlb_misses",		0x0,	0x08 },
3266840Skk208521 	{ "eist_trans",			0x0,	0x3a },
3276840Skk208521 	{ "esp",			0x0,	0xab },
3286840Skk208521 
3296840Skk208521 	{ "ext_snoop",			ALL_AGENTS,	0x77 },
3306840Skk208521 	{ "fp_mmx_trans",		0x0,	0xcc },
3316840Skk208521 	{ "hw_int_rcv",			0x0,	0xc8 },
3326840Skk208521 
3336840Skk208521 	{ "ild_stall",			0x0,	0x87 },
3346840Skk208521 	{ "inst_queue",			0x0,	0x83 },
3356840Skk208521 	{ "inst_retired",		0x0,	0xc0 },
3366840Skk208521 
3376840Skk208521 	{ "itlb",			0x0,	0x82 },
3386840Skk208521 	{ "itlb_miss_retired",		0x0,	0xc9 },
3396840Skk208521 	{ "l1d_all_ref",		0x0,	0x43 },
3406840Skk208521 
3416840Skk208521 	{ "l1d_cache_ld",		0x0,	0x40 },
3426840Skk208521 	{ "l1d_cache_lock",		0x0,	0x42 },
3436840Skk208521 	{ "l1d_cache_st",		0x0,	0x41 },
3446840Skk208521 
3456840Skk208521 	{ "l1d_m_evict",		0x0,	0x47 },
3466840Skk208521 	{ "l1d_m_repl",			0x0,	0x46 },
3476840Skk208521 	{ "l1d_pend_miss",		0x0,	0x48 },
3486840Skk208521 
3496840Skk208521 	{ "l1d_prefetch",		0x0,	0x4e },
3506840Skk208521 	{ "l1d_repl",			0x0,	0x45 },
3516840Skk208521 	{ "l1d_split",			0x0,	0x49 },
3526840Skk208521 
3536840Skk208521 	{ "l1i_misses",			0x0,	0x81 },
3546840Skk208521 	{ "l1i_reads",			0x0,	0x80 },
3556840Skk208521 	{ "l2_ads",			ALL_CORES,	0x21 },
3566840Skk208521 
3576840Skk208521 	{ "l2_dbus_busy_rd",		ALL_CORES,	0x23 },
3586840Skk208521 	{ "l2_ifetch",			ALL_CORES,	0x28 },
3596840Skk208521 	{ "l2_ld",			ALL_CORES,	0x29 },
3606840Skk208521 
3616840Skk208521 	{ "l2_lines_in",		ALL_CORES,	0x24 },
3626840Skk208521 	{ "l2_lines_out",		ALL_CORES,	0x26 },
3636840Skk208521 	{ "l2_lock",			ALL_CORES,	0x2b },
3646840Skk208521 
3656840Skk208521 	{ "l2_m_lines_in",		ALL_CORES,	0x25 },
3666840Skk208521 	{ "l2_m_lines_out",		ALL_CORES,	0x27 },
3676840Skk208521 	{ "l2_no_req",			ALL_CORES,	0x32 },
3686840Skk208521 
3696840Skk208521 	{ "l2_reject_busq",		ALL_CORES,	0x30 },
3706840Skk208521 	{ "l2_rqsts",			ALL_CORES,	0x2e },
3716840Skk208521 	{ "l2_st",			ALL_CORES,	0x2a },
3726840Skk208521 
3736840Skk208521 	{ "load_block",			0x0,	0x03 },
3746840Skk208521 	{ "load_hit_pre",		0x0,	0x4c },
3756840Skk208521 	{ "machine_nukes",		0x0,	0xc3 },
3766840Skk208521 
3776840Skk208521 	{ "macro_insts",		0x0,	0xaa },
3786840Skk208521 	{ "memory_disambiguation",	0x0,	0x09 },
3797728SKuriakose.Kuruvilla@Sun.COM 	{ "misalign_mem_ref",		0x0,	0x05 },
3806840Skk208521 	{ "page_walks",			0x0,	0x0c },
3816840Skk208521 
3826840Skk208521 	{ "pref_rqsts_dn",		0x0,	0xf8 },
3836840Skk208521 	{ "pref_rqsts_up",		0x0,	0xf0 },
3846840Skk208521 	{ "rat_stalls",			0x0,	0xd2 },
3856840Skk208521 
3866840Skk208521 	{ "resource_stalls",		0x0,	0xdc },
3876840Skk208521 	{ "rs_uops_dispatched",		0x0,	0xa0 },
3886840Skk208521 	{ "seg_reg_renames",		0x0,	0xd5 },
3896840Skk208521 
3906840Skk208521 	{ "seg_rename_stalls",		0x0,	0xd4 },
3916840Skk208521 	{ "segment_reg_loads",		0x0,	0x06 },
3926840Skk208521 	{ "simd_assist",		0x0,	0xcd },
3936840Skk208521 
3946840Skk208521 	{ "simd_comp_inst_retired",	0x0,	0xca },
3956840Skk208521 	{ "simd_inst_retired",		0x0,	0xc7 },
3966840Skk208521 	{ "simd_instr_retired",		0x0,	0xce },
3976840Skk208521 
3986840Skk208521 	{ "simd_sat_instr_retired",	0x0,	0xcf },
3996840Skk208521 	{ "simd_sat_uop_exec",		0x0,	0xb1 },
4006840Skk208521 	{ "simd_uop_type_exec",		0x0,	0xb3 },
4016840Skk208521 
4026840Skk208521 	{ "simd_uops_exec",		0x0,	0xb0 },
4036840Skk208521 	{ "snoop_stall_drv",		ALL_CORES | ALL_AGENTS,	0x7e },
4046840Skk208521 	{ "sse_pre_exec",		0x0,	0x07 },
4056840Skk208521 
4066840Skk208521 	{ "sse_pre_miss",		0x0,	0x4b },
4076840Skk208521 	{ "store_block",		0x0,	0x04 },
4086840Skk208521 	{ "thermal_trip",		0x0,	0x3b },
4096840Skk208521 
4106840Skk208521 	{ "uops_retired",		0x0,	0xc2 },
4116840Skk208521 	{ "x87_ops_retired",		0x0,	0xc1 },
4126840Skk208521 	{ "",				0x0,	NT_END }
4136840Skk208521 };
4146840Skk208521 
4156840Skk208521 /*
4166840Skk208521  * If any of the pic specific events require privileges, make sure to add a
4176840Skk208521  * check in configure_gpc() to find whether an event hard-coded as a number by
4186840Skk208521  * the user has any privilege requirements
4196840Skk208521  */
4208720SKuriakose.Kuruvilla@Sun.COM static const struct nametable_core_uarch pic0_events[] = {
4216840Skk208521 	/* Alphabetical order of event name */
4226840Skk208521 
4236840Skk208521 	{ "cycles_div_busy",		0x0,	0x14 },
4246840Skk208521 	{ "fp_comp_ops_exe",		0x0,	0x10 },
4256840Skk208521 	{ "idle_during_div",		0x0,	0x18 },
4266840Skk208521 
4276840Skk208521 	{ "mem_load_retired",		0x0,	0xcb },
4286840Skk208521 	{ "rs_uops_dispatched_port",	0x0,	0xa1 },
4296840Skk208521 	{ "",				0x0,	NT_END }
4306840Skk208521 };
4316840Skk208521 
4328720SKuriakose.Kuruvilla@Sun.COM static const struct nametable_core_uarch pic1_events[] = {
4336840Skk208521 	/* Alphabetical order of event name */
4346840Skk208521 
4356840Skk208521 	{ "delayed_bypass",	0x0,	0x19 },
4366840Skk208521 	{ "div",		0x0,	0x13 },
4376840Skk208521 	{ "fp_assist",		0x0,	0x11 },
4386840Skk208521 
4396840Skk208521 	{ "mul",		0x0,	0x12 },
4406840Skk208521 	{ "",			0x0,	NT_END }
4416840Skk208521 };
4426840Skk208521 
4438146SKrishnendu.Sadhukhan@Sun.COM /* FFC entries must be in order */
44411261SKuriakose.Kuruvilla@Sun.COM static char *ffc_names_non_htt[] = {
4458146SKrishnendu.Sadhukhan@Sun.COM 	"instr_retired.any",
4468146SKrishnendu.Sadhukhan@Sun.COM 	"cpu_clk_unhalted.core",
4478146SKrishnendu.Sadhukhan@Sun.COM 	"cpu_clk_unhalted.ref",
4488146SKrishnendu.Sadhukhan@Sun.COM 	NULL
4498146SKrishnendu.Sadhukhan@Sun.COM };
4508146SKrishnendu.Sadhukhan@Sun.COM 
45111261SKuriakose.Kuruvilla@Sun.COM static char *ffc_names_htt[] = {
4528146SKrishnendu.Sadhukhan@Sun.COM 	"instr_retired.any",
4537728SKuriakose.Kuruvilla@Sun.COM 	"cpu_clk_unhalted.thread",
4546840Skk208521 	"cpu_clk_unhalted.ref",
4556840Skk208521 	NULL
4566840Skk208521 };
4576840Skk208521 
45811261SKuriakose.Kuruvilla@Sun.COM static char *ffc_genericnames[] = {
45911261SKuriakose.Kuruvilla@Sun.COM 	"PAPI_tot_ins",
46011261SKuriakose.Kuruvilla@Sun.COM 	"PAPI_tot_cyc",
46111261SKuriakose.Kuruvilla@Sun.COM 	"",
46211261SKuriakose.Kuruvilla@Sun.COM 	NULL
46311261SKuriakose.Kuruvilla@Sun.COM };
4648146SKrishnendu.Sadhukhan@Sun.COM 
46511261SKuriakose.Kuruvilla@Sun.COM static char	**ffc_names = NULL;
46611261SKuriakose.Kuruvilla@Sun.COM static char	**ffc_allnames = NULL;
4678425SKrishnendu.Sadhukhan@Sun.COM static char	**gpc_names = NULL;
4687728SKuriakose.Kuruvilla@Sun.COM static uint32_t	versionid;
4696840Skk208521 static uint64_t	num_gpc;
4706840Skk208521 static uint64_t	width_gpc;
4716840Skk208521 static uint64_t	mask_gpc;
4726840Skk208521 static uint64_t	num_ffc;
4736840Skk208521 static uint64_t	width_ffc;
4746840Skk208521 static uint64_t	mask_ffc;
4756840Skk208521 static uint_t	total_pmc;
4766840Skk208521 static uint64_t	control_ffc;
4776840Skk208521 static uint64_t	control_gpc;
4786840Skk208521 static uint64_t	control_mask;
4797728SKuriakose.Kuruvilla@Sun.COM static uint32_t	arch_events_vector;
4806840Skk208521 
4817728SKuriakose.Kuruvilla@Sun.COM #define	IMPL_NAME_LEN 100
4827728SKuriakose.Kuruvilla@Sun.COM static char core_impl_name[IMPL_NAME_LEN];
4836840Skk208521 
4846840Skk208521 static const char *core_cpuref =
4856840Skk208521 	"See Appendix A of the \"Intel 64 and IA-32 Architectures Software" \
4866840Skk208521 	" Developer's Manual Volume 3B: System Programming Guide, Part 2\"" \
4876840Skk208521 	" Order Number: 253669-026US, Februrary 2008";
4886840Skk208521 
4897728SKuriakose.Kuruvilla@Sun.COM struct events_table_t {
4907728SKuriakose.Kuruvilla@Sun.COM 	uint8_t		eventselect;
4917728SKuriakose.Kuruvilla@Sun.COM 	uint8_t		unitmask;
4927728SKuriakose.Kuruvilla@Sun.COM 	uint64_t	supported_counters;
4937728SKuriakose.Kuruvilla@Sun.COM 	const char	*name;
4947728SKuriakose.Kuruvilla@Sun.COM };
4957728SKuriakose.Kuruvilla@Sun.COM 
4967728SKuriakose.Kuruvilla@Sun.COM /* Used to describe which counters support an event */
4977728SKuriakose.Kuruvilla@Sun.COM #define	C(x) (1 << (x))
4987728SKuriakose.Kuruvilla@Sun.COM #define	C0 C(0)
4997728SKuriakose.Kuruvilla@Sun.COM #define	C1 C(1)
5007728SKuriakose.Kuruvilla@Sun.COM #define	C2 C(2)
5017728SKuriakose.Kuruvilla@Sun.COM #define	C3 C(3)
5027728SKuriakose.Kuruvilla@Sun.COM #define	C_ALL 0xFFFFFFFFFFFFFFFF
5037728SKuriakose.Kuruvilla@Sun.COM 
5048146SKrishnendu.Sadhukhan@Sun.COM /* Architectural events */
5058146SKrishnendu.Sadhukhan@Sun.COM #define	ARCH_EVENTS_COMMON					\
5068146SKrishnendu.Sadhukhan@Sun.COM 	{ 0xc0, 0x00, C_ALL, "inst_retired.any_p" },		\
5078146SKrishnendu.Sadhukhan@Sun.COM 	{ 0x3c, 0x01, C_ALL, "cpu_clk_unhalted.ref_p" },	\
5088146SKrishnendu.Sadhukhan@Sun.COM 	{ 0x2e, 0x4f, C_ALL, "longest_lat_cache.reference" },	\
5098146SKrishnendu.Sadhukhan@Sun.COM 	{ 0x2e, 0x41, C_ALL, "longest_lat_cache.miss" },	\
5108146SKrishnendu.Sadhukhan@Sun.COM 	{ 0xc4, 0x00, C_ALL, "br_inst_retired.all_branches" },	\
5118146SKrishnendu.Sadhukhan@Sun.COM 	{ 0xc5, 0x00, C_ALL, "br_misp_retired.all_branches" }
5127728SKuriakose.Kuruvilla@Sun.COM 
51311261SKuriakose.Kuruvilla@Sun.COM static const struct events_table_t arch_events_table_non_htt[] = {
5148146SKrishnendu.Sadhukhan@Sun.COM 	{ 0x3c, 0x00, C_ALL, "cpu_clk_unhalted.core" },
5158146SKrishnendu.Sadhukhan@Sun.COM 	ARCH_EVENTS_COMMON
5167728SKuriakose.Kuruvilla@Sun.COM };
5177728SKuriakose.Kuruvilla@Sun.COM 
51811261SKuriakose.Kuruvilla@Sun.COM static const struct events_table_t arch_events_table_htt[] = {
5198146SKrishnendu.Sadhukhan@Sun.COM 	{ 0x3c, 0x00, C_ALL, "cpu_clk_unhalted.thread_p" },
5208146SKrishnendu.Sadhukhan@Sun.COM 	ARCH_EVENTS_COMMON
5218146SKrishnendu.Sadhukhan@Sun.COM };
5228146SKrishnendu.Sadhukhan@Sun.COM 
52311261SKuriakose.Kuruvilla@Sun.COM static char *arch_genevents_table[] = {
52411261SKuriakose.Kuruvilla@Sun.COM 	"PAPI_tot_cyc", /* cpu_clk_unhalted.thread_p/core */
52511261SKuriakose.Kuruvilla@Sun.COM 	"PAPI_tot_ins", /* inst_retired.any_p		  */
52611261SKuriakose.Kuruvilla@Sun.COM 	"",		/* cpu_clk_unhalted.ref_p	  */
52711261SKuriakose.Kuruvilla@Sun.COM 	"",		/* longest_lat_cache.reference	  */
52811261SKuriakose.Kuruvilla@Sun.COM 	"",		/* longest_lat_cache.miss	  */
52911261SKuriakose.Kuruvilla@Sun.COM 	"",		/* br_inst_retired.all_branches	  */
53011261SKuriakose.Kuruvilla@Sun.COM 	"",		/* br_misp_retired.all_branches	  */
53111261SKuriakose.Kuruvilla@Sun.COM };
53211261SKuriakose.Kuruvilla@Sun.COM 
53311261SKuriakose.Kuruvilla@Sun.COM static const struct events_table_t *arch_events_table = NULL;
5348146SKrishnendu.Sadhukhan@Sun.COM static uint64_t known_arch_events;
5358146SKrishnendu.Sadhukhan@Sun.COM static uint64_t known_ffc_num;
5367728SKuriakose.Kuruvilla@Sun.COM 
53711625SKuriakose.Kuruvilla@Sun.COM #define	GENERICEVENTS_FAM6_NHM						       \
53811261SKuriakose.Kuruvilla@Sun.COM { 0xc4, 0x01, C0|C1|C2|C3, "PAPI_br_cn" },   /* br_inst_retired.conditional */ \
53911261SKuriakose.Kuruvilla@Sun.COM { 0x1d, 0x01, C0|C1|C2|C3, "PAPI_hw_int" },  /* hw_int.rcx		    */ \
54011261SKuriakose.Kuruvilla@Sun.COM { 0x17, 0x01, C0|C1|C2|C3, "PAPI_tot_iis" }, /* inst_queue_writes	    */ \
54111261SKuriakose.Kuruvilla@Sun.COM { 0x43, 0x01, C0|C1,	   "PAPI_l1_dca" },  /* l1d_all_ref.any		    */ \
54211261SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x03, C0|C1|C2|C3, "PAPI_l1_dcm" },  /* l2_rqsts. loads and rfos    */ \
54311261SKuriakose.Kuruvilla@Sun.COM { 0x40, 0x0f, C0|C1|C2|C3, "PAPI_l1_dcr" },  /* l1d_cache_ld.mesi	    */ \
54411261SKuriakose.Kuruvilla@Sun.COM { 0x41, 0x0f, C0|C1|C2|C3, "PAPI_l1_dcw" },  /* l1d_cache_st.mesi	    */ \
54511261SKuriakose.Kuruvilla@Sun.COM { 0x80, 0x03, C0|C1|C2|C3, "PAPI_l1_ica" },  /* l1i.reads		    */ \
54611261SKuriakose.Kuruvilla@Sun.COM { 0x80, 0x01, C0|C1|C2|C3, "PAPI_l1_ich" },  /* l1i.hits		    */ \
54711261SKuriakose.Kuruvilla@Sun.COM { 0x80, 0x02, C0|C1|C2|C3, "PAPI_l1_icm" },  /* l1i.misses		    */ \
54811261SKuriakose.Kuruvilla@Sun.COM { 0x80, 0x03, C0|C1|C2|C3, "PAPI_l1_icr" },  /* l1i.reads		    */ \
54911261SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x33, C0|C1|C2|C3, "PAPI_l1_ldm" },  /* l2_rqsts. loads and ifetches */\
55011261SKuriakose.Kuruvilla@Sun.COM { 0x24, 0xff, C0|C1|C2|C3, "PAPI_l1_tcm" },  /* l2_rqsts.references	    */ \
55111261SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x02, C0|C1|C2|C3, "PAPI_l2_ldm" },  /* l2_rqsts.ld_miss	    */ \
55211261SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x08, C0|C1|C2|C3, "PAPI_l2_stm" },  /* l2_rqsts.rfo_miss	    */ \
55311261SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x3f, C0|C1|C2|C3, "PAPI_l2_tca" },				       \
55411261SKuriakose.Kuruvilla@Sun.COM 				/* l2_rqsts. loads, rfos and ifetches */       \
55511261SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x15, C0|C1|C2|C3, "PAPI_l2_tch" },				       \
55611261SKuriakose.Kuruvilla@Sun.COM 				/* l2_rqsts. ld_hit, rfo_hit and ifetch_hit */ \
55711261SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x2a, C0|C1|C2|C3, "PAPI_l2_tcm" },				       \
55811261SKuriakose.Kuruvilla@Sun.COM 			/* l2_rqsts. ld_miss, rfo_miss and ifetch_miss */      \
55911261SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x33, C0|C1|C2|C3, "PAPI_l2_tcr" },  /* l2_rqsts. loads and ifetches */\
56011261SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x0c, C0|C1|C2|C3, "PAPI_l2_tcw" },  /* l2_rqsts.rfos		    */ \
56111261SKuriakose.Kuruvilla@Sun.COM { 0x2e, 0x4f, C0|C1|C2|C3, "PAPI_l3_tca" },  /* l3_lat_cache.reference	    */ \
56211261SKuriakose.Kuruvilla@Sun.COM { 0x2e, 0x41, C0|C1|C2|C3, "PAPI_l3_tcm" },  /* l3_lat_cache.misses	    */ \
56311261SKuriakose.Kuruvilla@Sun.COM { 0x0b, 0x01, C0|C1|C2|C3, "PAPI_ld_ins" },  /* mem_inst_retired.loads	    */ \
56411261SKuriakose.Kuruvilla@Sun.COM { 0x0b, 0x03, C0|C1|C2|C3, "PAPI_lst_ins" },				       \
56511261SKuriakose.Kuruvilla@Sun.COM 				/* mem_inst_retired.loads and stores	    */ \
56611261SKuriakose.Kuruvilla@Sun.COM { 0x26, 0xf0, C0|C1|C2|C3, "PAPI_prf_dm" },  /* l2_data_rqsts.prefetch.mesi */ \
56711261SKuriakose.Kuruvilla@Sun.COM { 0x0b, 0x02, C0|C1|C2|C3, "PAPI_sr_ins" },  /* mem_inst_retired.stores	    */ \
56811261SKuriakose.Kuruvilla@Sun.COM { 0x49, 0x01, C0|C1|C2|C3, "PAPI_tlb_dm" },  /* dtlb_misses.any		    */ \
56911261SKuriakose.Kuruvilla@Sun.COM { 0x85, 0x01, C0|C1|C2|C3, "PAPI_tlb_im" }   /* itlb_misses.any		    */
57011261SKuriakose.Kuruvilla@Sun.COM 
57111261SKuriakose.Kuruvilla@Sun.COM 
57211625SKuriakose.Kuruvilla@Sun.COM #define	EVENTS_FAM6_NHM							\
5737728SKuriakose.Kuruvilla@Sun.COM 									\
5747728SKuriakose.Kuruvilla@Sun.COM { 0x80, 0x04, C0|C1|C2|C3, "l1i.cycles_stalled" },			\
5757728SKuriakose.Kuruvilla@Sun.COM { 0x80, 0x01, C0|C1|C2|C3, "l1i.hits" },				\
5767728SKuriakose.Kuruvilla@Sun.COM { 0x80, 0x02, C0|C1|C2|C3, "l1i.misses" },				\
5777728SKuriakose.Kuruvilla@Sun.COM 									\
5787728SKuriakose.Kuruvilla@Sun.COM { 0x80, 0x03, C0|C1|C2|C3, "l1i.reads" },				\
5797728SKuriakose.Kuruvilla@Sun.COM { 0x82, 0x01, C0|C1|C2|C3, "large_itlb.hit" },				\
5807728SKuriakose.Kuruvilla@Sun.COM { 0x87, 0x0F, C0|C1|C2|C3, "ild_stall.any" },				\
5817728SKuriakose.Kuruvilla@Sun.COM 									\
5827728SKuriakose.Kuruvilla@Sun.COM { 0x87, 0x04, C0|C1|C2|C3, "ild_stall.iq_full" },			\
5837728SKuriakose.Kuruvilla@Sun.COM { 0x87, 0x01, C0|C1|C2|C3, "ild_stall.lcp" },				\
5847728SKuriakose.Kuruvilla@Sun.COM { 0x87, 0x02, C0|C1|C2|C3, "ild_stall.mru" },				\
5857728SKuriakose.Kuruvilla@Sun.COM 									\
5867728SKuriakose.Kuruvilla@Sun.COM { 0x87, 0x08, C0|C1|C2|C3, "ild_stall.regen" },				\
5877728SKuriakose.Kuruvilla@Sun.COM { 0xE6, 0x02, C0|C1|C2|C3, "baclear.bad_target" },			\
5887728SKuriakose.Kuruvilla@Sun.COM { 0xE6, 0x01, C0|C1|C2|C3, "baclear.clear" },				\
5897728SKuriakose.Kuruvilla@Sun.COM 									\
5907728SKuriakose.Kuruvilla@Sun.COM { 0xE8, 0x01, C0|C1|C2|C3, "bpu_clears.early" },			\
5917728SKuriakose.Kuruvilla@Sun.COM { 0xE8, 0x02, C0|C1|C2|C3, "bpu_clears.late" },				\
5927728SKuriakose.Kuruvilla@Sun.COM { 0xE5, 0x01, C0|C1|C2|C3, "bpu_missed_call_ret" },			\
5937728SKuriakose.Kuruvilla@Sun.COM 									\
5947728SKuriakose.Kuruvilla@Sun.COM { 0xE0, 0x01, C0|C1|C2|C3, "br_inst_decoded" },				\
5957728SKuriakose.Kuruvilla@Sun.COM { 0x88, 0x7F, C0|C1|C2|C3, "br_inst_exec.any" },			\
5967728SKuriakose.Kuruvilla@Sun.COM { 0x88, 0x01, C0|C1|C2|C3, "br_inst_exec.cond" },			\
5977728SKuriakose.Kuruvilla@Sun.COM 									\
5987728SKuriakose.Kuruvilla@Sun.COM { 0x88, 0x02, C0|C1|C2|C3, "br_inst_exec.direct" },			\
5997728SKuriakose.Kuruvilla@Sun.COM { 0x88, 0x10, C0|C1|C2|C3, "br_inst_exec.direct_near_call" },		\
6007728SKuriakose.Kuruvilla@Sun.COM { 0x88, 0x20, C0|C1|C2|C3, "br_inst_exec.indirect_near_call" },		\
6017728SKuriakose.Kuruvilla@Sun.COM 									\
6027728SKuriakose.Kuruvilla@Sun.COM { 0x88, 0x04, C0|C1|C2|C3, "br_inst_exec.indirect_non_call" },		\
6037728SKuriakose.Kuruvilla@Sun.COM { 0x88, 0x30, C0|C1|C2|C3, "br_inst_exec.near_calls" },			\
6047728SKuriakose.Kuruvilla@Sun.COM { 0x88, 0x07, C0|C1|C2|C3, "br_inst_exec.non_calls" },			\
6057728SKuriakose.Kuruvilla@Sun.COM 									\
6067728SKuriakose.Kuruvilla@Sun.COM { 0x88, 0x08, C0|C1|C2|C3, "br_inst_exec.return_near" },		\
6077728SKuriakose.Kuruvilla@Sun.COM { 0x88, 0x40, C0|C1|C2|C3, "br_inst_exec.taken" },			\
6087728SKuriakose.Kuruvilla@Sun.COM { 0x89, 0x7F, C0|C1|C2|C3, "br_misp_exec.any" },			\
6097728SKuriakose.Kuruvilla@Sun.COM 									\
6107728SKuriakose.Kuruvilla@Sun.COM { 0x89, 0x01, C0|C1|C2|C3, "br_misp_exec.cond" },			\
6117728SKuriakose.Kuruvilla@Sun.COM { 0x89, 0x02, C0|C1|C2|C3, "br_misp_exec.direct" },			\
6127728SKuriakose.Kuruvilla@Sun.COM { 0x89, 0x10, C0|C1|C2|C3, "br_misp_exec.direct_near_call" },		\
6137728SKuriakose.Kuruvilla@Sun.COM 									\
6147728SKuriakose.Kuruvilla@Sun.COM { 0x89, 0x20, C0|C1|C2|C3, "br_misp_exec.indirect_near_call" },		\
6157728SKuriakose.Kuruvilla@Sun.COM { 0x89, 0x04, C0|C1|C2|C3, "br_misp_exec.indirect_non_call" },		\
6167728SKuriakose.Kuruvilla@Sun.COM { 0x89, 0x30, C0|C1|C2|C3, "br_misp_exec.near_calls" },			\
6177728SKuriakose.Kuruvilla@Sun.COM 									\
6187728SKuriakose.Kuruvilla@Sun.COM { 0x89, 0x07, C0|C1|C2|C3, "br_misp_exec.non_calls" },			\
6197728SKuriakose.Kuruvilla@Sun.COM { 0x89, 0x08, C0|C1|C2|C3, "br_misp_exec.return_near" },		\
6207728SKuriakose.Kuruvilla@Sun.COM { 0x89, 0x40, C0|C1|C2|C3, "br_misp_exec.taken" },			\
6217728SKuriakose.Kuruvilla@Sun.COM 									\
6227728SKuriakose.Kuruvilla@Sun.COM { 0x17, 0x01, C0|C1|C2|C3, "inst_queue_writes" },			\
6237728SKuriakose.Kuruvilla@Sun.COM { 0x1E, 0x01, C0|C1|C2|C3, "inst_queue_write_cycles" },			\
6247728SKuriakose.Kuruvilla@Sun.COM { 0xA7, 0x01, C0|C1|C2|C3, "baclear_force_iq" },			\
6257728SKuriakose.Kuruvilla@Sun.COM 									\
6267728SKuriakose.Kuruvilla@Sun.COM { 0xD0, 0x01, C0|C1|C2|C3, "macro_insts.decoded" },			\
6277728SKuriakose.Kuruvilla@Sun.COM { 0xA6, 0x01, C0|C1|C2|C3, "macro_insts.fusions_decoded" },		\
6287728SKuriakose.Kuruvilla@Sun.COM { 0x19, 0x01, C0|C1|C2|C3, "two_uop_insts_decoded" },			\
6297728SKuriakose.Kuruvilla@Sun.COM 									\
6307728SKuriakose.Kuruvilla@Sun.COM { 0x18, 0x01, C0|C1|C2|C3, "inst_decoded.dec0" },			\
6317728SKuriakose.Kuruvilla@Sun.COM { 0xD1, 0x04, C0|C1|C2|C3, "uops_decoded.esp_folding" },		\
6327728SKuriakose.Kuruvilla@Sun.COM { 0xD1, 0x08, C0|C1|C2|C3, "uops_decoded.esp_sync" },			\
6337728SKuriakose.Kuruvilla@Sun.COM 									\
6347728SKuriakose.Kuruvilla@Sun.COM { 0xD1, 0x02, C0|C1|C2|C3, "uops_decoded.ms" },				\
6357728SKuriakose.Kuruvilla@Sun.COM { 0x20, 0x01, C0|C1|C2|C3, "lsd_overflow" },				\
6367728SKuriakose.Kuruvilla@Sun.COM { 0x0E, 0x01, C0|C1|C2|C3, "uops_issued.any" },				\
6377728SKuriakose.Kuruvilla@Sun.COM 									\
6387728SKuriakose.Kuruvilla@Sun.COM { 0x0E, 0x02, C0|C1|C2|C3, "uops_issued.fused" },			\
6397728SKuriakose.Kuruvilla@Sun.COM { 0xA2, 0x20, C0|C1|C2|C3, "resource_stalls.fpcw" },			\
6407728SKuriakose.Kuruvilla@Sun.COM { 0xA2, 0x02, C0|C1|C2|C3, "resource_stalls.load" },			\
6417728SKuriakose.Kuruvilla@Sun.COM 									\
6427728SKuriakose.Kuruvilla@Sun.COM { 0xA2, 0x40, C0|C1|C2|C3, "resource_stalls.mxcsr" },			\
6437728SKuriakose.Kuruvilla@Sun.COM { 0xA2, 0x04, C0|C1|C2|C3, "resource_stalls.rs_full" },			\
6447728SKuriakose.Kuruvilla@Sun.COM { 0xA2, 0x08, C0|C1|C2|C3, "resource_stalls.store" },			\
6457728SKuriakose.Kuruvilla@Sun.COM 									\
6467728SKuriakose.Kuruvilla@Sun.COM { 0xA2, 0x01, C0|C1|C2|C3, "resource_stalls.any" },			\
6477728SKuriakose.Kuruvilla@Sun.COM { 0xD2, 0x01, C0|C1|C2|C3, "rat_stalls.flags" },			\
6487728SKuriakose.Kuruvilla@Sun.COM { 0xD2, 0x02, C0|C1|C2|C3, "rat_stalls.registers" },			\
6497728SKuriakose.Kuruvilla@Sun.COM 									\
6507728SKuriakose.Kuruvilla@Sun.COM { 0xD2, 0x04, C0|C1|C2|C3, "rat_stalls.rob_read_port" },		\
6517728SKuriakose.Kuruvilla@Sun.COM { 0xD2, 0x08, C0|C1|C2|C3, "rat_stalls.scoreboard" },			\
6527728SKuriakose.Kuruvilla@Sun.COM { 0xD2, 0x0F, C0|C1|C2|C3, "rat_stalls.any" },				\
6537728SKuriakose.Kuruvilla@Sun.COM 									\
6547728SKuriakose.Kuruvilla@Sun.COM { 0xD4, 0x01, C0|C1|C2|C3, "seg_rename_stalls" },			\
6557728SKuriakose.Kuruvilla@Sun.COM { 0xD5, 0x01, C0|C1|C2|C3, "es_reg_renames" },				\
6567728SKuriakose.Kuruvilla@Sun.COM { 0x10, 0x02, C0|C1|C2|C3, "fp_comp_ops_exe.mmx" },			\
6577728SKuriakose.Kuruvilla@Sun.COM 									\
6587728SKuriakose.Kuruvilla@Sun.COM { 0x10, 0x80, C0|C1|C2|C3, "fp_comp_ops_exe.sse_double_precision" },	\
6597728SKuriakose.Kuruvilla@Sun.COM { 0x10, 0x04, C0|C1|C2|C3, "fp_comp_ops_exe.sse_fp" },			\
6607728SKuriakose.Kuruvilla@Sun.COM { 0x10, 0x10, C0|C1|C2|C3, "fp_comp_ops_exe.sse_fp_packed" },		\
6617728SKuriakose.Kuruvilla@Sun.COM 									\
6627728SKuriakose.Kuruvilla@Sun.COM { 0x10, 0x20, C0|C1|C2|C3, "fp_comp_ops_exe.sse_fp_scalar" },		\
6637728SKuriakose.Kuruvilla@Sun.COM { 0x10, 0x40, C0|C1|C2|C3, "fp_comp_ops_exe.sse_single_precision" },	\
6647728SKuriakose.Kuruvilla@Sun.COM { 0x10, 0x08, C0|C1|C2|C3, "fp_comp_ops_exe.sse2_integer" },		\
6657728SKuriakose.Kuruvilla@Sun.COM 									\
6667728SKuriakose.Kuruvilla@Sun.COM { 0x10, 0x01, C0|C1|C2|C3, "fp_comp_ops_exe.x87" },			\
6677728SKuriakose.Kuruvilla@Sun.COM { 0x14, 0x01, C0|C1|C2|C3, "arith.cycles_div_busy" },			\
6687728SKuriakose.Kuruvilla@Sun.COM { 0x14, 0x02, C0|C1|C2|C3, "arith.mul" },				\
6697728SKuriakose.Kuruvilla@Sun.COM 									\
6707728SKuriakose.Kuruvilla@Sun.COM { 0x12, 0x04, C0|C1|C2|C3, "simd_int_128.pack" },			\
6717728SKuriakose.Kuruvilla@Sun.COM { 0x12, 0x20, C0|C1|C2|C3, "simd_int_128.packed_arith" },		\
6727728SKuriakose.Kuruvilla@Sun.COM { 0x12, 0x10, C0|C1|C2|C3, "simd_int_128.packed_logical" },		\
6737728SKuriakose.Kuruvilla@Sun.COM 									\
6747728SKuriakose.Kuruvilla@Sun.COM { 0x12, 0x01, C0|C1|C2|C3, "simd_int_128.packed_mpy" },			\
6757728SKuriakose.Kuruvilla@Sun.COM { 0x12, 0x02, C0|C1|C2|C3, "simd_int_128.packed_shift" },		\
6767728SKuriakose.Kuruvilla@Sun.COM { 0x12, 0x40, C0|C1|C2|C3, "simd_int_128.shuffle_move" },		\
6777728SKuriakose.Kuruvilla@Sun.COM 									\
6787728SKuriakose.Kuruvilla@Sun.COM { 0x12, 0x08, C0|C1|C2|C3, "simd_int_128.unpack" },			\
6797728SKuriakose.Kuruvilla@Sun.COM { 0xFD, 0x04, C0|C1|C2|C3, "simd_int_64.pack" },			\
6807728SKuriakose.Kuruvilla@Sun.COM { 0xFD, 0x20, C0|C1|C2|C3, "simd_int_64.packed_arith" },		\
6817728SKuriakose.Kuruvilla@Sun.COM 									\
6827728SKuriakose.Kuruvilla@Sun.COM { 0xFD, 0x10, C0|C1|C2|C3, "simd_int_64.packed_logical" },		\
6837728SKuriakose.Kuruvilla@Sun.COM { 0xFD, 0x01, C0|C1|C2|C3, "simd_int_64.packed_mpy" },			\
6847728SKuriakose.Kuruvilla@Sun.COM { 0xFD, 0x02, C0|C1|C2|C3, "simd_int_64.packed_shift" },		\
6857728SKuriakose.Kuruvilla@Sun.COM 									\
6867728SKuriakose.Kuruvilla@Sun.COM { 0xFD, 0x40, C0|C1|C2|C3, "simd_int_64.shuffle_move" },		\
6877728SKuriakose.Kuruvilla@Sun.COM { 0xFD, 0x08, C0|C1|C2|C3, "simd_int_64.unpack" },			\
6887728SKuriakose.Kuruvilla@Sun.COM { 0xB1, 0x01, C0|C1|C2|C3, "uops_executed.port0" },			\
6897728SKuriakose.Kuruvilla@Sun.COM 									\
6907728SKuriakose.Kuruvilla@Sun.COM { 0xB1, 0x02, C0|C1|C2|C3, "uops_executed.port1" },			\
6917728SKuriakose.Kuruvilla@Sun.COM { 0x40, 0x04, C0|C1, "l1d_cache_ld.e_state" },				\
6927728SKuriakose.Kuruvilla@Sun.COM { 0x40, 0x01, C0|C1, "l1d_cache_ld.i_state" },				\
6937728SKuriakose.Kuruvilla@Sun.COM 									\
6947728SKuriakose.Kuruvilla@Sun.COM { 0x40, 0x08, C0|C1, "l1d_cache_ld.m_state" },				\
6957728SKuriakose.Kuruvilla@Sun.COM { 0x40, 0x0F, C0|C1, "l1d_cache_ld.mesi" },				\
6967728SKuriakose.Kuruvilla@Sun.COM { 0x40, 0x02, C0|C1, "l1d_cache_ld.s_state" },				\
6977728SKuriakose.Kuruvilla@Sun.COM 									\
6987728SKuriakose.Kuruvilla@Sun.COM { 0x41, 0x04, C0|C1, "l1d_cache_st.e_state" },				\
6997728SKuriakose.Kuruvilla@Sun.COM { 0x41, 0x08, C0|C1, "l1d_cache_st.m_state" },				\
7007728SKuriakose.Kuruvilla@Sun.COM { 0x41, 0x0F, C0|C1, "l1d_cache_st.mesi" },				\
7017728SKuriakose.Kuruvilla@Sun.COM 									\
7027728SKuriakose.Kuruvilla@Sun.COM { 0x41, 0x02, C0|C1, "l1d_cache_st.s_state" },				\
7037728SKuriakose.Kuruvilla@Sun.COM { 0x42, 0x04, C0|C1, "l1d_cache_lock.e_state" },			\
7047728SKuriakose.Kuruvilla@Sun.COM { 0x42, 0x01, C0|C1, "l1d_cache_lock.hit" },				\
7057728SKuriakose.Kuruvilla@Sun.COM 									\
7067728SKuriakose.Kuruvilla@Sun.COM { 0x42, 0x08, C0|C1, "l1d_cache_lock.m_state" },			\
7077728SKuriakose.Kuruvilla@Sun.COM { 0x42, 0x02, C0|C1, "l1d_cache_lock.s_state" },			\
7087728SKuriakose.Kuruvilla@Sun.COM { 0x43, 0x01, C0|C1, "l1d_all_ref.any" },				\
7097728SKuriakose.Kuruvilla@Sun.COM 									\
7107728SKuriakose.Kuruvilla@Sun.COM { 0x43, 0x02, C0|C1, "l1d_all_ref.cacheable" },				\
7117728SKuriakose.Kuruvilla@Sun.COM { 0x4B, 0x01, C0|C1, "mmx2_mem_exec.nta" },				\
7127728SKuriakose.Kuruvilla@Sun.COM { 0x4C, 0x01, C0|C1, "load_hit_pre" },					\
7137728SKuriakose.Kuruvilla@Sun.COM 									\
7147728SKuriakose.Kuruvilla@Sun.COM { 0x4E, 0x02, C0|C1, "l1d_prefetch.miss" },				\
7157728SKuriakose.Kuruvilla@Sun.COM { 0x4E, 0x01, C0|C1, "l1d_prefetch.requests" },				\
7167728SKuriakose.Kuruvilla@Sun.COM { 0x4E, 0x04, C0|C1, "l1d_prefetch.triggers" },				\
7177728SKuriakose.Kuruvilla@Sun.COM 									\
7187728SKuriakose.Kuruvilla@Sun.COM { 0x51, 0x04, C0|C1, "l1d.m_evict" },					\
7197728SKuriakose.Kuruvilla@Sun.COM { 0x51, 0x02, C0|C1, "l1d.m_repl" },					\
7207728SKuriakose.Kuruvilla@Sun.COM { 0x51, 0x08, C0|C1, "l1d.m_snoop_evict" },				\
7217728SKuriakose.Kuruvilla@Sun.COM 									\
7227728SKuriakose.Kuruvilla@Sun.COM { 0x51, 0x01, C0|C1, "l1d.repl" },					\
7237728SKuriakose.Kuruvilla@Sun.COM { 0x52, 0x01, C0|C1, "l1d_cache_prefetch_lock_fb_hit" },		\
7247728SKuriakose.Kuruvilla@Sun.COM { 0x53, 0x01, C0|C1, "l1d_cache_lock_fb_hit" },				\
7257728SKuriakose.Kuruvilla@Sun.COM 									\
7267728SKuriakose.Kuruvilla@Sun.COM { 0x63, 0x02, C0|C1, "cache_lock_cycles.l1d" },				\
7277728SKuriakose.Kuruvilla@Sun.COM { 0x63, 0x01, C0|C1, "cache_lock_cycles.l1d_l2" },			\
7287728SKuriakose.Kuruvilla@Sun.COM { 0x06, 0x04, C0|C1|C2|C3, "store_blocks.at_ret" },			\
7297728SKuriakose.Kuruvilla@Sun.COM 									\
7307728SKuriakose.Kuruvilla@Sun.COM { 0x06, 0x08, C0|C1|C2|C3, "store_blocks.l1d_block" },			\
7317728SKuriakose.Kuruvilla@Sun.COM { 0x06, 0x01, C0|C1|C2|C3, "store_blocks.not_sta" },			\
7327728SKuriakose.Kuruvilla@Sun.COM { 0x06, 0x02, C0|C1|C2|C3, "store_blocks.sta" },			\
7337728SKuriakose.Kuruvilla@Sun.COM 									\
7347728SKuriakose.Kuruvilla@Sun.COM { 0x13, 0x07, C0|C1|C2|C3, "load_dispatch.any" },			\
7357728SKuriakose.Kuruvilla@Sun.COM { 0x13, 0x04, C0|C1|C2|C3, "load_dispatch.mob" },			\
7367728SKuriakose.Kuruvilla@Sun.COM { 0x13, 0x01, C0|C1|C2|C3, "load_dispatch.rs" },			\
7377728SKuriakose.Kuruvilla@Sun.COM 									\
7387728SKuriakose.Kuruvilla@Sun.COM { 0x13, 0x02, C0|C1|C2|C3, "load_dispatch.rs_delayed" },		\
7397728SKuriakose.Kuruvilla@Sun.COM { 0x08, 0x01, C0|C1|C2|C3, "dtlb_load_misses.any" },			\
7407728SKuriakose.Kuruvilla@Sun.COM { 0x08, 0x20, C0|C1|C2|C3, "dtlb_load_misses.pde_miss" },		\
7417728SKuriakose.Kuruvilla@Sun.COM 									\
7427728SKuriakose.Kuruvilla@Sun.COM { 0x08, 0x02, C0|C1|C2|C3, "dtlb_load_misses.walk_completed" },		\
7437728SKuriakose.Kuruvilla@Sun.COM { 0x49, 0x01, C0|C1|C2|C3, "dtlb_misses.any" },				\
7447728SKuriakose.Kuruvilla@Sun.COM { 0x49, 0x10, C0|C1|C2|C3, "dtlb_misses.stlb_hit" },			\
7457728SKuriakose.Kuruvilla@Sun.COM 									\
7467728SKuriakose.Kuruvilla@Sun.COM { 0x49, 0x02, C0|C1|C2|C3, "dtlb_misses.walk_completed" },		\
7477728SKuriakose.Kuruvilla@Sun.COM { 0x4F, 0x02, C0|C1|C2|C3, "ept.epde_miss" },				\
7487728SKuriakose.Kuruvilla@Sun.COM { 0x4F, 0x08, C0|C1|C2|C3, "ept.epdpe_miss" },				\
7497728SKuriakose.Kuruvilla@Sun.COM 									\
7507728SKuriakose.Kuruvilla@Sun.COM { 0x85, 0x01, C0|C1|C2|C3, "itlb_misses.any" },				\
7517728SKuriakose.Kuruvilla@Sun.COM { 0x85, 0x02, C0|C1|C2|C3, "itlb_misses.walk_completed" },		\
7527728SKuriakose.Kuruvilla@Sun.COM { 0x24, 0xAA, C0|C1|C2|C3, "l2_rqsts.miss" },				\
7537728SKuriakose.Kuruvilla@Sun.COM 									\
7547728SKuriakose.Kuruvilla@Sun.COM { 0x24, 0xFF, C0|C1|C2|C3, "l2_rqsts.references" },			\
7557728SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x10, C0|C1|C2|C3, "l2_rqsts.ifetch_hit" },			\
7567728SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x20, C0|C1|C2|C3, "l2_rqsts.ifetch_miss" },			\
7577728SKuriakose.Kuruvilla@Sun.COM 									\
7587728SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x30, C0|C1|C2|C3, "l2_rqsts.ifetches" },			\
7597728SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x01, C0|C1|C2|C3, "l2_rqsts.ld_hit" },				\
7607728SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x02, C0|C1|C2|C3, "l2_rqsts.ld_miss" },			\
7617728SKuriakose.Kuruvilla@Sun.COM 									\
7627728SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x03, C0|C1|C2|C3, "l2_rqsts.loads" },				\
7637728SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x40, C0|C1|C2|C3, "l2_rqsts.prefetch_hit" },			\
7647728SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x80, C0|C1|C2|C3, "l2_rqsts.prefetch_miss" },			\
7657728SKuriakose.Kuruvilla@Sun.COM 									\
7667728SKuriakose.Kuruvilla@Sun.COM { 0x24, 0xC0, C0|C1|C2|C3, "l2_rqsts.prefetches" },			\
7677728SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x04, C0|C1|C2|C3, "l2_rqsts.rfo_hit" },			\
7687728SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x08, C0|C1|C2|C3, "l2_rqsts.rfo_miss" },			\
7697728SKuriakose.Kuruvilla@Sun.COM 									\
7707728SKuriakose.Kuruvilla@Sun.COM { 0x24, 0x0C, C0|C1|C2|C3, "l2_rqsts.rfos" },				\
7717728SKuriakose.Kuruvilla@Sun.COM { 0x26, 0xFF, C0|C1|C2|C3, "l2_data_rqsts.any" },			\
7727728SKuriakose.Kuruvilla@Sun.COM { 0x26, 0x04, C0|C1|C2|C3, "l2_data_rqsts.demand.e_state" },		\
7737728SKuriakose.Kuruvilla@Sun.COM 									\
7747728SKuriakose.Kuruvilla@Sun.COM { 0x26, 0x01, C0|C1|C2|C3, "l2_data_rqsts.demand.i_state" },		\
7757728SKuriakose.Kuruvilla@Sun.COM { 0x26, 0x08, C0|C1|C2|C3, "l2_data_rqsts.demand.m_state" },		\
7767728SKuriakose.Kuruvilla@Sun.COM { 0x26, 0x0F, C0|C1|C2|C3, "l2_data_rqsts.demand.mesi" },		\
7777728SKuriakose.Kuruvilla@Sun.COM 									\
7787728SKuriakose.Kuruvilla@Sun.COM { 0x26, 0x02, C0|C1|C2|C3, "l2_data_rqsts.demand.s_state" },		\
7797728SKuriakose.Kuruvilla@Sun.COM { 0x26, 0x40, C0|C1|C2|C3, "l2_data_rqsts.prefetch.e_state" },		\
7807728SKuriakose.Kuruvilla@Sun.COM { 0x26, 0x10, C0|C1|C2|C3, "l2_data_rqsts.prefetch.i_state" },		\
7817728SKuriakose.Kuruvilla@Sun.COM 									\
7827728SKuriakose.Kuruvilla@Sun.COM { 0x26, 0x80, C0|C1|C2|C3, "l2_data_rqsts.prefetch.m_state" },		\
7837728SKuriakose.Kuruvilla@Sun.COM { 0x26, 0xF0, C0|C1|C2|C3, "l2_data_rqsts.prefetch.mesi" },		\
7847728SKuriakose.Kuruvilla@Sun.COM { 0x26, 0x20, C0|C1|C2|C3, "l2_data_rqsts.prefetch.s_state" },		\
7857728SKuriakose.Kuruvilla@Sun.COM 									\
7867728SKuriakose.Kuruvilla@Sun.COM { 0x27, 0x40, C0|C1|C2|C3, "l2_write.lock.e_state" },			\
7877728SKuriakose.Kuruvilla@Sun.COM { 0x27, 0x10, C0|C1|C2|C3, "l2_write.lock.i_state" },			\
7887728SKuriakose.Kuruvilla@Sun.COM { 0x27, 0x20, C0|C1|C2|C3, "l2_write.lock.s_state" },			\
7897728SKuriakose.Kuruvilla@Sun.COM 									\
7907728SKuriakose.Kuruvilla@Sun.COM { 0x27, 0x0E, C0|C1|C2|C3, "l2_write.rfo.hit" },			\
7917728SKuriakose.Kuruvilla@Sun.COM { 0x27, 0x01, C0|C1|C2|C3, "l2_write.rfo.i_state" },			\
7927728SKuriakose.Kuruvilla@Sun.COM { 0x27, 0x08, C0|C1|C2|C3, "l2_write.rfo.m_state" },			\
7937728SKuriakose.Kuruvilla@Sun.COM 									\
7947728SKuriakose.Kuruvilla@Sun.COM { 0x27, 0x0F, C0|C1|C2|C3, "l2_write.rfo.mesi" },			\
7957728SKuriakose.Kuruvilla@Sun.COM { 0x27, 0x02, C0|C1|C2|C3, "l2_write.rfo.s_state" },			\
7967728SKuriakose.Kuruvilla@Sun.COM { 0x28, 0x04, C0|C1|C2|C3, "l1d_wb_l2.e_state" },			\
7977728SKuriakose.Kuruvilla@Sun.COM 									\
7987728SKuriakose.Kuruvilla@Sun.COM { 0x28, 0x01, C0|C1|C2|C3, "l1d_wb_l2.i_state" },			\
7997728SKuriakose.Kuruvilla@Sun.COM { 0x28, 0x08, C0|C1|C2|C3, "l1d_wb_l2.m_state" },			\
8007728SKuriakose.Kuruvilla@Sun.COM { 0xF0, 0x80, C0|C1|C2|C3, "l2_transactions.any" },			\
8017728SKuriakose.Kuruvilla@Sun.COM 									\
8027728SKuriakose.Kuruvilla@Sun.COM { 0xF0, 0x20, C0|C1|C2|C3, "l2_transactions.fill" },			\
8037728SKuriakose.Kuruvilla@Sun.COM { 0xF0, 0x04, C0|C1|C2|C3, "l2_transactions.ifetch" },			\
8047728SKuriakose.Kuruvilla@Sun.COM { 0xF0, 0x10, C0|C1|C2|C3, "l2_transactions.l1d_wb" },			\
8057728SKuriakose.Kuruvilla@Sun.COM 									\
8067728SKuriakose.Kuruvilla@Sun.COM { 0xF0, 0x01, C0|C1|C2|C3, "l2_transactions.load" },			\
8077728SKuriakose.Kuruvilla@Sun.COM { 0xF0, 0x08, C0|C1|C2|C3, "l2_transactions.prefetch" },		\
8087728SKuriakose.Kuruvilla@Sun.COM { 0xF0, 0x02, C0|C1|C2|C3, "l2_transactions.rfo" },			\
8097728SKuriakose.Kuruvilla@Sun.COM 									\
8107728SKuriakose.Kuruvilla@Sun.COM { 0xF0, 0x40, C0|C1|C2|C3, "l2_transactions.wb" },			\
8117728SKuriakose.Kuruvilla@Sun.COM { 0xF1, 0x07, C0|C1|C2|C3, "l2_lines_in.any" },				\
8127728SKuriakose.Kuruvilla@Sun.COM { 0xF1, 0x04, C0|C1|C2|C3, "l2_lines_in.e_state" },			\
8137728SKuriakose.Kuruvilla@Sun.COM 									\
8147728SKuriakose.Kuruvilla@Sun.COM { 0xF1, 0x02, C0|C1|C2|C3, "l2_lines_in.s_state" },			\
8157728SKuriakose.Kuruvilla@Sun.COM { 0xF2, 0x0F, C0|C1|C2|C3, "l2_lines_out.any" },			\
8167728SKuriakose.Kuruvilla@Sun.COM { 0xF2, 0x01, C0|C1|C2|C3, "l2_lines_out.demand_clean" },		\
8177728SKuriakose.Kuruvilla@Sun.COM 									\
8187728SKuriakose.Kuruvilla@Sun.COM { 0xF2, 0x02, C0|C1|C2|C3, "l2_lines_out.demand_dirty" },		\
8197728SKuriakose.Kuruvilla@Sun.COM { 0xF2, 0x04, C0|C1|C2|C3, "l2_lines_out.prefetch_clean" },		\
8207728SKuriakose.Kuruvilla@Sun.COM { 0x6C, 0x01, C0|C1|C2|C3, "io_transactions" },				\
8217728SKuriakose.Kuruvilla@Sun.COM 									\
8227728SKuriakose.Kuruvilla@Sun.COM { 0xB0, 0x80, C0|C1|C2|C3, "offcore_requests.any" },			\
8237728SKuriakose.Kuruvilla@Sun.COM { 0xB0, 0x10, C0|C1|C2|C3, "offcore_requests.any.rfo" },		\
8247728SKuriakose.Kuruvilla@Sun.COM { 0xB0, 0x40, C0|C1|C2|C3, "offcore_requests.l1d_writeback" },		\
8257728SKuriakose.Kuruvilla@Sun.COM 									\
8267728SKuriakose.Kuruvilla@Sun.COM { 0xB8, 0x01, C0|C1|C2|C3, "snoop_response.hit" },			\
8277728SKuriakose.Kuruvilla@Sun.COM { 0xB8, 0x02, C0|C1|C2|C3, "snoop_response.hite" },			\
8287728SKuriakose.Kuruvilla@Sun.COM { 0xB8, 0x04, C0|C1|C2|C3, "snoop_response.hitm" },			\
8297728SKuriakose.Kuruvilla@Sun.COM 									\
8307728SKuriakose.Kuruvilla@Sun.COM { 0xF4, 0x10, C0|C1|C2|C3, "sq_misc.split_lock" },			\
8317728SKuriakose.Kuruvilla@Sun.COM { 0x0B, 0x01, C0|C1|C2|C3, "mem_inst_retired.loads" },			\
8327728SKuriakose.Kuruvilla@Sun.COM { 0x0B, 0x02, C0|C1|C2|C3, "mem_inst_retired.stores" },			\
8337728SKuriakose.Kuruvilla@Sun.COM 									\
8347728SKuriakose.Kuruvilla@Sun.COM { 0xC0, 0x04, C0|C1|C2|C3, "inst_retired.mmx" },			\
8357728SKuriakose.Kuruvilla@Sun.COM { 0xC0, 0x02, C0|C1|C2|C3, "inst_retired.x87" },			\
8367728SKuriakose.Kuruvilla@Sun.COM { 0xC7, 0x04, C0|C1|C2|C3, "ssex_uops_retired.packed_double" },		\
8377728SKuriakose.Kuruvilla@Sun.COM 									\
8387728SKuriakose.Kuruvilla@Sun.COM { 0xC7, 0x01, C0|C1|C2|C3, "ssex_uops_retired.packed_single" },		\
8397728SKuriakose.Kuruvilla@Sun.COM { 0xC7, 0x08, C0|C1|C2|C3, "ssex_uops_retired.scalar_double" },		\
8407728SKuriakose.Kuruvilla@Sun.COM { 0xC7, 0x02, C0|C1|C2|C3, "ssex_uops_retired.scalar_single" },		\
8417728SKuriakose.Kuruvilla@Sun.COM 									\
8427728SKuriakose.Kuruvilla@Sun.COM { 0xC7, 0x10, C0|C1|C2|C3, "ssex_uops_retired.vector_integer" },	\
8437728SKuriakose.Kuruvilla@Sun.COM { 0xC2, 0x01, C0|C1|C2|C3, "uops_retired.any" },			\
8447728SKuriakose.Kuruvilla@Sun.COM { 0xC2, 0x04, C0|C1|C2|C3, "uops_retired.macro_fused" },		\
8457728SKuriakose.Kuruvilla@Sun.COM 									\
8467728SKuriakose.Kuruvilla@Sun.COM { 0xC8, 0x20, C0|C1|C2|C3, "itlb_miss_retired" },			\
8477728SKuriakose.Kuruvilla@Sun.COM { 0xCB, 0x80, C0|C1|C2|C3, "mem_load_retired.dtlb_miss" },		\
8487728SKuriakose.Kuruvilla@Sun.COM { 0xCB, 0x40, C0|C1|C2|C3, "mem_load_retired.hit_lfb" },		\
8497728SKuriakose.Kuruvilla@Sun.COM 									\
8507728SKuriakose.Kuruvilla@Sun.COM { 0xCB, 0x01, C0|C1|C2|C3, "mem_load_retired.l1d_hit" },		\
8517728SKuriakose.Kuruvilla@Sun.COM { 0xCB, 0x02, C0|C1|C2|C3, "mem_load_retired.l2_hit" },			\
8527728SKuriakose.Kuruvilla@Sun.COM { 0xCB, 0x10, C0|C1|C2|C3, "mem_load_retired.llc_miss" },		\
8537728SKuriakose.Kuruvilla@Sun.COM 									\
8547728SKuriakose.Kuruvilla@Sun.COM { 0xCB, 0x04, C0|C1|C2|C3, "mem_load_retired.llc_unshared_hit" },	\
8557728SKuriakose.Kuruvilla@Sun.COM { 0xCB, 0x08, C0|C1|C2|C3, "mem_load_retired.other_core_l2_hit_hitm" },	\
8567728SKuriakose.Kuruvilla@Sun.COM { 0x0F, 0x02, C0|C1|C2|C3, "mem_uncore_retired.other_core_l2_hitm" },	\
8577728SKuriakose.Kuruvilla@Sun.COM 									\
8587728SKuriakose.Kuruvilla@Sun.COM { 0x0F, 0x08, C0|C1|C2|C3, "mem_uncore_retired.remote_cache_local_home_hit" },\
8597728SKuriakose.Kuruvilla@Sun.COM { 0x0F, 0x10, C0|C1|C2|C3, "mem_uncore_retired.remote_dram" },		\
8607728SKuriakose.Kuruvilla@Sun.COM { 0x0F, 0x20, C0|C1|C2|C3, "mem_uncore_retired.local_dram" },		\
8617728SKuriakose.Kuruvilla@Sun.COM 									\
8627728SKuriakose.Kuruvilla@Sun.COM { 0x0C, 0x01, C0|C1|C2|C3, "mem_store_retired.dtlb_miss" },		\
8637728SKuriakose.Kuruvilla@Sun.COM { 0xC4, 0x01, C0|C1|C2|C3, "br_inst_retired.conditional" },		\
8647728SKuriakose.Kuruvilla@Sun.COM { 0xC4, 0x02, C0|C1|C2|C3, "br_inst_retired.near_call" },		\
8657728SKuriakose.Kuruvilla@Sun.COM 									\
8667728SKuriakose.Kuruvilla@Sun.COM { 0xC5, 0x02, C0|C1|C2|C3, "br_misp_retired.near_call" },		\
8677728SKuriakose.Kuruvilla@Sun.COM { 0xDB, 0x01, C0|C1|C2|C3, "uop_unfusion" },				\
8687728SKuriakose.Kuruvilla@Sun.COM { 0xF7, 0x01, C0|C1|C2|C3, "fp_assist.all" },				\
8697728SKuriakose.Kuruvilla@Sun.COM 									\
8707728SKuriakose.Kuruvilla@Sun.COM { 0xF7, 0x04, C0|C1|C2|C3, "fp_assist.input" },				\
8717728SKuriakose.Kuruvilla@Sun.COM { 0xF7, 0x02, C0|C1|C2|C3, "fp_assist.output" },			\
8727728SKuriakose.Kuruvilla@Sun.COM { 0xCC, 0x03, C0|C1|C2|C3, "fp_mmx_trans.any" },			\
8737728SKuriakose.Kuruvilla@Sun.COM 									\
8747728SKuriakose.Kuruvilla@Sun.COM { 0xCC, 0x01, C0|C1|C2|C3, "fp_mmx_trans.to_fp" },			\
8757728SKuriakose.Kuruvilla@Sun.COM { 0xCC, 0x02, C0|C1|C2|C3, "fp_mmx_trans.to_mmx" },			\
8767728SKuriakose.Kuruvilla@Sun.COM { 0xC3, 0x04, C0|C1|C2|C3, "machine_clears.smc" }
8777728SKuriakose.Kuruvilla@Sun.COM 
87811261SKuriakose.Kuruvilla@Sun.COM #define	GENERICEVENTS_FAM6_MOD28					       \
87911261SKuriakose.Kuruvilla@Sun.COM { 0xc4, 0x00, C0|C1, "PAPI_br_ins" },	/* br_inst_retired.any */	       \
88011261SKuriakose.Kuruvilla@Sun.COM { 0xc5, 0x00, C0|C1, "PAPI_br_msp" },	/* br_inst_retired.mispred */	       \
88111261SKuriakose.Kuruvilla@Sun.COM { 0xc4, 0x03, C0|C1, "PAPI_br_ntk" },					       \
88211261SKuriakose.Kuruvilla@Sun.COM 			/* br_inst_retired.pred_not_taken|mispred_not_taken */ \
88311261SKuriakose.Kuruvilla@Sun.COM { 0xc4, 0x05, C0|C1, "PAPI_br_prc" },					       \
88411261SKuriakose.Kuruvilla@Sun.COM 			/* br_inst_retired.pred_not_taken|pred_taken */	       \
88511261SKuriakose.Kuruvilla@Sun.COM { 0xc8, 0x00, C0|C1, "PAPI_hw_int" },	/* hw_int_rcv */	      	       \
88611261SKuriakose.Kuruvilla@Sun.COM { 0xaa, 0x03, C0|C1, "PAPI_tot_iis" },	/* macro_insts.all_decoded */	       \
88711261SKuriakose.Kuruvilla@Sun.COM { 0x40, 0x23, C0|C1, "PAPI_l1_dca" },	/* l1d_cache.l1|st */	      	       \
88811261SKuriakose.Kuruvilla@Sun.COM { 0x2a, 0x41, C0|C1, "PAPI_l2_stm" },	/* l2_st.self.i_state */	       \
88911261SKuriakose.Kuruvilla@Sun.COM { 0x2e, 0x4f, C0|C1, "PAPI_l2_tca" },	/* longest_lat_cache.reference */      \
89011261SKuriakose.Kuruvilla@Sun.COM { 0x2e, 0x4e, C0|C1, "PAPI_l2_tch" },   /* l2_rqsts.mes */		       \
89111261SKuriakose.Kuruvilla@Sun.COM { 0x2e, 0x41, C0|C1, "PAPI_l2_tcm" },	/* longest_lat_cache.miss */	       \
89211261SKuriakose.Kuruvilla@Sun.COM { 0x2a, 0x4f, C0|C1, "PAPI_l2_tcw" },	/* l2_st.self.mesi */		       \
89311261SKuriakose.Kuruvilla@Sun.COM { 0x08, 0x07, C0|C1, "PAPI_tlb_dm" },	/* data_tlb_misses.dtlb.miss */	       \
89411261SKuriakose.Kuruvilla@Sun.COM { 0x82, 0x02, C0|C1, "PAPI_tlb_im" }	/* itlb.misses */
89511261SKuriakose.Kuruvilla@Sun.COM 
89611261SKuriakose.Kuruvilla@Sun.COM 
8978425SKrishnendu.Sadhukhan@Sun.COM #define	EVENTS_FAM6_MOD28						\
8988425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x2,  0x81, C0|C1, "store_forwards.good" },                   \
8998425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x6,  0x0,  C0|C1, "segment_reg_loads.any" },                 \
9008425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x7,  0x1,  C0|C1, "prefetch.prefetcht0" },                   \
9018425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x7,  0x6,  C0|C1, "prefetch.sw_l2" },                        \
9028425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x7,  0x8,  C0|C1, "prefetch.prefetchnta" },                  \
9038425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x8,  0x7,  C0|C1, "data_tlb_misses.dtlb_miss" },             \
9048425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x8,  0x5,  C0|C1, "data_tlb_misses.dtlb_miss_ld" },          \
9058425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x8,  0x9,  C0|C1, "data_tlb_misses.l0_dtlb_miss_ld" },	\
9068425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x8,  0x6,  C0|C1, "data_tlb_misses.dtlb_miss_st" },          \
9078425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC,  0x3,  C0|C1, "page_walks.cycles" },                     \
9088425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x10, 0x1,  C0|C1, "x87_comp_ops_exe.any.s" },                \
9098425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x10, 0x81, C0|C1, "x87_comp_ops_exe.any.ar" },               \
9108425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x11, 0x1,  C0|C1, "fp_assist" },                             \
9118425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x11, 0x81, C0|C1, "fp_assist.ar" },                          \
9128425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x12, 0x1,  C0|C1, "mul.s" },                                 \
9138425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x12, 0x81, C0|C1, "mul.ar" },                                \
9148425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x13, 0x1,  C0|C1, "div.s" },                                 \
9158425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x13, 0x81, C0|C1, "div.ar" },                                \
9168425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x14, 0x1,  C0|C1, "cycles_div_busy" },                       \
9178425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x21, 0x0,  C0|C1, "l2_ads" },                      		\
9188425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x22, 0x0,  C0|C1, "l2_dbus_busy" },                		\
9198425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x24, 0x0,  C0|C1, "l2_lines_in" },   			\
9208425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x25, 0x0,  C0|C1, "l2_m_lines_in" },               		\
9218425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x26, 0x0,  C0|C1, "l2_lines_out" },  			\
9228425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x27, 0x0,  C0|C1, "l2_m_lines_out" },			\
9238425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x28, 0x0,  C0|C1, "l2_ifetch" },  				\
9248425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x29, 0x0,  C0|C1, "l2_ld" },					\
9258425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x2A, 0x0,  C0|C1, "l2_st" },      				\
9268425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x2B, 0x0,  C0|C1, "l2_lock" },    				\
9278425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x2E, 0x0,  C0|C1, "l2_rqsts" },             			\
9288425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x2E, 0x41, C0|C1, "l2_rqsts.self.demand.i_state" },		\
9298425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x2E, 0x4F, C0|C1, "l2_rqsts.self.demand.mesi" },		\
9308425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x30, 0x0,  C0|C1, "l2_reject_bus_q" },			\
9318425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x32, 0x0,  C0|C1, "l2_no_req" },                   		\
9328425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x3A, 0x0,  C0|C1, "eist_trans" },                            \
9338425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x3B, 0xC0, C0|C1, "thermal_trip" },                          \
9348425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x3C, 0x0,  C0|C1, "cpu_clk_unhalted.core_p" },               \
9358425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x3C, 0x1,  C0|C1, "cpu_clk_unhalted.bus" },                  \
9368425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x3C, 0x2,  C0|C1, "cpu_clk_unhalted.no_other" },             \
9378425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x40, 0x21, C0|C1, "l1d_cache.ld" },                          \
9388425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x40, 0x22, C0|C1, "l1d_cache.st" },                          \
9398425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x60, 0x0,  C0|C1, "bus_request_outstanding" },		\
9408425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x61, 0x0,  C0|C1, "bus_bnr_drv" },                		\
9418425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x62, 0x0,  C0|C1, "bus_drdy_clocks" },            		\
9428425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x63, 0x0,  C0|C1, "bus_lock_clocks" },  			\
9438425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x64, 0x0,  C0|C1, "bus_data_rcv" },                		\
9448425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x65, 0x0,  C0|C1, "bus_trans_brd" },    			\
9458425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x66, 0x0,  C0|C1, "bus_trans_rfo" },    			\
9468425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x67, 0x0,  C0|C1, "bus_trans_wb" },     			\
9478425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x68, 0x0,  C0|C1, "bus_trans_ifetch" }, 			\
9488425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x69, 0x0,  C0|C1, "bus_trans_inval" },  			\
9498425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x6A, 0x0,  C0|C1, "bus_trans_pwr" },				\
9508425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x6B, 0x0,  C0|C1, "bus_trans_p" },      			\
9518425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x6C, 0x0,  C0|C1, "bus_trans_io" },     			\
9528425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x6D, 0x0,  C0|C1, "bus_trans_def" },    			\
9538425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x6E, 0x0,  C0|C1, "bus_trans_burst" },  			\
9548425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x6F, 0x0,  C0|C1, "bus_trans_mem" },    			\
9558425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x70, 0x0,  C0|C1, "bus_trans_any" },    			\
9568425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x77, 0x0,  C0|C1, "ext_snoop" },     			\
9578425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x7A, 0x0,  C0|C1, "bus_hit_drv" },                		\
9588425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x7B, 0x0,  C0|C1, "bus_hitm_drv" },               		\
9598425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x7D, 0x0,  C0|C1, "busq_empty" },                  		\
9608425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x7E, 0x0,  C0|C1, "snoop_stall_drv" },  			\
9618425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x7F, 0x0,  C0|C1, "bus_io_wait" },				\
9628425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x80, 0x3,  C0|C1, "icache.accesses" },                       \
9638425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x80, 0x2,  C0|C1, "icache.misses" },                         \
9648425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x82, 0x4,  C0|C1, "itlb.flush" },                            \
9658425SKrishnendu.Sadhukhan@Sun.COM 	{ 0x82, 0x2,  C0|C1, "itlb.misses" },                           \
9668425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xAA, 0x2,  C0|C1, "macro_insts.cisc_decoded" },              \
9678425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xAA, 0x3,  C0|C1, "macro_insts.all_decoded" },               \
9688425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xB0, 0x0,  C0|C1, "simd_uops_exec.s" },                      \
9698425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xB0, 0x80, C0|C1, "simd_uops_exec.ar" },                     \
9708425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xB1, 0x0,  C0|C1, "simd_sat_uop_exec.s" },                   \
9718425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xB1, 0x80, C0|C1, "simd_sat_uop_exec.ar" },                  \
9728425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xB3, 0x1,  C0|C1, "simd_uop_type_exec.mul.s" },              \
9738425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xB3, 0x81, C0|C1, "simd_uop_type_exec.mul.ar" },             \
9748425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xB3, 0x02, C0|C1, "simd_uop_type_exec.shift.s" },            \
9758425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xB3, 0x82, C0|C1, "simd_uop_type_exec.shift.ar" },           \
9768425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xB3, 0x04, C0|C1, "simd_uop_type_exec.pack.s" },             \
9778425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xB3, 0x84, C0|C1, "simd_uop_type_exec.pack.ar" },            \
9788425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xB3, 0x08, C0|C1, "simd_uop_type_exec.unpack.s" },           \
9798425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xB3, 0x88, C0|C1, "simd_uop_type_exec.unpack.ar" },          \
9808425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xB3, 0x10, C0|C1, "simd_uop_type_exec.logical.s" },          \
9818425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xB3, 0x90, C0|C1, "simd_uop_type_exec.logical.ar" },         \
9828425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xB3, 0x20, C0|C1, "simd_uop_type_exec.arithmetic.s" },       \
9838425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xB3, 0xA0, C0|C1, "simd_uop_type_exec.arithmetic.ar" },      \
9848425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC2, 0x10, C0|C1, "uops_retired.any" },                      \
9858425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC3, 0x1,  C0|C1, "machine_clears.smc" },                    \
9868425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC4, 0x0,  C0|C1, "br_inst_retired.any" },                   \
9878425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC4, 0x1,  C0|C1, "br_inst_retired.pred_not_taken" },        \
9888425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC4, 0x2,  C0|C1, "br_inst_retired.mispred_not_taken" },     \
9898425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC4, 0x4,  C0|C1, "br_inst_retired.pred_taken" },            \
9908425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC4, 0x8,  C0|C1, "br_inst_retired.mispred_taken" },         \
9918425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC4, 0xA,  C0|C1, "br_inst_retired.mispred" },               \
9928425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC4, 0xC,  C0|C1, "br_inst_retired.taken" },                 \
9938425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC4, 0xF,  C0|C1, "br_inst_retired.any1" },                  \
9948425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC6, 0x1,  C0|C1, "cycles_int_masked.cycles_int_masked" },   \
9958425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC6, 0x2,  C0|C1,						\
9968425SKrishnendu.Sadhukhan@Sun.COM 		"cycles_int_masked.cycles_int_pending_and_masked" },	\
9978425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC7, 0x1,  C0|C1, "simd_inst_retired.packed_single" },       \
9988425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC7, 0x2,  C0|C1, "simd_inst_retired.scalar_single" },      	\
9998425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC7, 0x4,  C0|C1, "simd_inst_retired.packed_double" },       \
10008425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC7, 0x8,  C0|C1, "simd_inst_retired.scalar_double" },       \
10018425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC7, 0x10, C0|C1, "simd_inst_retired.vector" },              \
10028425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC7, 0x1F, C0|C1, "simd_inst_retired.any" },                 \
10038425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xC8, 0x00, C0|C1, "hw_int_rcv" },                            \
10048425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xCA, 0x1,  C0|C1, "simd_comp_inst_retired.packed_single" },  \
10058425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xCA, 0x2,  C0|C1, "simd_comp_inst_retired.scalar_single" }, 	\
10068425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xCA, 0x4,  C0|C1, "simd_comp_inst_retired.packed_double" },  \
10078425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xCA, 0x8,  C0|C1, "simd_comp_inst_retired.scalar_double" },  \
10088425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xCB, 0x1,  C0|C1, "mem_load_retired.l2_hit" },               \
10098425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xCB, 0x2,  C0|C1, "mem_load_retired.l2_miss" },              \
10108425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xCB, 0x4,  C0|C1, "mem_load_retired.dtlb_miss" },           	\
10118425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xCD, 0x0,  C0|C1, "simd_assist" },                           \
10128425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xCE, 0x0,  C0|C1, "simd_instr_retired" },                    \
10138425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xCF, 0x0,  C0|C1, "simd_sat_instr_retired" },                \
10148425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xE0, 0x1,  C0|C1, "br_inst_decoded" },                       \
10158425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xE4, 0x1,  C0|C1, "bogus_br" },                             	\
10168425SKrishnendu.Sadhukhan@Sun.COM 	{ 0xE6, 0x1,  C0|C1, "baclears.any" }
10177728SKuriakose.Kuruvilla@Sun.COM 
10187728SKuriakose.Kuruvilla@Sun.COM static const struct events_table_t *events_table = NULL;
10197728SKuriakose.Kuruvilla@Sun.COM 
102011625SKuriakose.Kuruvilla@Sun.COM const struct events_table_t events_fam6_nhm[] = {
102111625SKuriakose.Kuruvilla@Sun.COM 	GENERICEVENTS_FAM6_NHM,
102211625SKuriakose.Kuruvilla@Sun.COM 	EVENTS_FAM6_NHM,
10237728SKuriakose.Kuruvilla@Sun.COM 	{ NT_END, 0, 0, "" }
10247728SKuriakose.Kuruvilla@Sun.COM };
10257728SKuriakose.Kuruvilla@Sun.COM 
10268425SKrishnendu.Sadhukhan@Sun.COM const struct events_table_t events_fam6_mod28[] = {
102711261SKuriakose.Kuruvilla@Sun.COM 	GENERICEVENTS_FAM6_MOD28,
10288425SKrishnendu.Sadhukhan@Sun.COM 	EVENTS_FAM6_MOD28,
10298425SKrishnendu.Sadhukhan@Sun.COM 	{ NT_END, 0, 0, "" }
10308425SKrishnendu.Sadhukhan@Sun.COM };
10318425SKrishnendu.Sadhukhan@Sun.COM 
10327728SKuriakose.Kuruvilla@Sun.COM /*
10337728SKuriakose.Kuruvilla@Sun.COM  * Initialize string containing list of supported general-purpose counter
10348720SKuriakose.Kuruvilla@Sun.COM  * events for processors of Penryn and Merom Family
10357728SKuriakose.Kuruvilla@Sun.COM  */
10367728SKuriakose.Kuruvilla@Sun.COM static void
pcbe_init_core_uarch()10378720SKuriakose.Kuruvilla@Sun.COM pcbe_init_core_uarch()
10387728SKuriakose.Kuruvilla@Sun.COM {
10398720SKuriakose.Kuruvilla@Sun.COM 	const struct nametable_core_uarch	*n;
104011261SKuriakose.Kuruvilla@Sun.COM 	const struct generic_events		*k;
10418720SKuriakose.Kuruvilla@Sun.COM 	const struct nametable_core_uarch	*picspecific_events;
104211261SKuriakose.Kuruvilla@Sun.COM 	const struct generic_events		*picspecific_genericevents;
10437728SKuriakose.Kuruvilla@Sun.COM 	size_t			common_size;
10447728SKuriakose.Kuruvilla@Sun.COM 	size_t			size;
10457728SKuriakose.Kuruvilla@Sun.COM 	uint64_t		i;
10467728SKuriakose.Kuruvilla@Sun.COM 
10477728SKuriakose.Kuruvilla@Sun.COM 	gpc_names = kmem_alloc(num_gpc * sizeof (char *), KM_SLEEP);
10487728SKuriakose.Kuruvilla@Sun.COM 
10497728SKuriakose.Kuruvilla@Sun.COM 	/* Calculate space needed to save all the common event names */
10507728SKuriakose.Kuruvilla@Sun.COM 	common_size = 0;
10518720SKuriakose.Kuruvilla@Sun.COM 	for (n = cmn_gpc_events_core_uarch; n->event_num != NT_END; n++) {
10527728SKuriakose.Kuruvilla@Sun.COM 		common_size += strlen(n->name) + 1;
10537728SKuriakose.Kuruvilla@Sun.COM 	}
10547728SKuriakose.Kuruvilla@Sun.COM 
105511261SKuriakose.Kuruvilla@Sun.COM 	for (k = cmn_generic_events; k->event_num != NT_END; k++) {
105611261SKuriakose.Kuruvilla@Sun.COM 		common_size += strlen(k->name) + 1;
105711261SKuriakose.Kuruvilla@Sun.COM 	}
105811261SKuriakose.Kuruvilla@Sun.COM 
10597728SKuriakose.Kuruvilla@Sun.COM 	for (i = 0; i < num_gpc; i++) {
10607728SKuriakose.Kuruvilla@Sun.COM 		size = 0;
106111261SKuriakose.Kuruvilla@Sun.COM 		picspecific_genericevents = NULL;
106211261SKuriakose.Kuruvilla@Sun.COM 
10637728SKuriakose.Kuruvilla@Sun.COM 		switch (i) {
10647728SKuriakose.Kuruvilla@Sun.COM 			case 0:
10657728SKuriakose.Kuruvilla@Sun.COM 				picspecific_events = pic0_events;
106611261SKuriakose.Kuruvilla@Sun.COM 				picspecific_genericevents = generic_events_pic0;
10677728SKuriakose.Kuruvilla@Sun.COM 				break;
10687728SKuriakose.Kuruvilla@Sun.COM 			case 1:
10697728SKuriakose.Kuruvilla@Sun.COM 				picspecific_events = pic1_events;
10707728SKuriakose.Kuruvilla@Sun.COM 				break;
10717728SKuriakose.Kuruvilla@Sun.COM 			default:
10727728SKuriakose.Kuruvilla@Sun.COM 				picspecific_events = NULL;
10737728SKuriakose.Kuruvilla@Sun.COM 				break;
10747728SKuriakose.Kuruvilla@Sun.COM 		}
10757728SKuriakose.Kuruvilla@Sun.COM 		if (picspecific_events != NULL) {
10767728SKuriakose.Kuruvilla@Sun.COM 			for (n = picspecific_events;
10777728SKuriakose.Kuruvilla@Sun.COM 			    n->event_num != NT_END;
10787728SKuriakose.Kuruvilla@Sun.COM 			    n++) {
10797728SKuriakose.Kuruvilla@Sun.COM 				size += strlen(n->name) + 1;
10807728SKuriakose.Kuruvilla@Sun.COM 			}
10817728SKuriakose.Kuruvilla@Sun.COM 		}
108211261SKuriakose.Kuruvilla@Sun.COM 		if (picspecific_genericevents != NULL) {
108311261SKuriakose.Kuruvilla@Sun.COM 			for (k = picspecific_genericevents;
108411261SKuriakose.Kuruvilla@Sun.COM 			    k->event_num != NT_END; k++) {
108511261SKuriakose.Kuruvilla@Sun.COM 				size += strlen(k->name) + 1;
108611261SKuriakose.Kuruvilla@Sun.COM 			}
108711261SKuriakose.Kuruvilla@Sun.COM 		}
10887728SKuriakose.Kuruvilla@Sun.COM 
10897728SKuriakose.Kuruvilla@Sun.COM 		gpc_names[i] =
10907728SKuriakose.Kuruvilla@Sun.COM 		    kmem_alloc(size + common_size + 1, KM_SLEEP);
10917728SKuriakose.Kuruvilla@Sun.COM 
10927728SKuriakose.Kuruvilla@Sun.COM 		gpc_names[i][0] = '\0';
10937728SKuriakose.Kuruvilla@Sun.COM 		if (picspecific_events != NULL) {
10947728SKuriakose.Kuruvilla@Sun.COM 			for (n = picspecific_events;
109511261SKuriakose.Kuruvilla@Sun.COM 			    n->event_num != NT_END; n++) {
10967728SKuriakose.Kuruvilla@Sun.COM 				(void) strcat(gpc_names[i], n->name);
10977728SKuriakose.Kuruvilla@Sun.COM 				(void) strcat(gpc_names[i], ",");
10987728SKuriakose.Kuruvilla@Sun.COM 			}
10997728SKuriakose.Kuruvilla@Sun.COM 		}
110011261SKuriakose.Kuruvilla@Sun.COM 		if (picspecific_genericevents != NULL) {
110111261SKuriakose.Kuruvilla@Sun.COM 			for (k = picspecific_genericevents;
110211261SKuriakose.Kuruvilla@Sun.COM 			    k->event_num != NT_END; k++) {
110311261SKuriakose.Kuruvilla@Sun.COM 				(void) strcat(gpc_names[i], k->name);
110411261SKuriakose.Kuruvilla@Sun.COM 				(void) strcat(gpc_names[i], ",");
110511261SKuriakose.Kuruvilla@Sun.COM 			}
110611261SKuriakose.Kuruvilla@Sun.COM 		}
11078720SKuriakose.Kuruvilla@Sun.COM 		for (n = cmn_gpc_events_core_uarch; n->event_num != NT_END;
11087728SKuriakose.Kuruvilla@Sun.COM 		    n++) {
11097728SKuriakose.Kuruvilla@Sun.COM 			(void) strcat(gpc_names[i], n->name);
11107728SKuriakose.Kuruvilla@Sun.COM 			(void) strcat(gpc_names[i], ",");
11117728SKuriakose.Kuruvilla@Sun.COM 		}
111211261SKuriakose.Kuruvilla@Sun.COM 		for (k = cmn_generic_events; k->event_num != NT_END; k++) {
111311261SKuriakose.Kuruvilla@Sun.COM 			(void) strcat(gpc_names[i], k->name);
111411261SKuriakose.Kuruvilla@Sun.COM 			(void) strcat(gpc_names[i], ",");
111511261SKuriakose.Kuruvilla@Sun.COM 		}
111611261SKuriakose.Kuruvilla@Sun.COM 
11177728SKuriakose.Kuruvilla@Sun.COM 		/*
11187728SKuriakose.Kuruvilla@Sun.COM 		 * Remove trailing comma.
11197728SKuriakose.Kuruvilla@Sun.COM 		 */
11207728SKuriakose.Kuruvilla@Sun.COM 		gpc_names[i][common_size + size - 1] = '\0';
11217728SKuriakose.Kuruvilla@Sun.COM 	}
11227728SKuriakose.Kuruvilla@Sun.COM }
11237728SKuriakose.Kuruvilla@Sun.COM 
11246840Skk208521 static int
core_pcbe_init(void)11256840Skk208521 core_pcbe_init(void)
11266840Skk208521 {
11276840Skk208521 	struct cpuid_regs	cp;
11286840Skk208521 	size_t			size;
11296840Skk208521 	uint64_t		i;
11307728SKuriakose.Kuruvilla@Sun.COM 	uint64_t		j;
11317728SKuriakose.Kuruvilla@Sun.COM 	uint64_t		arch_events_vector_length;
11327728SKuriakose.Kuruvilla@Sun.COM 	size_t			arch_events_string_length;
113311625SKuriakose.Kuruvilla@Sun.COM 	uint_t			model;
11347728SKuriakose.Kuruvilla@Sun.COM 
11357728SKuriakose.Kuruvilla@Sun.COM 	if (cpuid_getvendor(CPU) != X86_VENDOR_Intel)
11367728SKuriakose.Kuruvilla@Sun.COM 		return (-1);
11376840Skk208521 
11387728SKuriakose.Kuruvilla@Sun.COM 	/* Obtain Basic CPUID information */
11397728SKuriakose.Kuruvilla@Sun.COM 	cp.cp_eax = 0x0;
11407728SKuriakose.Kuruvilla@Sun.COM 	(void) __cpuid_insn(&cp);
11417728SKuriakose.Kuruvilla@Sun.COM 
11427728SKuriakose.Kuruvilla@Sun.COM 	/* No Architectural Performance Monitoring Leaf returned by CPUID */
11437728SKuriakose.Kuruvilla@Sun.COM 	if (cp.cp_eax < 0xa) {
11446840Skk208521 		return (-1);
11457728SKuriakose.Kuruvilla@Sun.COM 	}
11466840Skk208521 
11476840Skk208521 	/* Obtain the Architectural Performance Monitoring Leaf */
11486840Skk208521 	cp.cp_eax = 0xa;
11496840Skk208521 	(void) __cpuid_insn(&cp);
11506840Skk208521 
11516840Skk208521 	versionid = cp.cp_eax & 0xFF;
11526840Skk208521 
11536840Skk208521 	/*
11548425SKrishnendu.Sadhukhan@Sun.COM 	 * Fixed-Function Counters (FFC)
11558425SKrishnendu.Sadhukhan@Sun.COM 	 *
11566840Skk208521 	 * All Family 6 Model 15 and Model 23 processors have fixed-function
11576840Skk208521 	 * counters.  These counters were made Architectural with
11587728SKuriakose.Kuruvilla@Sun.COM 	 * Family 6 Model 15 Stepping 9.
11596840Skk208521 	 */
11606840Skk208521 	switch (versionid) {
11616840Skk208521 
11626840Skk208521 		case 0:
11636840Skk208521 			return (-1);
11646840Skk208521 
11657728SKuriakose.Kuruvilla@Sun.COM 		case 2:
11666840Skk208521 			num_ffc = cp.cp_edx & 0x1F;
11676840Skk208521 			width_ffc = (cp.cp_edx >> 5) & 0xFF;
11686840Skk208521 
11697728SKuriakose.Kuruvilla@Sun.COM 			/*
11707728SKuriakose.Kuruvilla@Sun.COM 			 * Some processors have an errata (AW34) where
11717728SKuriakose.Kuruvilla@Sun.COM 			 * versionid is reported as 2 when actually 1.
11727728SKuriakose.Kuruvilla@Sun.COM 			 * In this case, fixed-function counters are
11737728SKuriakose.Kuruvilla@Sun.COM 			 * model-specific as in Version 1.
11747728SKuriakose.Kuruvilla@Sun.COM 			 */
11757728SKuriakose.Kuruvilla@Sun.COM 			if (num_ffc != 0) {
11767728SKuriakose.Kuruvilla@Sun.COM 				break;
11776840Skk208521 			}
11787728SKuriakose.Kuruvilla@Sun.COM 			/* FALLTHROUGH */
11797728SKuriakose.Kuruvilla@Sun.COM 		case 1:
11807728SKuriakose.Kuruvilla@Sun.COM 			num_ffc = 3;
11817728SKuriakose.Kuruvilla@Sun.COM 			width_ffc = 40;
11827728SKuriakose.Kuruvilla@Sun.COM 			versionid = 1;
11836840Skk208521 			break;
11846840Skk208521 
11856840Skk208521 		default:
11867728SKuriakose.Kuruvilla@Sun.COM 			num_ffc = cp.cp_edx & 0x1F;
11877728SKuriakose.Kuruvilla@Sun.COM 			width_ffc = (cp.cp_edx >> 5) & 0xFF;
11886840Skk208521 			break;
11896840Skk208521 	}
11906840Skk208521 
11917728SKuriakose.Kuruvilla@Sun.COM 
11926840Skk208521 	if (num_ffc >= 64)
11936840Skk208521 		return (-1);
11946840Skk208521 
11958146SKrishnendu.Sadhukhan@Sun.COM 	/* Set HTT-specific names of architectural & FFC events */
119612826Skuriakose.kuruvilla@oracle.com 	if (is_x86_feature(x86_featureset, X86FSET_HTT)) {
11978146SKrishnendu.Sadhukhan@Sun.COM 		ffc_names = ffc_names_htt;
11988146SKrishnendu.Sadhukhan@Sun.COM 		arch_events_table = arch_events_table_htt;
11998146SKrishnendu.Sadhukhan@Sun.COM 		known_arch_events =
12008146SKrishnendu.Sadhukhan@Sun.COM 		    sizeof (arch_events_table_htt) /
12018146SKrishnendu.Sadhukhan@Sun.COM 		    sizeof (struct events_table_t);
12028146SKrishnendu.Sadhukhan@Sun.COM 		known_ffc_num =
12038146SKrishnendu.Sadhukhan@Sun.COM 		    sizeof (ffc_names_htt) / sizeof (char *);
12048146SKrishnendu.Sadhukhan@Sun.COM 	} else {
12058146SKrishnendu.Sadhukhan@Sun.COM 		ffc_names = ffc_names_non_htt;
12068146SKrishnendu.Sadhukhan@Sun.COM 		arch_events_table = arch_events_table_non_htt;
12078146SKrishnendu.Sadhukhan@Sun.COM 		known_arch_events =
12088146SKrishnendu.Sadhukhan@Sun.COM 		    sizeof (arch_events_table_non_htt) /
12098146SKrishnendu.Sadhukhan@Sun.COM 		    sizeof (struct events_table_t);
12108146SKrishnendu.Sadhukhan@Sun.COM 		known_ffc_num =
12118146SKrishnendu.Sadhukhan@Sun.COM 		    sizeof (ffc_names_non_htt) / sizeof (char *);
12128146SKrishnendu.Sadhukhan@Sun.COM 	}
12138146SKrishnendu.Sadhukhan@Sun.COM 
12148146SKrishnendu.Sadhukhan@Sun.COM 	if (num_ffc >= known_ffc_num) {
12156840Skk208521 		/*
12166840Skk208521 		 * The system seems to have more fixed-function counters than
12176840Skk208521 		 * what this PCBE is able to handle correctly.  Default to the
12186840Skk208521 		 * maximum number of fixed-function counters that this driver
12196840Skk208521 		 * is aware of.
12206840Skk208521 		 */
12218146SKrishnendu.Sadhukhan@Sun.COM 		num_ffc = known_ffc_num - 1;
12226840Skk208521 	}
12236840Skk208521 
12246840Skk208521 	mask_ffc = BITMASK_XBITS(width_ffc);
12258425SKrishnendu.Sadhukhan@Sun.COM 	control_ffc = BITMASK_XBITS(num_ffc);
12266840Skk208521 
12278425SKrishnendu.Sadhukhan@Sun.COM 	/*
12288425SKrishnendu.Sadhukhan@Sun.COM 	 * General Purpose Counters (GPC)
12298425SKrishnendu.Sadhukhan@Sun.COM 	 */
12306840Skk208521 	num_gpc = (cp.cp_eax >> 8) & 0xFF;
12316840Skk208521 	width_gpc = (cp.cp_eax >> 16) & 0xFF;
12326840Skk208521 
12336840Skk208521 	if (num_gpc >= 64)
12346840Skk208521 		return (-1);
12356840Skk208521 
12366840Skk208521 	mask_gpc = BITMASK_XBITS(width_gpc);
12376840Skk208521 
12386840Skk208521 	control_gpc = BITMASK_XBITS(num_gpc);
12396840Skk208521 
12406840Skk208521 	control_mask = (control_ffc << 32) | control_gpc;
12416840Skk208521 
12428425SKrishnendu.Sadhukhan@Sun.COM 	total_pmc = num_gpc + num_ffc;
12436840Skk208521 	if (total_pmc > 64) {
12446840Skk208521 		/* Too wide for the overflow bitmap */
12456840Skk208521 		return (-1);
12466840Skk208521 	}
12476840Skk208521 
124811261SKuriakose.Kuruvilla@Sun.COM 	/* FFC names */
124911261SKuriakose.Kuruvilla@Sun.COM 	ffc_allnames = kmem_alloc(num_ffc * sizeof (char *), KM_SLEEP);
125011261SKuriakose.Kuruvilla@Sun.COM 	for (i = 0; i < num_ffc; i++) {
125111261SKuriakose.Kuruvilla@Sun.COM 		ffc_allnames[i] = kmem_alloc(
125211261SKuriakose.Kuruvilla@Sun.COM 		    strlen(ffc_names[i]) + strlen(ffc_genericnames[i]) + 2,
125311261SKuriakose.Kuruvilla@Sun.COM 		    KM_SLEEP);
125411261SKuriakose.Kuruvilla@Sun.COM 
125511261SKuriakose.Kuruvilla@Sun.COM 		ffc_allnames[i][0] = '\0';
125611261SKuriakose.Kuruvilla@Sun.COM 		(void) strcat(ffc_allnames[i], ffc_names[i]);
125711261SKuriakose.Kuruvilla@Sun.COM 
125811261SKuriakose.Kuruvilla@Sun.COM 		/* Check if this ffc has a generic name */
125911261SKuriakose.Kuruvilla@Sun.COM 		if (strcmp(ffc_genericnames[i], "") != 0) {
126011261SKuriakose.Kuruvilla@Sun.COM 			(void) strcat(ffc_allnames[i], ",");
126111261SKuriakose.Kuruvilla@Sun.COM 			(void) strcat(ffc_allnames[i], ffc_genericnames[i]);
126211261SKuriakose.Kuruvilla@Sun.COM 		}
126311261SKuriakose.Kuruvilla@Sun.COM 	}
126411261SKuriakose.Kuruvilla@Sun.COM 
126511261SKuriakose.Kuruvilla@Sun.COM 	/* GPC events for Family 6 Models 15, 23 and 29 only */
12667728SKuriakose.Kuruvilla@Sun.COM 	if ((cpuid_getfamily(CPU) == 6) &&
12678720SKuriakose.Kuruvilla@Sun.COM 	    ((cpuid_getmodel(CPU) == 15) || (cpuid_getmodel(CPU) == 23) ||
12688720SKuriakose.Kuruvilla@Sun.COM 	    (cpuid_getmodel(CPU) == 29))) {
12697728SKuriakose.Kuruvilla@Sun.COM 		(void) snprintf(core_impl_name, IMPL_NAME_LEN,
12707728SKuriakose.Kuruvilla@Sun.COM 		    "Core Microarchitecture");
12718720SKuriakose.Kuruvilla@Sun.COM 		pcbe_init_core_uarch();
12727728SKuriakose.Kuruvilla@Sun.COM 		return (0);
12737728SKuriakose.Kuruvilla@Sun.COM 	}
12747728SKuriakose.Kuruvilla@Sun.COM 
12757728SKuriakose.Kuruvilla@Sun.COM 	(void) snprintf(core_impl_name, IMPL_NAME_LEN,
12767728SKuriakose.Kuruvilla@Sun.COM 	    "Intel Arch PerfMon v%d on Family %d Model %d",
12777728SKuriakose.Kuruvilla@Sun.COM 	    versionid, cpuid_getfamily(CPU), cpuid_getmodel(CPU));
12787728SKuriakose.Kuruvilla@Sun.COM 
12798425SKrishnendu.Sadhukhan@Sun.COM 	/*
12808425SKrishnendu.Sadhukhan@Sun.COM 	 * Architectural events
12818425SKrishnendu.Sadhukhan@Sun.COM 	 */
12827728SKuriakose.Kuruvilla@Sun.COM 	arch_events_vector_length = (cp.cp_eax >> 24) & 0xFF;
12837728SKuriakose.Kuruvilla@Sun.COM 
12847728SKuriakose.Kuruvilla@Sun.COM 	ASSERT(known_arch_events == arch_events_vector_length);
12857728SKuriakose.Kuruvilla@Sun.COM 
12867728SKuriakose.Kuruvilla@Sun.COM 	/*
12877728SKuriakose.Kuruvilla@Sun.COM 	 * To handle the case where a new performance monitoring setup is run
12887728SKuriakose.Kuruvilla@Sun.COM 	 * on a non-debug kernel
12897728SKuriakose.Kuruvilla@Sun.COM 	 */
12907728SKuriakose.Kuruvilla@Sun.COM 	if (known_arch_events > arch_events_vector_length) {
12917728SKuriakose.Kuruvilla@Sun.COM 		known_arch_events = arch_events_vector_length;
12927728SKuriakose.Kuruvilla@Sun.COM 	} else {
12937728SKuriakose.Kuruvilla@Sun.COM 		arch_events_vector_length = known_arch_events;
12947728SKuriakose.Kuruvilla@Sun.COM 	}
12957728SKuriakose.Kuruvilla@Sun.COM 
12967728SKuriakose.Kuruvilla@Sun.COM 	arch_events_vector = cp.cp_ebx &
12977728SKuriakose.Kuruvilla@Sun.COM 	    BITMASK_XBITS(arch_events_vector_length);
12987728SKuriakose.Kuruvilla@Sun.COM 
12998425SKrishnendu.Sadhukhan@Sun.COM 	/*
13008425SKrishnendu.Sadhukhan@Sun.COM 	 * Process architectural and non-architectural events using GPC
13018425SKrishnendu.Sadhukhan@Sun.COM 	 */
13026840Skk208521 	if (num_gpc > 0) {
13037728SKuriakose.Kuruvilla@Sun.COM 
13046840Skk208521 		gpc_names = kmem_alloc(num_gpc * sizeof (char *), KM_SLEEP);
13056840Skk208521 
13067728SKuriakose.Kuruvilla@Sun.COM 		/* Calculate space required for the architectural gpc events */
13077728SKuriakose.Kuruvilla@Sun.COM 		arch_events_string_length = 0;
13087728SKuriakose.Kuruvilla@Sun.COM 		for (i = 0; i < known_arch_events; i++) {
13097728SKuriakose.Kuruvilla@Sun.COM 			if (((1U << i) & arch_events_vector) == 0) {
13107728SKuriakose.Kuruvilla@Sun.COM 				arch_events_string_length +=
13117728SKuriakose.Kuruvilla@Sun.COM 				    strlen(arch_events_table[i].name) + 1;
131211261SKuriakose.Kuruvilla@Sun.COM 				if (strcmp(arch_genevents_table[i], "") != 0) {
131311261SKuriakose.Kuruvilla@Sun.COM 					arch_events_string_length +=
131411261SKuriakose.Kuruvilla@Sun.COM 					    strlen(arch_genevents_table[i]) + 1;
131511261SKuriakose.Kuruvilla@Sun.COM 				}
13167728SKuriakose.Kuruvilla@Sun.COM 			}
13177728SKuriakose.Kuruvilla@Sun.COM 		}
13187728SKuriakose.Kuruvilla@Sun.COM 
13198425SKrishnendu.Sadhukhan@Sun.COM 		/* Non-architectural events list */
132011625SKuriakose.Kuruvilla@Sun.COM 		model = cpuid_getmodel(CPU);
132111625SKuriakose.Kuruvilla@Sun.COM 		switch (model) {
132211625SKuriakose.Kuruvilla@Sun.COM 			/* Nehalem */
132311625SKuriakose.Kuruvilla@Sun.COM 			case 26:
132411625SKuriakose.Kuruvilla@Sun.COM 			case 30:
132511625SKuriakose.Kuruvilla@Sun.COM 			case 31:
132611625SKuriakose.Kuruvilla@Sun.COM 			/* Westmere */
132711625SKuriakose.Kuruvilla@Sun.COM 			case 37:
132811625SKuriakose.Kuruvilla@Sun.COM 			case 44:
132911625SKuriakose.Kuruvilla@Sun.COM 			/* Nehalem-EX */
133011625SKuriakose.Kuruvilla@Sun.COM 			case 46:
133112759SAdrian.Frost@Sun.COM 			case 47:
133211625SKuriakose.Kuruvilla@Sun.COM 				events_table = events_fam6_nhm;
133311625SKuriakose.Kuruvilla@Sun.COM 				break;
133411625SKuriakose.Kuruvilla@Sun.COM 			case 28:
133511625SKuriakose.Kuruvilla@Sun.COM 				events_table = events_fam6_mod28;
133611625SKuriakose.Kuruvilla@Sun.COM 				break;
13376840Skk208521 		}
13386840Skk208521 
13396840Skk208521 		for (i = 0; i < num_gpc; i++) {
13407728SKuriakose.Kuruvilla@Sun.COM 
13418425SKrishnendu.Sadhukhan@Sun.COM 			/*
13428425SKrishnendu.Sadhukhan@Sun.COM 			 * Determine length of all supported event names
13438425SKrishnendu.Sadhukhan@Sun.COM 			 * (architectural + non-architectural)
13448425SKrishnendu.Sadhukhan@Sun.COM 			 */
13457728SKuriakose.Kuruvilla@Sun.COM 			size = arch_events_string_length;
13467728SKuriakose.Kuruvilla@Sun.COM 			for (j = 0; events_table != NULL &&
13477728SKuriakose.Kuruvilla@Sun.COM 			    events_table[j].eventselect != NT_END;
13487728SKuriakose.Kuruvilla@Sun.COM 			    j++) {
13497728SKuriakose.Kuruvilla@Sun.COM 				if (C(i) & events_table[j].supported_counters) {
13507728SKuriakose.Kuruvilla@Sun.COM 					size += strlen(events_table[j].name) +
13517728SKuriakose.Kuruvilla@Sun.COM 					    1;
13526840Skk208521 				}
13536840Skk208521 			}
13546840Skk208521 
13557728SKuriakose.Kuruvilla@Sun.COM 			/* Allocate memory for this pics list */
13567728SKuriakose.Kuruvilla@Sun.COM 			gpc_names[i] = kmem_alloc(size + 1, KM_SLEEP);
13576840Skk208521 			gpc_names[i][0] = '\0';
13587728SKuriakose.Kuruvilla@Sun.COM 			if (size == 0) {
13597728SKuriakose.Kuruvilla@Sun.COM 				continue;
13607728SKuriakose.Kuruvilla@Sun.COM 			}
13617728SKuriakose.Kuruvilla@Sun.COM 
13628425SKrishnendu.Sadhukhan@Sun.COM 			/*
13638425SKrishnendu.Sadhukhan@Sun.COM 			 * Create the list of all supported events
13648425SKrishnendu.Sadhukhan@Sun.COM 			 * (architectural + non-architectural)
13658425SKrishnendu.Sadhukhan@Sun.COM 			 */
13667728SKuriakose.Kuruvilla@Sun.COM 			for (j = 0; j < known_arch_events; j++) {
13677728SKuriakose.Kuruvilla@Sun.COM 				if (((1U << j) & arch_events_vector) == 0) {
13687728SKuriakose.Kuruvilla@Sun.COM 					(void) strcat(gpc_names[i],
13697728SKuriakose.Kuruvilla@Sun.COM 					    arch_events_table[j].name);
13706840Skk208521 					(void) strcat(gpc_names[i], ",");
137111261SKuriakose.Kuruvilla@Sun.COM 					if (strcmp(
137211261SKuriakose.Kuruvilla@Sun.COM 					    arch_genevents_table[j], "")
137311261SKuriakose.Kuruvilla@Sun.COM 					    != 0) {
137411261SKuriakose.Kuruvilla@Sun.COM 						(void) strcat(gpc_names[i],
137511261SKuriakose.Kuruvilla@Sun.COM 						    arch_genevents_table[j]);
137611261SKuriakose.Kuruvilla@Sun.COM 						(void) strcat(gpc_names[i],
137711261SKuriakose.Kuruvilla@Sun.COM 						    ",");
137811261SKuriakose.Kuruvilla@Sun.COM 					}
13796840Skk208521 				}
13806840Skk208521 			}
13817728SKuriakose.Kuruvilla@Sun.COM 
13827728SKuriakose.Kuruvilla@Sun.COM 			for (j = 0; events_table != NULL &&
13837728SKuriakose.Kuruvilla@Sun.COM 			    events_table[j].eventselect != NT_END;
13847728SKuriakose.Kuruvilla@Sun.COM 			    j++) {
13857728SKuriakose.Kuruvilla@Sun.COM 				if (C(i) & events_table[j].supported_counters) {
13867728SKuriakose.Kuruvilla@Sun.COM 					(void) strcat(gpc_names[i],
13877728SKuriakose.Kuruvilla@Sun.COM 					    events_table[j].name);
13887728SKuriakose.Kuruvilla@Sun.COM 					(void) strcat(gpc_names[i], ",");
13897728SKuriakose.Kuruvilla@Sun.COM 				}
13906840Skk208521 			}
13918425SKrishnendu.Sadhukhan@Sun.COM 
13928425SKrishnendu.Sadhukhan@Sun.COM 			/* Remove trailing comma */
13937728SKuriakose.Kuruvilla@Sun.COM 			gpc_names[i][size - 1] = '\0';
13946840Skk208521 		}
13956840Skk208521 	}
139611261SKuriakose.Kuruvilla@Sun.COM 
13976840Skk208521 	return (0);
13986840Skk208521 }
13996840Skk208521 
core_pcbe_ncounters()14006840Skk208521 static uint_t core_pcbe_ncounters()
14016840Skk208521 {
14026840Skk208521 	return (total_pmc);
14036840Skk208521 }
14046840Skk208521 
core_pcbe_impl_name(void)14056840Skk208521 static const char *core_pcbe_impl_name(void)
14066840Skk208521 {
14076840Skk208521 	return (core_impl_name);
14086840Skk208521 }
14096840Skk208521 
core_pcbe_cpuref(void)14106840Skk208521 static const char *core_pcbe_cpuref(void)
14116840Skk208521 {
14126840Skk208521 	return (core_cpuref);
14136840Skk208521 }
14146840Skk208521 
core_pcbe_list_events(uint_t picnum)14156840Skk208521 static char *core_pcbe_list_events(uint_t picnum)
14166840Skk208521 {
14176840Skk208521 	ASSERT(picnum < cpc_ncounters);
14186840Skk208521 
14196840Skk208521 	if (picnum < num_gpc) {
14206840Skk208521 		return (gpc_names[picnum]);
14216840Skk208521 	} else {
142211261SKuriakose.Kuruvilla@Sun.COM 		return (ffc_allnames[picnum - num_gpc]);
14236840Skk208521 	}
14246840Skk208521 }
14256840Skk208521 
core_pcbe_list_attrs(void)14266840Skk208521 static char *core_pcbe_list_attrs(void)
14276840Skk208521 {
14287728SKuriakose.Kuruvilla@Sun.COM 	if (versionid >= 3) {
14297728SKuriakose.Kuruvilla@Sun.COM 		return ("edge,inv,umask,cmask,anythr");
14307728SKuriakose.Kuruvilla@Sun.COM 	} else {
14317728SKuriakose.Kuruvilla@Sun.COM 		return ("edge,pc,inv,umask,cmask");
14327728SKuriakose.Kuruvilla@Sun.COM 	}
14336840Skk208521 }
14346840Skk208521 
14358720SKuriakose.Kuruvilla@Sun.COM static const struct nametable_core_uarch *
find_gpcevent_core_uarch(char * name,const struct nametable_core_uarch * nametable)14368720SKuriakose.Kuruvilla@Sun.COM find_gpcevent_core_uarch(char *name,
14378720SKuriakose.Kuruvilla@Sun.COM     const struct nametable_core_uarch *nametable)
14386840Skk208521 {
14398720SKuriakose.Kuruvilla@Sun.COM 	const struct nametable_core_uarch *n;
14408425SKrishnendu.Sadhukhan@Sun.COM 	int compare_result = -1;
14416840Skk208521 
14426840Skk208521 	for (n = nametable; n->event_num != NT_END; n++) {
14436840Skk208521 		compare_result = strcmp(name, n->name);
14446840Skk208521 		if (compare_result <= 0) {
14456840Skk208521 			break;
14466840Skk208521 		}
14476840Skk208521 	}
14486840Skk208521 
14496840Skk208521 	if (compare_result == 0) {
14506840Skk208521 		return (n);
14516840Skk208521 	}
14526840Skk208521 
14536840Skk208521 	return (NULL);
14546840Skk208521 }
14556840Skk208521 
145611261SKuriakose.Kuruvilla@Sun.COM static const struct generic_events *
find_generic_events(char * name,const struct generic_events * table)145711261SKuriakose.Kuruvilla@Sun.COM find_generic_events(char *name, const struct generic_events *table)
145811261SKuriakose.Kuruvilla@Sun.COM {
145911261SKuriakose.Kuruvilla@Sun.COM 	const struct generic_events *n;
146011261SKuriakose.Kuruvilla@Sun.COM 
146111261SKuriakose.Kuruvilla@Sun.COM 	for (n = table; n->event_num != NT_END; n++) {
146211261SKuriakose.Kuruvilla@Sun.COM 		if (strcmp(name, n->name) == 0) {
146311261SKuriakose.Kuruvilla@Sun.COM 			return (n);
146411261SKuriakose.Kuruvilla@Sun.COM 		};
146511261SKuriakose.Kuruvilla@Sun.COM 	}
146611261SKuriakose.Kuruvilla@Sun.COM 
146711261SKuriakose.Kuruvilla@Sun.COM 	return (NULL);
146811261SKuriakose.Kuruvilla@Sun.COM }
146911261SKuriakose.Kuruvilla@Sun.COM 
14707728SKuriakose.Kuruvilla@Sun.COM static const struct events_table_t *
find_gpcevent(char * name)14717728SKuriakose.Kuruvilla@Sun.COM find_gpcevent(char *name)
14727728SKuriakose.Kuruvilla@Sun.COM {
14737728SKuriakose.Kuruvilla@Sun.COM 	int i;
14747728SKuriakose.Kuruvilla@Sun.COM 
14758425SKrishnendu.Sadhukhan@Sun.COM 	/* Search architectural events */
14767728SKuriakose.Kuruvilla@Sun.COM 	for (i = 0; i < known_arch_events; i++) {
147711261SKuriakose.Kuruvilla@Sun.COM 		if (strcmp(name, arch_events_table[i].name) == 0 ||
147811261SKuriakose.Kuruvilla@Sun.COM 		    strcmp(name, arch_genevents_table[i]) == 0) {
14797728SKuriakose.Kuruvilla@Sun.COM 			if (((1U << i) & arch_events_vector) == 0) {
14807728SKuriakose.Kuruvilla@Sun.COM 				return (&arch_events_table[i]);
14817728SKuriakose.Kuruvilla@Sun.COM 			}
14827728SKuriakose.Kuruvilla@Sun.COM 		}
14837728SKuriakose.Kuruvilla@Sun.COM 	}
14847728SKuriakose.Kuruvilla@Sun.COM 
14858425SKrishnendu.Sadhukhan@Sun.COM 	/* Search non-architectural events */
14868425SKrishnendu.Sadhukhan@Sun.COM 	if (events_table != NULL) {
14878425SKrishnendu.Sadhukhan@Sun.COM 		for (i = 0; events_table[i].eventselect != NT_END; i++) {
14888425SKrishnendu.Sadhukhan@Sun.COM 			if (strcmp(name, events_table[i].name) == 0) {
14898425SKrishnendu.Sadhukhan@Sun.COM 				return (&events_table[i]);
14908425SKrishnendu.Sadhukhan@Sun.COM 			}
14917728SKuriakose.Kuruvilla@Sun.COM 		}
14927728SKuriakose.Kuruvilla@Sun.COM 	}
14937728SKuriakose.Kuruvilla@Sun.COM 
14947728SKuriakose.Kuruvilla@Sun.COM 	return (NULL);
14957728SKuriakose.Kuruvilla@Sun.COM }
149611261SKuriakose.Kuruvilla@Sun.COM 
14976840Skk208521 static uint64_t
core_pcbe_event_coverage(char * event)14986840Skk208521 core_pcbe_event_coverage(char *event)
14996840Skk208521 {
15006840Skk208521 	uint64_t bitmap;
15016840Skk208521 	uint64_t bitmask;
15027728SKuriakose.Kuruvilla@Sun.COM 	const struct events_table_t *n;
15036840Skk208521 	int i;
15046840Skk208521 
15056840Skk208521 	bitmap = 0;
15066840Skk208521 
15076840Skk208521 	/* Is it an event that a GPC can track? */
15087728SKuriakose.Kuruvilla@Sun.COM 	if (versionid >= 3) {
15097728SKuriakose.Kuruvilla@Sun.COM 		n = find_gpcevent(event);
15107728SKuriakose.Kuruvilla@Sun.COM 		if (n != NULL) {
15117728SKuriakose.Kuruvilla@Sun.COM 			bitmap |= (n->supported_counters &
15127728SKuriakose.Kuruvilla@Sun.COM 			    BITMASK_XBITS(num_gpc));
15137728SKuriakose.Kuruvilla@Sun.COM 		}
15147728SKuriakose.Kuruvilla@Sun.COM 	} else {
151511261SKuriakose.Kuruvilla@Sun.COM 		if (find_generic_events(event, cmn_generic_events) != NULL) {
151611261SKuriakose.Kuruvilla@Sun.COM 			bitmap |= BITMASK_XBITS(num_gpc);
151711261SKuriakose.Kuruvilla@Sun.COM 		} if (find_generic_events(event, generic_events_pic0) != NULL) {
151811261SKuriakose.Kuruvilla@Sun.COM 			bitmap |= 1ULL;
151911261SKuriakose.Kuruvilla@Sun.COM 		} else if (find_gpcevent_core_uarch(event,
152011261SKuriakose.Kuruvilla@Sun.COM 		    cmn_gpc_events_core_uarch) != NULL) {
15217728SKuriakose.Kuruvilla@Sun.COM 			bitmap |= BITMASK_XBITS(num_gpc);
15228720SKuriakose.Kuruvilla@Sun.COM 		} else if (find_gpcevent_core_uarch(event, pic0_events) !=
15238720SKuriakose.Kuruvilla@Sun.COM 		    NULL) {
15247728SKuriakose.Kuruvilla@Sun.COM 			bitmap |= 1ULL;
15258720SKuriakose.Kuruvilla@Sun.COM 		} else if (find_gpcevent_core_uarch(event, pic1_events) !=
15268720SKuriakose.Kuruvilla@Sun.COM 		    NULL) {
15277728SKuriakose.Kuruvilla@Sun.COM 			bitmap |= 1ULL << 1;
15287728SKuriakose.Kuruvilla@Sun.COM 		}
15296840Skk208521 	}
15306840Skk208521 
15316840Skk208521 	/* Check if the event can be counted in the fixed-function counters */
15326840Skk208521 	if (num_ffc > 0) {
15336840Skk208521 		bitmask = 1ULL << num_gpc;
15346840Skk208521 		for (i = 0; i < num_ffc; i++) {
15356840Skk208521 			if (strcmp(event, ffc_names[i]) == 0) {
15366840Skk208521 				bitmap |= bitmask;
153711261SKuriakose.Kuruvilla@Sun.COM 			} else if (strcmp(event, ffc_genericnames[i]) == 0) {
153811261SKuriakose.Kuruvilla@Sun.COM 				bitmap |= bitmask;
15396840Skk208521 			}
15406840Skk208521 			bitmask = bitmask << 1;
15416840Skk208521 		}
15426840Skk208521 	}
15436840Skk208521 
15446840Skk208521 	return (bitmap);
15456840Skk208521 }
15466840Skk208521 
15476840Skk208521 static uint64_t
core_pcbe_overflow_bitmap(void)15486840Skk208521 core_pcbe_overflow_bitmap(void)
15496840Skk208521 {
15506840Skk208521 	uint64_t interrupt_status;
15516840Skk208521 	uint64_t intrbits_ffc;
15526840Skk208521 	uint64_t intrbits_gpc;
15536840Skk208521 	extern int kcpc_hw_overflow_intr_installed;
15546840Skk208521 	uint64_t overflow_bitmap;
15556840Skk208521 
15566840Skk208521 	RDMSR(PERF_GLOBAL_STATUS, interrupt_status);
15576840Skk208521 	WRMSR(PERF_GLOBAL_OVF_CTRL, interrupt_status);
15586840Skk208521 
15596840Skk208521 	interrupt_status = interrupt_status & control_mask;
15606840Skk208521 	intrbits_ffc = (interrupt_status >> 32) & control_ffc;
15616840Skk208521 	intrbits_gpc = interrupt_status & control_gpc;
15626840Skk208521 	overflow_bitmap = (intrbits_ffc << num_gpc) | intrbits_gpc;
15636840Skk208521 
15646840Skk208521 	ASSERT(kcpc_hw_overflow_intr_installed);
15656840Skk208521 	(*kcpc_hw_enable_cpc_intr)();
15666840Skk208521 
15676840Skk208521 	return (overflow_bitmap);
15686840Skk208521 }
15696840Skk208521 
15706840Skk208521 static int
check_cpc_securitypolicy(core_pcbe_config_t * conf,const struct nametable_core_uarch * n)15717728SKuriakose.Kuruvilla@Sun.COM check_cpc_securitypolicy(core_pcbe_config_t *conf,
15728720SKuriakose.Kuruvilla@Sun.COM     const struct nametable_core_uarch *n)
15736840Skk208521 {
15746840Skk208521 	if (conf->core_ctl & n->restricted_bits) {
15756840Skk208521 		if (secpolicy_cpc_cpu(crgetcred()) != 0) {
15766840Skk208521 			return (CPC_ATTR_REQUIRES_PRIVILEGE);
15776840Skk208521 		}
15786840Skk208521 	}
15796840Skk208521 	return (0);
15806840Skk208521 }
15816840Skk208521 
15826840Skk208521 static int
configure_gpc(uint_t picnum,char * event,uint64_t preset,uint32_t flags,uint_t nattrs,kcpc_attr_t * attrs,void ** data)15836840Skk208521 configure_gpc(uint_t picnum, char *event, uint64_t preset, uint32_t flags,
15846840Skk208521     uint_t nattrs, kcpc_attr_t *attrs, void **data)
15856840Skk208521 {
15866840Skk208521 	core_pcbe_config_t	conf;
15878720SKuriakose.Kuruvilla@Sun.COM 	const struct nametable_core_uarch	*n;
158811261SKuriakose.Kuruvilla@Sun.COM 	const struct generic_events *k = NULL;
15898720SKuriakose.Kuruvilla@Sun.COM 	const struct nametable_core_uarch	*m;
15908720SKuriakose.Kuruvilla@Sun.COM 	const struct nametable_core_uarch	*picspecific_events;
15918720SKuriakose.Kuruvilla@Sun.COM 	struct nametable_core_uarch	nt_raw = { "", 0x0, 0x0 };
15926840Skk208521 	uint_t			i;
15936840Skk208521 	long			event_num;
15947728SKuriakose.Kuruvilla@Sun.COM 	const struct events_table_t *eventcode;
15956840Skk208521 
15966840Skk208521 	if (((preset & BITS_EXTENDED_FROM_31) != 0) &&
15976840Skk208521 	    ((preset & BITS_EXTENDED_FROM_31) !=
15986840Skk208521 	    BITS_EXTENDED_FROM_31)) {
15996840Skk208521 
16006840Skk208521 		/*
16016840Skk208521 		 * Bits beyond bit-31 in the general-purpose counters can only
16026840Skk208521 		 * be written to by extension of bit 31.  We cannot preset
16036840Skk208521 		 * these bits to any value other than all 1s or all 0s.
16046840Skk208521 		 */
16056840Skk208521 		return (CPC_ATTRIBUTE_OUT_OF_RANGE);
16066840Skk208521 	}
16076840Skk208521 
16087728SKuriakose.Kuruvilla@Sun.COM 	if (versionid >= 3) {
16097728SKuriakose.Kuruvilla@Sun.COM 		eventcode = find_gpcevent(event);
16107728SKuriakose.Kuruvilla@Sun.COM 		if (eventcode != NULL) {
16117728SKuriakose.Kuruvilla@Sun.COM 			if ((C(picnum) & eventcode->supported_counters) == 0) {
16127728SKuriakose.Kuruvilla@Sun.COM 				return (CPC_PIC_NOT_CAPABLE);
16137728SKuriakose.Kuruvilla@Sun.COM 			}
161411261SKuriakose.Kuruvilla@Sun.COM 			if (nattrs > 0 &&
161511261SKuriakose.Kuruvilla@Sun.COM 			    (strncmp("PAPI_", event, 5) == 0)) {
161611261SKuriakose.Kuruvilla@Sun.COM 				return (CPC_ATTRIBUTE_OUT_OF_RANGE);
161711261SKuriakose.Kuruvilla@Sun.COM 			}
16187728SKuriakose.Kuruvilla@Sun.COM 			conf.core_ctl = eventcode->eventselect;
16197728SKuriakose.Kuruvilla@Sun.COM 			conf.core_ctl |= eventcode->unitmask <<
16207728SKuriakose.Kuruvilla@Sun.COM 			    CORE_UMASK_SHIFT;
16217728SKuriakose.Kuruvilla@Sun.COM 		} else {
16227728SKuriakose.Kuruvilla@Sun.COM 			/* Event specified as raw event code */
16237728SKuriakose.Kuruvilla@Sun.COM 			if (ddi_strtol(event, NULL, 0, &event_num) != 0) {
16247728SKuriakose.Kuruvilla@Sun.COM 				return (CPC_INVALID_EVENT);
16257728SKuriakose.Kuruvilla@Sun.COM 			}
16267728SKuriakose.Kuruvilla@Sun.COM 			conf.core_ctl = event_num & 0xFF;
16276840Skk208521 		}
16287728SKuriakose.Kuruvilla@Sun.COM 	} else {
162911261SKuriakose.Kuruvilla@Sun.COM 		if ((k = find_generic_events(event, cmn_generic_events)) !=
163011261SKuriakose.Kuruvilla@Sun.COM 		    NULL ||
163111261SKuriakose.Kuruvilla@Sun.COM 		    (picnum == 0 &&
163211261SKuriakose.Kuruvilla@Sun.COM 		    (k = find_generic_events(event, generic_events_pic0)) !=
163311261SKuriakose.Kuruvilla@Sun.COM 		    NULL)) {
163411261SKuriakose.Kuruvilla@Sun.COM 			if (nattrs > 0) {
163511261SKuriakose.Kuruvilla@Sun.COM 				return (CPC_ATTRIBUTE_OUT_OF_RANGE);
16367728SKuriakose.Kuruvilla@Sun.COM 			}
163711261SKuriakose.Kuruvilla@Sun.COM 			conf.core_ctl = k->event_num;
163811261SKuriakose.Kuruvilla@Sun.COM 			conf.core_ctl |= k->umask << CORE_UMASK_SHIFT;
163911261SKuriakose.Kuruvilla@Sun.COM 		} else {
164011261SKuriakose.Kuruvilla@Sun.COM 			/* Not a generic event */
16417728SKuriakose.Kuruvilla@Sun.COM 
164211261SKuriakose.Kuruvilla@Sun.COM 			n = find_gpcevent_core_uarch(event,
164311261SKuriakose.Kuruvilla@Sun.COM 			    cmn_gpc_events_core_uarch);
164411261SKuriakose.Kuruvilla@Sun.COM 			if (n == NULL) {
164511261SKuriakose.Kuruvilla@Sun.COM 				switch (picnum) {
164611261SKuriakose.Kuruvilla@Sun.COM 					case 0:
164711261SKuriakose.Kuruvilla@Sun.COM 						picspecific_events =
164811261SKuriakose.Kuruvilla@Sun.COM 						    pic0_events;
164911261SKuriakose.Kuruvilla@Sun.COM 						break;
165011261SKuriakose.Kuruvilla@Sun.COM 					case 1:
165111261SKuriakose.Kuruvilla@Sun.COM 						picspecific_events =
165211261SKuriakose.Kuruvilla@Sun.COM 						    pic1_events;
165311261SKuriakose.Kuruvilla@Sun.COM 						break;
165411261SKuriakose.Kuruvilla@Sun.COM 					default:
165511261SKuriakose.Kuruvilla@Sun.COM 						picspecific_events = NULL;
165611261SKuriakose.Kuruvilla@Sun.COM 						break;
165711261SKuriakose.Kuruvilla@Sun.COM 				}
165811261SKuriakose.Kuruvilla@Sun.COM 				if (picspecific_events != NULL) {
165911261SKuriakose.Kuruvilla@Sun.COM 					n = find_gpcevent_core_uarch(event,
166011261SKuriakose.Kuruvilla@Sun.COM 					    picspecific_events);
16616840Skk208521 				}
16626840Skk208521 			}
166311261SKuriakose.Kuruvilla@Sun.COM 			if (n == NULL) {
166411261SKuriakose.Kuruvilla@Sun.COM 
166511261SKuriakose.Kuruvilla@Sun.COM 				/*
166611261SKuriakose.Kuruvilla@Sun.COM 				 * Check if this is a case where the event was
166711261SKuriakose.Kuruvilla@Sun.COM 				 * specified directly by its event number
166811261SKuriakose.Kuruvilla@Sun.COM 				 * instead of its name string.
166911261SKuriakose.Kuruvilla@Sun.COM 				 */
167011261SKuriakose.Kuruvilla@Sun.COM 				if (ddi_strtol(event, NULL, 0, &event_num) !=
167111261SKuriakose.Kuruvilla@Sun.COM 				    0) {
167211261SKuriakose.Kuruvilla@Sun.COM 					return (CPC_INVALID_EVENT);
167311261SKuriakose.Kuruvilla@Sun.COM 				}
167411261SKuriakose.Kuruvilla@Sun.COM 
167511261SKuriakose.Kuruvilla@Sun.COM 				event_num = event_num & 0xFF;
167611261SKuriakose.Kuruvilla@Sun.COM 
167711261SKuriakose.Kuruvilla@Sun.COM 				/*
167811261SKuriakose.Kuruvilla@Sun.COM 				 * Search the event table to find out if the
167911261SKuriakose.Kuruvilla@Sun.COM 				 * event specified has an privilege
168011261SKuriakose.Kuruvilla@Sun.COM 				 * requirements.  Currently none of the
168111261SKuriakose.Kuruvilla@Sun.COM 				 * pic-specific counters have any privilege
168211261SKuriakose.Kuruvilla@Sun.COM 				 * requirements.  Hence only the table
168311261SKuriakose.Kuruvilla@Sun.COM 				 * cmn_gpc_events_core_uarch is searched.
168411261SKuriakose.Kuruvilla@Sun.COM 				 */
168511261SKuriakose.Kuruvilla@Sun.COM 				for (m = cmn_gpc_events_core_uarch;
168611261SKuriakose.Kuruvilla@Sun.COM 				    m->event_num != NT_END;
168711261SKuriakose.Kuruvilla@Sun.COM 				    m++) {
168811261SKuriakose.Kuruvilla@Sun.COM 					if (event_num == m->event_num) {
168911261SKuriakose.Kuruvilla@Sun.COM 						break;
169011261SKuriakose.Kuruvilla@Sun.COM 					}
169111261SKuriakose.Kuruvilla@Sun.COM 				}
169211261SKuriakose.Kuruvilla@Sun.COM 				if (m->event_num == NT_END) {
169311261SKuriakose.Kuruvilla@Sun.COM 					nt_raw.event_num = (uint8_t)event_num;
169411261SKuriakose.Kuruvilla@Sun.COM 					n = &nt_raw;
169511261SKuriakose.Kuruvilla@Sun.COM 				} else {
169611261SKuriakose.Kuruvilla@Sun.COM 					n = m;
169711261SKuriakose.Kuruvilla@Sun.COM 				}
16987728SKuriakose.Kuruvilla@Sun.COM 			}
169911261SKuriakose.Kuruvilla@Sun.COM 			conf.core_ctl = n->event_num; /* Event Select */
17006840Skk208521 		}
17016840Skk208521 	}
17026840Skk208521 
17037728SKuriakose.Kuruvilla@Sun.COM 
17046840Skk208521 	conf.core_picno = picnum;
17056840Skk208521 	conf.core_pictype = CORE_GPC;
17066840Skk208521 	conf.core_rawpic = preset & mask_gpc;
17076840Skk208521 
17086840Skk208521 	conf.core_pes = GPC_BASE_PES + picnum;
17096840Skk208521 	conf.core_pmc = GPC_BASE_PMC + picnum;
17106840Skk208521 
17116840Skk208521 	for (i = 0; i < nattrs; i++) {
17126840Skk208521 		if (strncmp(attrs[i].ka_name, "umask", 6) == 0) {
17138436SKuriakose.Kuruvilla@Sun.COM 			if ((attrs[i].ka_val | CORE_UMASK_MASK) !=
17148436SKuriakose.Kuruvilla@Sun.COM 			    CORE_UMASK_MASK) {
17157728SKuriakose.Kuruvilla@Sun.COM 				return (CPC_ATTRIBUTE_OUT_OF_RANGE);
17167728SKuriakose.Kuruvilla@Sun.COM 			}
17178436SKuriakose.Kuruvilla@Sun.COM 			/* Clear out the default umask */
17188436SKuriakose.Kuruvilla@Sun.COM 			conf.core_ctl &= ~ (CORE_UMASK_MASK <<
17198436SKuriakose.Kuruvilla@Sun.COM 			    CORE_UMASK_SHIFT);
17208436SKuriakose.Kuruvilla@Sun.COM 			/* Use the user provided umask */
17216840Skk208521 			conf.core_ctl |= attrs[i].ka_val <<
17226840Skk208521 			    CORE_UMASK_SHIFT;
17237728SKuriakose.Kuruvilla@Sun.COM 		} else  if (strncmp(attrs[i].ka_name, "edge", 6) == 0) {
17246840Skk208521 			if (attrs[i].ka_val != 0)
17256840Skk208521 				conf.core_ctl |= CORE_EDGE;
17266840Skk208521 		} else if (strncmp(attrs[i].ka_name, "inv", 4) == 0) {
17276840Skk208521 			if (attrs[i].ka_val != 0)
17286840Skk208521 				conf.core_ctl |= CORE_INV;
17296840Skk208521 		} else if (strncmp(attrs[i].ka_name, "cmask", 6) == 0) {
17306840Skk208521 			if ((attrs[i].ka_val | CORE_CMASK_MASK) !=
17316840Skk208521 			    CORE_CMASK_MASK) {
17326840Skk208521 				return (CPC_ATTRIBUTE_OUT_OF_RANGE);
17336840Skk208521 			}
17347728SKuriakose.Kuruvilla@Sun.COM 			conf.core_ctl |= attrs[i].ka_val <<
17357728SKuriakose.Kuruvilla@Sun.COM 			    CORE_CMASK_SHIFT;
17367728SKuriakose.Kuruvilla@Sun.COM 		} else if (strncmp(attrs[i].ka_name, "anythr", 7) ==
17377728SKuriakose.Kuruvilla@Sun.COM 		    0) {
17387728SKuriakose.Kuruvilla@Sun.COM 			if (versionid < 3)
17397728SKuriakose.Kuruvilla@Sun.COM 				return (CPC_INVALID_ATTRIBUTE);
17407728SKuriakose.Kuruvilla@Sun.COM 			if (secpolicy_cpc_cpu(crgetcred()) != 0) {
17417728SKuriakose.Kuruvilla@Sun.COM 				return (CPC_ATTR_REQUIRES_PRIVILEGE);
17427728SKuriakose.Kuruvilla@Sun.COM 			}
17437728SKuriakose.Kuruvilla@Sun.COM 			if (attrs[i].ka_val != 0)
17447728SKuriakose.Kuruvilla@Sun.COM 				conf.core_ctl |= CORE_ANYTHR;
17456840Skk208521 		} else {
17466840Skk208521 			return (CPC_INVALID_ATTRIBUTE);
17476840Skk208521 		}
17486840Skk208521 	}
17496840Skk208521 
17506840Skk208521 	if (flags & CPC_COUNT_USER)
17516840Skk208521 		conf.core_ctl |= CORE_USR;
17526840Skk208521 	if (flags & CPC_COUNT_SYSTEM)
17536840Skk208521 		conf.core_ctl |= CORE_OS;
17546840Skk208521 	if (flags & CPC_OVF_NOTIFY_EMT)
17556840Skk208521 		conf.core_ctl |= CORE_INT;
17566840Skk208521 	conf.core_ctl |= CORE_EN;
17576840Skk208521 
175811261SKuriakose.Kuruvilla@Sun.COM 	if (versionid < 3 && k == NULL) {
17597728SKuriakose.Kuruvilla@Sun.COM 		if (check_cpc_securitypolicy(&conf, n) != 0) {
17607728SKuriakose.Kuruvilla@Sun.COM 			return (CPC_ATTR_REQUIRES_PRIVILEGE);
17617728SKuriakose.Kuruvilla@Sun.COM 		}
17626840Skk208521 	}
17636840Skk208521 
17646840Skk208521 	*data = kmem_alloc(sizeof (core_pcbe_config_t), KM_SLEEP);
17656840Skk208521 	*((core_pcbe_config_t *)*data) = conf;
17666840Skk208521 
17676840Skk208521 	return (0);
17686840Skk208521 }
17696840Skk208521 
17706840Skk208521 static int
configure_ffc(uint_t picnum,char * event,uint64_t preset,uint32_t flags,uint_t nattrs,kcpc_attr_t * attrs,void ** data)17716840Skk208521 configure_ffc(uint_t picnum, char *event, uint64_t preset, uint32_t flags,
17727728SKuriakose.Kuruvilla@Sun.COM     uint_t nattrs, kcpc_attr_t *attrs, void **data)
17736840Skk208521 {
17746840Skk208521 	core_pcbe_config_t	*conf;
17757728SKuriakose.Kuruvilla@Sun.COM 	uint_t			i;
17766840Skk208521 
17776840Skk208521 	if (picnum - num_gpc >= num_ffc) {
17786840Skk208521 		return (CPC_INVALID_PICNUM);
17796840Skk208521 	}
17807728SKuriakose.Kuruvilla@Sun.COM 
178111261SKuriakose.Kuruvilla@Sun.COM 	if ((strcmp(ffc_names[picnum-num_gpc], event) != 0) &&
178211261SKuriakose.Kuruvilla@Sun.COM 	    (strcmp(ffc_genericnames[picnum-num_gpc], event) != 0)) {
17836840Skk208521 		return (CPC_INVALID_EVENT);
17846840Skk208521 	}
17856840Skk208521 
17867728SKuriakose.Kuruvilla@Sun.COM 	if ((versionid < 3) && (nattrs != 0)) {
17876840Skk208521 		return (CPC_INVALID_ATTRIBUTE);
17886840Skk208521 	}
17896840Skk208521 
17906840Skk208521 	conf = kmem_alloc(sizeof (core_pcbe_config_t), KM_SLEEP);
17917728SKuriakose.Kuruvilla@Sun.COM 	conf->core_ctl = 0;
17927728SKuriakose.Kuruvilla@Sun.COM 
17937728SKuriakose.Kuruvilla@Sun.COM 	for (i = 0; i < nattrs; i++) {
17947728SKuriakose.Kuruvilla@Sun.COM 		if (strncmp(attrs[i].ka_name, "anythr", 7) == 0) {
17957728SKuriakose.Kuruvilla@Sun.COM 			if (secpolicy_cpc_cpu(crgetcred()) != 0) {
1796*13070SEthindra.Ramamurthy@Sun.COM 				kmem_free(conf, sizeof (core_pcbe_config_t));
17977728SKuriakose.Kuruvilla@Sun.COM 				return (CPC_ATTR_REQUIRES_PRIVILEGE);
17987728SKuriakose.Kuruvilla@Sun.COM 			}
17997728SKuriakose.Kuruvilla@Sun.COM 			if (attrs[i].ka_val != 0) {
18007728SKuriakose.Kuruvilla@Sun.COM 				conf->core_ctl |= CORE_FFC_ANYTHR;
18017728SKuriakose.Kuruvilla@Sun.COM 			}
18027728SKuriakose.Kuruvilla@Sun.COM 		} else {
18037728SKuriakose.Kuruvilla@Sun.COM 			kmem_free(conf, sizeof (core_pcbe_config_t));
18047728SKuriakose.Kuruvilla@Sun.COM 			return (CPC_INVALID_ATTRIBUTE);
18057728SKuriakose.Kuruvilla@Sun.COM 		}
18067728SKuriakose.Kuruvilla@Sun.COM 	}
18076840Skk208521 
18086840Skk208521 	conf->core_picno = picnum;
18096840Skk208521 	conf->core_pictype = CORE_FFC;
18106840Skk208521 	conf->core_rawpic = preset & mask_ffc;
18116840Skk208521 	conf->core_pmc = FFC_BASE_PMC + (picnum - num_gpc);
18126840Skk208521 
18136840Skk208521 	/* All fixed-function counters have the same control register */
18146840Skk208521 	conf->core_pes = PERF_FIXED_CTR_CTRL;
18156840Skk208521 
18166840Skk208521 	if (flags & CPC_COUNT_USER)
18176840Skk208521 		conf->core_ctl |= CORE_FFC_USR_EN;
18186840Skk208521 	if (flags & CPC_COUNT_SYSTEM)
18196840Skk208521 		conf->core_ctl |= CORE_FFC_OS_EN;
18206840Skk208521 	if (flags & CPC_OVF_NOTIFY_EMT)
18216840Skk208521 		conf->core_ctl |= CORE_FFC_PMI;
18226840Skk208521 
18236840Skk208521 	*data = conf;
18246840Skk208521 	return (0);
18256840Skk208521 }
18266840Skk208521 
18276840Skk208521 /*ARGSUSED*/
18286840Skk208521 static int
core_pcbe_configure(uint_t picnum,char * event,uint64_t preset,uint32_t flags,uint_t nattrs,kcpc_attr_t * attrs,void ** data,void * token)18296840Skk208521 core_pcbe_configure(uint_t picnum, char *event, uint64_t preset,
18306840Skk208521     uint32_t flags, uint_t nattrs, kcpc_attr_t *attrs, void **data,
18316840Skk208521     void *token)
18326840Skk208521 {
18336840Skk208521 	int			ret;
18346840Skk208521 	core_pcbe_config_t	*conf;
18356840Skk208521 
18366840Skk208521 	/*
18376840Skk208521 	 * If we've been handed an existing configuration, we need only preset
18386840Skk208521 	 * the counter value.
18396840Skk208521 	 */
18406840Skk208521 	if (*data != NULL) {
18416840Skk208521 		conf = *data;
18426840Skk208521 		ASSERT(conf->core_pictype == CORE_GPC ||
18436840Skk208521 		    conf->core_pictype == CORE_FFC);
18446840Skk208521 		if (conf->core_pictype == CORE_GPC)
18456840Skk208521 			conf->core_rawpic = preset & mask_gpc;
18466840Skk208521 		else /* CORE_FFC */
18476840Skk208521 			conf->core_rawpic = preset & mask_ffc;
18486840Skk208521 		return (0);
18496840Skk208521 	}
18506840Skk208521 
18516840Skk208521 	if (picnum >= total_pmc) {
18526840Skk208521 		return (CPC_INVALID_PICNUM);
18536840Skk208521 	}
18546840Skk208521 
18556840Skk208521 	if (picnum < num_gpc) {
18566840Skk208521 		ret = configure_gpc(picnum, event, preset, flags,
18576840Skk208521 		    nattrs, attrs, data);
18586840Skk208521 	} else {
18596840Skk208521 		ret = configure_ffc(picnum, event, preset, flags,
18607728SKuriakose.Kuruvilla@Sun.COM 		    nattrs, attrs, data);
18616840Skk208521 	}
18626840Skk208521 	return (ret);
18636840Skk208521 }
18646840Skk208521 
18656840Skk208521 static void
core_pcbe_program(void * token)18666840Skk208521 core_pcbe_program(void *token)
18676840Skk208521 {
18686840Skk208521 	core_pcbe_config_t	*cfg;
18696840Skk208521 	uint64_t		perf_global_ctrl;
18706840Skk208521 	uint64_t		perf_fixed_ctr_ctrl;
18716840Skk208521 	uint64_t		curcr4;
18726840Skk208521 
18736840Skk208521 	core_pcbe_allstop();
18746840Skk208521 
18756840Skk208521 	curcr4 = getcr4();
18766840Skk208521 	if (kcpc_allow_nonpriv(token))
18776840Skk208521 		/* Allow RDPMC at any ring level */
18786840Skk208521 		setcr4(curcr4 | CR4_PCE);
18796840Skk208521 	else
18806840Skk208521 		/* Allow RDPMC only at ring 0 */
18816840Skk208521 		setcr4(curcr4 & ~CR4_PCE);
18826840Skk208521 
18836840Skk208521 	/* Clear any overflow indicators before programming the counters */
18846840Skk208521 	WRMSR(PERF_GLOBAL_OVF_CTRL, MASK_CONDCHGD_OVFBUFFER | control_mask);
18856840Skk208521 
18866840Skk208521 	cfg = NULL;
18876840Skk208521 	perf_global_ctrl = 0;
18886840Skk208521 	perf_fixed_ctr_ctrl = 0;
18896840Skk208521 	cfg = (core_pcbe_config_t *)kcpc_next_config(token, cfg, NULL);
18906840Skk208521 	while (cfg != NULL) {
18916840Skk208521 		ASSERT(cfg->core_pictype == CORE_GPC ||
18926840Skk208521 		    cfg->core_pictype == CORE_FFC);
18936840Skk208521 
18946840Skk208521 		if (cfg->core_pictype == CORE_GPC) {
18956840Skk208521 			/*
18966840Skk208521 			 * General-purpose counter registers have write
18976840Skk208521 			 * restrictions where only the lower 32-bits can be
18986840Skk208521 			 * written to.  The rest of the relevant bits are
18996840Skk208521 			 * written to by extension from bit 31 (all ZEROS if
19006840Skk208521 			 * bit-31 is ZERO and all ONE if bit-31 is ONE).  This
19016840Skk208521 			 * makes it possible to write to the counter register
19026840Skk208521 			 * only values that have all ONEs or all ZEROs in the
19036840Skk208521 			 * higher bits.
19046840Skk208521 			 */
19056840Skk208521 			if (((cfg->core_rawpic & BITS_EXTENDED_FROM_31) == 0) ||
19066840Skk208521 			    ((cfg->core_rawpic & BITS_EXTENDED_FROM_31) ==
19076840Skk208521 			    BITS_EXTENDED_FROM_31)) {
19086840Skk208521 				/*
19096840Skk208521 				 * Straighforward case where the higher bits
19106840Skk208521 				 * are all ZEROs or all ONEs.
19116840Skk208521 				 */
19126840Skk208521 				WRMSR(cfg->core_pmc,
19136840Skk208521 				    (cfg->core_rawpic & mask_gpc));
19146840Skk208521 			} else {
19156840Skk208521 				/*
19166840Skk208521 				 * The high order bits are not all the same.
19176840Skk208521 				 * We save what is currently in the registers
19186840Skk208521 				 * and do not write to it.  When we want to do
19196840Skk208521 				 * a read from this register later (in
19206840Skk208521 				 * core_pcbe_sample()), we subtract the value
19216840Skk208521 				 * we save here to get the actual event count.
19226840Skk208521 				 *
19236840Skk208521 				 * NOTE: As a result, we will not get overflow
19246840Skk208521 				 * interrupts as expected.
19256840Skk208521 				 */
19266840Skk208521 				RDMSR(cfg->core_pmc, cfg->core_rawpic);
19276840Skk208521 				cfg->core_rawpic = cfg->core_rawpic & mask_gpc;
19286840Skk208521 			}
19296840Skk208521 			WRMSR(cfg->core_pes, cfg->core_ctl);
19306840Skk208521 			perf_global_ctrl |= 1ull << cfg->core_picno;
19316840Skk208521 		} else {
19326840Skk208521 			/*
19336840Skk208521 			 * Unlike the general-purpose counters, all relevant
19346840Skk208521 			 * bits of fixed-function counters can be written to.
19356840Skk208521 			 */
19366840Skk208521 			WRMSR(cfg->core_pmc, cfg->core_rawpic & mask_ffc);
19376840Skk208521 
19386840Skk208521 			/*
19396840Skk208521 			 * Collect the control bits for all the
19406840Skk208521 			 * fixed-function counters and write it at one shot
19416840Skk208521 			 * later in this function
19426840Skk208521 			 */
19436840Skk208521 			perf_fixed_ctr_ctrl |= cfg->core_ctl <<
19446840Skk208521 			    ((cfg->core_picno - num_gpc) * CORE_FFC_ATTR_SIZE);
19456840Skk208521 			perf_global_ctrl |=
19466840Skk208521 			    1ull << (cfg->core_picno - num_gpc + 32);
19476840Skk208521 		}
19486840Skk208521 
19496840Skk208521 		cfg = (core_pcbe_config_t *)
19506840Skk208521 		    kcpc_next_config(token, cfg, NULL);
19516840Skk208521 	}
19526840Skk208521 
19536840Skk208521 	/* Enable all the counters */
19546840Skk208521 	WRMSR(PERF_FIXED_CTR_CTRL, perf_fixed_ctr_ctrl);
19556840Skk208521 	WRMSR(PERF_GLOBAL_CTRL, perf_global_ctrl);
19566840Skk208521 }
19576840Skk208521 
19586840Skk208521 static void
core_pcbe_allstop(void)19596840Skk208521 core_pcbe_allstop(void)
19606840Skk208521 {
19616840Skk208521 	/* Disable all the counters together */
19626840Skk208521 	WRMSR(PERF_GLOBAL_CTRL, ALL_STOPPED);
19636840Skk208521 
19646840Skk208521 	setcr4(getcr4() & ~CR4_PCE);
19656840Skk208521 }
19666840Skk208521 
19676840Skk208521 static void
core_pcbe_sample(void * token)19686840Skk208521 core_pcbe_sample(void *token)
19696840Skk208521 {
19706840Skk208521 	uint64_t		*daddr;
19716840Skk208521 	uint64_t		curpic;
19726840Skk208521 	core_pcbe_config_t	*cfg;
19736840Skk208521 	uint64_t			counter_mask;
19746840Skk208521 
19756840Skk208521 	cfg = (core_pcbe_config_t *)kcpc_next_config(token, NULL, &daddr);
19766840Skk208521 	while (cfg != NULL) {
19776840Skk208521 		ASSERT(cfg->core_pictype == CORE_GPC ||
19786840Skk208521 		    cfg->core_pictype == CORE_FFC);
19796840Skk208521 
19806840Skk208521 		curpic = rdmsr(cfg->core_pmc);
19816840Skk208521 
19826840Skk208521 		DTRACE_PROBE4(core__pcbe__sample,
19836840Skk208521 		    uint64_t, cfg->core_pmc,
19846840Skk208521 		    uint64_t, curpic,
19856840Skk208521 		    uint64_t, cfg->core_rawpic,
19866840Skk208521 		    uint64_t, *daddr);
19876840Skk208521 
19886840Skk208521 		if (cfg->core_pictype == CORE_GPC) {
19896840Skk208521 			counter_mask = mask_gpc;
19906840Skk208521 		} else {
19916840Skk208521 			counter_mask = mask_ffc;
19926840Skk208521 		}
19936840Skk208521 		curpic = curpic & counter_mask;
19946840Skk208521 		if (curpic >= cfg->core_rawpic) {
19956840Skk208521 			*daddr += curpic - cfg->core_rawpic;
19966840Skk208521 		} else {
19976840Skk208521 			/* Counter overflowed since our last sample */
19986840Skk208521 			*daddr += counter_mask - (cfg->core_rawpic - curpic) +
19996840Skk208521 			    1;
20006840Skk208521 		}
20016840Skk208521 		cfg->core_rawpic = *daddr & counter_mask;
20026840Skk208521 
20036840Skk208521 		cfg =
20046840Skk208521 		    (core_pcbe_config_t *)kcpc_next_config(token, cfg, &daddr);
20056840Skk208521 	}
20066840Skk208521 }
20076840Skk208521 
20086840Skk208521 static void
core_pcbe_free(void * config)20096840Skk208521 core_pcbe_free(void *config)
20106840Skk208521 {
20116840Skk208521 	kmem_free(config, sizeof (core_pcbe_config_t));
20126840Skk208521 }
20136840Skk208521 
20146840Skk208521 static struct modlpcbe core_modlpcbe = {
20156840Skk208521 	&mod_pcbeops,
20167258Skk208521 	"Core Performance Counters",
20176840Skk208521 	&core_pcbe_ops
20186840Skk208521 };
20196840Skk208521 
20206840Skk208521 static struct modlinkage core_modl = {
20216840Skk208521 	MODREV_1,
20226840Skk208521 	&core_modlpcbe,
20236840Skk208521 };
20246840Skk208521 
20256840Skk208521 int
_init(void)20266840Skk208521 _init(void)
20276840Skk208521 {
20286840Skk208521 	if (core_pcbe_init() != 0) {
20296840Skk208521 		return (ENOTSUP);
20306840Skk208521 	}
20316840Skk208521 	return (mod_install(&core_modl));
20326840Skk208521 }
20336840Skk208521 
20346840Skk208521 int
_fini(void)20356840Skk208521 _fini(void)
20366840Skk208521 {
20376840Skk208521 	return (mod_remove(&core_modl));
20386840Skk208521 }
20396840Skk208521 
20406840Skk208521 int
_info(struct modinfo * mi)20416840Skk208521 _info(struct modinfo *mi)
20426840Skk208521 {
20436840Skk208521 	return (mod_info(&core_modl, mi));
20446840Skk208521 }
2045