xref: /onnv-gate/usr/src/uts/sun4u/pcbe/us234_pcbe.c (revision 7640:c468bb5b1d2d)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57258Skk208521  * Common Development and Distribution License (the "License").
67258Skk208521  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
227258Skk208521  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
27*7640SJonathan.Haslam@Sun.COM  * This file contains preset event names from the Performance Application
28*7640SJonathan.Haslam@Sun.COM  * Programming Interface v3.5 which included the following notice:
29*7640SJonathan.Haslam@Sun.COM  *
30*7640SJonathan.Haslam@Sun.COM  *                             Copyright (c) 2005,6
31*7640SJonathan.Haslam@Sun.COM  *                           Innovative Computing Labs
32*7640SJonathan.Haslam@Sun.COM  *                         Computer Science Department,
33*7640SJonathan.Haslam@Sun.COM  *                            University of Tennessee,
34*7640SJonathan.Haslam@Sun.COM  *                                 Knoxville, TN.
35*7640SJonathan.Haslam@Sun.COM  *                              All Rights Reserved.
36*7640SJonathan.Haslam@Sun.COM  *
37*7640SJonathan.Haslam@Sun.COM  *
38*7640SJonathan.Haslam@Sun.COM  * Redistribution and use in source and binary forms, with or without
39*7640SJonathan.Haslam@Sun.COM  * modification, are permitted provided that the following conditions are met:
40*7640SJonathan.Haslam@Sun.COM  *
41*7640SJonathan.Haslam@Sun.COM  *    * Redistributions of source code must retain the above copyright notice,
42*7640SJonathan.Haslam@Sun.COM  *      this list of conditions and the following disclaimer.
43*7640SJonathan.Haslam@Sun.COM  *    * Redistributions in binary form must reproduce the above copyright
44*7640SJonathan.Haslam@Sun.COM  *      notice, this list of conditions and the following disclaimer in the
45*7640SJonathan.Haslam@Sun.COM  *      documentation and/or other materials provided with the distribution.
46*7640SJonathan.Haslam@Sun.COM  *    * Neither the name of the University of Tennessee nor the names of its
47*7640SJonathan.Haslam@Sun.COM  *      contributors may be used to endorse or promote products derived from
48*7640SJonathan.Haslam@Sun.COM  *      this software without specific prior written permission.
49*7640SJonathan.Haslam@Sun.COM  *
50*7640SJonathan.Haslam@Sun.COM  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
51*7640SJonathan.Haslam@Sun.COM  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52*7640SJonathan.Haslam@Sun.COM  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53*7640SJonathan.Haslam@Sun.COM  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
54*7640SJonathan.Haslam@Sun.COM  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
55*7640SJonathan.Haslam@Sun.COM  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
56*7640SJonathan.Haslam@Sun.COM  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57*7640SJonathan.Haslam@Sun.COM  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58*7640SJonathan.Haslam@Sun.COM  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59*7640SJonathan.Haslam@Sun.COM  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60*7640SJonathan.Haslam@Sun.COM  * POSSIBILITY OF SUCH DAMAGE.
61*7640SJonathan.Haslam@Sun.COM  *
62*7640SJonathan.Haslam@Sun.COM  *
63*7640SJonathan.Haslam@Sun.COM  * This open source software license conforms to the BSD License template.
64*7640SJonathan.Haslam@Sun.COM  */
65*7640SJonathan.Haslam@Sun.COM 
66*7640SJonathan.Haslam@Sun.COM /*
670Sstevel@tonic-gate  * UltraSPARC Performance Counter Backend
680Sstevel@tonic-gate  */
690Sstevel@tonic-gate 
700Sstevel@tonic-gate #include <sys/cpuvar.h>
710Sstevel@tonic-gate #include <sys/systm.h>
720Sstevel@tonic-gate #include <sys/cmn_err.h>
730Sstevel@tonic-gate #include <sys/spitregs.h>
740Sstevel@tonic-gate #include <sys/cheetahregs.h>
750Sstevel@tonic-gate #include <sys/cpc_impl.h>
760Sstevel@tonic-gate #include <sys/cpc_pcbe.h>
770Sstevel@tonic-gate #include <sys/modctl.h>
780Sstevel@tonic-gate #include <sys/machsystm.h>
790Sstevel@tonic-gate #include <sys/sdt.h>
800Sstevel@tonic-gate 
810Sstevel@tonic-gate static int us_pcbe_init(void);
820Sstevel@tonic-gate static uint_t us_pcbe_ncounters(void);
830Sstevel@tonic-gate static const char *us_pcbe_impl_name(void);
840Sstevel@tonic-gate static const char *us_pcbe_cpuref(void);
850Sstevel@tonic-gate static char *us_pcbe_list_events(uint_t picnum);
860Sstevel@tonic-gate static char *us_pcbe_list_attrs(void);
870Sstevel@tonic-gate static uint64_t us_pcbe_event_coverage(char *event);
880Sstevel@tonic-gate static uint64_t us_pcbe_overflow_bitmap(void);
890Sstevel@tonic-gate static int us_pcbe_configure(uint_t picnum, char *event, uint64_t preset,
900Sstevel@tonic-gate     uint32_t flags, uint_t nattrs, kcpc_attr_t *attrs, void **data,
910Sstevel@tonic-gate     void *token);
920Sstevel@tonic-gate static void us_pcbe_program(void *token);
930Sstevel@tonic-gate static void us_pcbe_allstop(void);
940Sstevel@tonic-gate static void us_pcbe_sample(void *token);
950Sstevel@tonic-gate static void us_pcbe_free(void *config);
960Sstevel@tonic-gate 
970Sstevel@tonic-gate extern void ultra_setpcr(uint64_t);
980Sstevel@tonic-gate extern uint64_t ultra_getpcr(void);
990Sstevel@tonic-gate extern void ultra_setpic(uint64_t);
1000Sstevel@tonic-gate extern uint64_t ultra_getpic(void);
1010Sstevel@tonic-gate extern uint64_t ultra_gettick(void);
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate pcbe_ops_t us_pcbe_ops = {
1040Sstevel@tonic-gate 	PCBE_VER_1,
1050Sstevel@tonic-gate 	CPC_CAP_OVERFLOW_INTERRUPT,
1060Sstevel@tonic-gate 	us_pcbe_ncounters,
1070Sstevel@tonic-gate 	us_pcbe_impl_name,
1080Sstevel@tonic-gate 	us_pcbe_cpuref,
1090Sstevel@tonic-gate 	us_pcbe_list_events,
1100Sstevel@tonic-gate 	us_pcbe_list_attrs,
1110Sstevel@tonic-gate 	us_pcbe_event_coverage,
1120Sstevel@tonic-gate 	us_pcbe_overflow_bitmap,
1130Sstevel@tonic-gate 	us_pcbe_configure,
1140Sstevel@tonic-gate 	us_pcbe_program,
1150Sstevel@tonic-gate 	us_pcbe_allstop,
1160Sstevel@tonic-gate 	us_pcbe_sample,
1170Sstevel@tonic-gate 	us_pcbe_free
1180Sstevel@tonic-gate };
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate typedef struct _us_pcbe_config {
1210Sstevel@tonic-gate 	uint8_t		us_picno;	/* 0 for pic0 or 1 for pic1 */
1220Sstevel@tonic-gate 	uint32_t	us_bits;	/* %pcr event code unshifted */
1230Sstevel@tonic-gate 	uint32_t	us_flags;	/* user/system/priv */
1240Sstevel@tonic-gate 	uint32_t	us_pic;		/* unshifted raw %pic value */
1250Sstevel@tonic-gate } us_pcbe_config_t;
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate struct nametable {
1280Sstevel@tonic-gate 	const uint8_t	bits;
1290Sstevel@tonic-gate 	const char	*name;
1300Sstevel@tonic-gate };
1310Sstevel@tonic-gate 
132*7640SJonathan.Haslam@Sun.COM typedef struct _us_generic_event {
133*7640SJonathan.Haslam@Sun.COM 	char *name;
134*7640SJonathan.Haslam@Sun.COM 	char *event;
135*7640SJonathan.Haslam@Sun.COM } us_generic_event_t;
136*7640SJonathan.Haslam@Sun.COM 
1370Sstevel@tonic-gate #define	PIC0_MASK (((uint64_t)1 << 32) - 1)
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate #define	ULTRA_PCR_SYS		(UINT64_C(1) << CPC_ULTRA_PCR_SYS)
1400Sstevel@tonic-gate #define	ULTRA_PCR_PRIVPIC	(UINT64_C(1) << CPC_ULTRA_PCR_PRIVPIC)
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate #define	CPC_ULTRA_PCR_USR		2
1430Sstevel@tonic-gate #define	CPC_ULTRA_PCR_SYS		1
1440Sstevel@tonic-gate #define	CPC_ULTRA_PCR_PRIVPIC		0
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate #define	CPC_ULTRA_PCR_PIC0_SHIFT	4
1470Sstevel@tonic-gate #define	CPC_ULTRA2_PCR_PIC_MASK		UINT64_C(0xf)
1480Sstevel@tonic-gate #define	CPC_ULTRA3_PCR_PIC_MASK		UINT64_C(0x3f)
1490Sstevel@tonic-gate #define	CPC_ULTRA_PCR_PIC1_SHIFT	11
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate #define	NT_END 0xFF
152*7640SJonathan.Haslam@Sun.COM #define	CPC_GEN_END { NULL, NULL }
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate static const uint64_t   allstopped = ULTRA_PCR_PRIVPIC;
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate #define	USall_EVENTS_0						\
1570Sstevel@tonic-gate 	{0x0,	"Cycle_cnt"},					\
1580Sstevel@tonic-gate 	{0x1,	"Instr_cnt"},					\
1590Sstevel@tonic-gate 	{0x2,	"Dispatch0_IC_miss"},				\
1600Sstevel@tonic-gate 	{0x8,	"IC_ref"},					\
1610Sstevel@tonic-gate 	{0x9,	"DC_rd"},					\
1620Sstevel@tonic-gate 	{0xa,	"DC_wr"},					\
1630Sstevel@tonic-gate 	{0xc,	"EC_ref"},					\
1640Sstevel@tonic-gate 	{0xe,	"EC_snoop_inv"}
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate static const struct nametable US12_names0[] = {
1670Sstevel@tonic-gate 	USall_EVENTS_0,
1680Sstevel@tonic-gate 	{0x3,	"Dispatch0_storeBuf"},
1690Sstevel@tonic-gate 	{0xb,	"Load_use"},
1700Sstevel@tonic-gate 	{0xd,	"EC_write_hit_RDO"},
1710Sstevel@tonic-gate 	{0xf,	"EC_rd_hit"},
1720Sstevel@tonic-gate 	{NT_END, ""}
1730Sstevel@tonic-gate };
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate #define	US3all_EVENTS_0						\
1760Sstevel@tonic-gate 	{0x3,	"Dispatch0_br_target"},				\
1770Sstevel@tonic-gate 	{0x4,	"Dispatch0_2nd_br"},				\
1780Sstevel@tonic-gate 	{0x5,	"Rstall_storeQ"},				\
1790Sstevel@tonic-gate 	{0x6,	"Rstall_IU_use"},				\
1800Sstevel@tonic-gate 	{0xd,	"EC_write_hit_RTO"},				\
1810Sstevel@tonic-gate 	{0xf,	"EC_rd_miss"},					\
1820Sstevel@tonic-gate 	{0x10,	"PC_port0_rd"},					\
1830Sstevel@tonic-gate 	{0x11,	"SI_snoop"},					\
1840Sstevel@tonic-gate 	{0x12,	"SI_ciq_flow"},					\
1850Sstevel@tonic-gate 	{0x13,	"SI_owned"},					\
1860Sstevel@tonic-gate 	{0x14,	"SW_count_0"},					\
1870Sstevel@tonic-gate 	{0x15,	"IU_Stat_Br_miss_taken"},			\
1880Sstevel@tonic-gate 	{0x16,	"IU_Stat_Br_count_taken"},			\
1890Sstevel@tonic-gate 	{0x17,	"Dispatch_rs_mispred"},				\
1900Sstevel@tonic-gate 	{0x18,	"FA_pipe_completion"}
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate #define	US3_MC_EVENTS_0						\
1930Sstevel@tonic-gate 	{0x20,	"MC_reads_0"},					\
1940Sstevel@tonic-gate 	{0x21,	"MC_reads_1"},					\
1950Sstevel@tonic-gate 	{0x22,	"MC_reads_2"},					\
1960Sstevel@tonic-gate 	{0x23,	"MC_reads_3"},					\
1970Sstevel@tonic-gate 	{0x24,	"MC_stalls_0"},					\
1980Sstevel@tonic-gate 	{0x25,	"MC_stalls_2"}
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate #define	US3_I_MC_EVENTS_0					\
2010Sstevel@tonic-gate 	{0x20,	"MC_read_dispatched"},				\
2020Sstevel@tonic-gate 	{0x21,	"MC_write_dispatched"},				\
2030Sstevel@tonic-gate 	{0x22,	"MC_read_returned_to_JBU"},			\
2040Sstevel@tonic-gate 	{0x23,	"MC_msl_busy_stall"},				\
2050Sstevel@tonic-gate 	{0x24,	"MC_mdb_overflow_stall"},			\
2060Sstevel@tonic-gate 	{0x25,	"MC_miu_spec_request"}
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate #define	USall_EVENTS_1						\
2090Sstevel@tonic-gate 	{0x0,	"Cycle_cnt"},					\
2100Sstevel@tonic-gate 	{0x1,	"Instr_cnt"},					\
2110Sstevel@tonic-gate 	{0x2,	"Dispatch0_mispred"},				\
2120Sstevel@tonic-gate 	{0xd,	"EC_wb"},					\
2130Sstevel@tonic-gate 	{0xe,	"EC_snoop_cb"}
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate static const struct nametable US3_names0[] = {
2160Sstevel@tonic-gate 	USall_EVENTS_0,
2170Sstevel@tonic-gate 	US3all_EVENTS_0,
2180Sstevel@tonic-gate 	US3_MC_EVENTS_0,
2190Sstevel@tonic-gate 	{NT_END, ""}
2200Sstevel@tonic-gate };
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate static const struct nametable US3_PLUS_names0[] = {
2230Sstevel@tonic-gate 	USall_EVENTS_0,
2240Sstevel@tonic-gate 	US3all_EVENTS_0,
2250Sstevel@tonic-gate 	US3_MC_EVENTS_0,
2260Sstevel@tonic-gate 	{0x19,	"EC_wb_remote"},
2270Sstevel@tonic-gate 	{0x1a,	"EC_miss_local"},
2280Sstevel@tonic-gate 	{0x1b,	"EC_miss_mtag_remote"},
2290Sstevel@tonic-gate 	{NT_END, ""}
2300Sstevel@tonic-gate };
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate static const struct nametable US3_I_names0[] = {
2330Sstevel@tonic-gate 	USall_EVENTS_0,
2340Sstevel@tonic-gate 	US3all_EVENTS_0,
2350Sstevel@tonic-gate 	US3_I_MC_EVENTS_0,
2360Sstevel@tonic-gate 	{NT_END, ""}
2370Sstevel@tonic-gate };
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate static const struct nametable US4_PLUS_names0[] = {
2400Sstevel@tonic-gate 	{0x0,   "Cycle_cnt"},
2410Sstevel@tonic-gate 	{0x1,   "Instr_cnt"},
2420Sstevel@tonic-gate 	{0x2,   "Dispatch0_IC_miss"},
2430Sstevel@tonic-gate 	{0x3,   "IU_stat_jmp_correct_pred"},
2440Sstevel@tonic-gate 	{0x4,   "Dispatch0_2nd_br"},
2450Sstevel@tonic-gate 	{0x5,   "Rstall_storeQ"},
2460Sstevel@tonic-gate 	{0x6,   "Rstall_IU_use"},
2470Sstevel@tonic-gate 	{0x7,   "IU_stat_ret_correct_pred"},
2480Sstevel@tonic-gate 	{0x8,   "IC_ref"},
2490Sstevel@tonic-gate 	{0x9,   "DC_rd"},
2500Sstevel@tonic-gate 	{0xa,   "Rstall_FP_use"},
2510Sstevel@tonic-gate 	{0xb,   "SW_pf_instr"},
2520Sstevel@tonic-gate 	{0xc,   "L2_ref"},
2530Sstevel@tonic-gate 	{0xd,   "L2_write_hit_RTO"},
2540Sstevel@tonic-gate 	{0xe,   "L2_snoop_inv_sh"},
2550Sstevel@tonic-gate 	{0xf,   "L2_rd_miss"},
2560Sstevel@tonic-gate 	{0x10,  "PC_rd"},
2570Sstevel@tonic-gate 	{0x11,  "SI_snoop_sh"},
2580Sstevel@tonic-gate 	{0x12,  "SI_ciq_flow_sh"},
2590Sstevel@tonic-gate 	{0x13,  "Re_DC_miss"},
2600Sstevel@tonic-gate 	{0x14,  "SW_count_NOP"},
2610Sstevel@tonic-gate 	{0x15,  "IU_stat_br_miss_taken"},
2620Sstevel@tonic-gate 	{0x16,  "IU_stat_br_count_untaken"},
2630Sstevel@tonic-gate 	{0x17,  "HW_pf_exec"},
2640Sstevel@tonic-gate 	{0x18,  "FA_pipe_completion"},
2650Sstevel@tonic-gate 	{0x19,  "SSM_L3_wb_remote"},
2660Sstevel@tonic-gate 	{0x1a,  "SSM_L3_miss_local"},
2670Sstevel@tonic-gate 	{0x1b,  "SSM_L3_miss_mtag_remote"},
2680Sstevel@tonic-gate 	{0x1c,  "SW_pf_str_trapped"},
2690Sstevel@tonic-gate 	{0x1d,  "SW_pf_PC_installed"},
2700Sstevel@tonic-gate 	{0x1e,  "IPB_to_IC_fill"},
2710Sstevel@tonic-gate 	{0x1f,  "L2_write_miss"},
2720Sstevel@tonic-gate 	{0x20,  "MC_reads_0_sh"},
2730Sstevel@tonic-gate 	{0x21,  "MC_reads_1_sh"},
2740Sstevel@tonic-gate 	{0x22,  "MC_reads_2_sh"},
2750Sstevel@tonic-gate 	{0x23,  "MC_reads_3_sh"},
2760Sstevel@tonic-gate 	{0x24,  "MC_stalls_0_sh"},
2770Sstevel@tonic-gate 	{0x25,  "MC_stalls_2_sh"},
2780Sstevel@tonic-gate 	{0x26,  "L2_hit_other_half"},
2790Sstevel@tonic-gate 	{0x28,  "L3_rd_miss"},
2800Sstevel@tonic-gate 	{0x29,  "Re_L2_miss"},
2810Sstevel@tonic-gate 	{0x2a,  "IC_miss_cancelled"},
2820Sstevel@tonic-gate 	{0x2b,  "DC_wr_miss"},
2830Sstevel@tonic-gate 	{0x2c,  "L3_hit_I_state_sh"},
2840Sstevel@tonic-gate 	{0x2d,  "SI_RTS_src_data"},
2850Sstevel@tonic-gate 	{0x2e,  "L2_IC_miss"},
2860Sstevel@tonic-gate 	{0x2f,  "SSM_new_transaction_sh"},
2870Sstevel@tonic-gate 	{0x30,  "L2_SW_pf_miss"},
2880Sstevel@tonic-gate 	{0x31,  "L2_wb"},
2890Sstevel@tonic-gate 	{0x32,  "L2_wb_sh"},
2900Sstevel@tonic-gate 	{0x33,  "L2_snoop_cb_sh"},
2910Sstevel@tonic-gate 	{NT_END, ""}
2920Sstevel@tonic-gate };
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate #define	US3all_EVENTS_1				\
2960Sstevel@tonic-gate 	{0x3,	"IC_miss_cancelled"},		\
2970Sstevel@tonic-gate 	{0x5,	"Re_FPU_bypass"},		\
2980Sstevel@tonic-gate 	{0x6,	"Re_DC_miss"},			\
2990Sstevel@tonic-gate 	{0x7,	"Re_EC_miss"},			\
3000Sstevel@tonic-gate 	{0x8,	"IC_miss"},			\
3010Sstevel@tonic-gate 	{0x9,	"DC_rd_miss"},			\
3020Sstevel@tonic-gate 	{0xa,	"DC_wr_miss"},			\
3030Sstevel@tonic-gate 	{0xb,	"Rstall_FP_use"},		\
3040Sstevel@tonic-gate 	{0xc,	"EC_misses"},			\
3050Sstevel@tonic-gate 	{0xf,	"EC_ic_miss"},			\
3060Sstevel@tonic-gate 	{0x10,	"Re_PC_miss"},			\
3070Sstevel@tonic-gate 	{0x11,	"ITLB_miss"},			\
3080Sstevel@tonic-gate 	{0x12,	"DTLB_miss"},			\
3090Sstevel@tonic-gate 	{0x13,	"WC_miss"},			\
3100Sstevel@tonic-gate 	{0x14,	"WC_snoop_cb"},			\
3110Sstevel@tonic-gate 	{0x15,	"WC_scrubbed"},			\
3120Sstevel@tonic-gate 	{0x16,	"WC_wb_wo_read"},		\
3130Sstevel@tonic-gate 	{0x18,	"PC_soft_hit"},			\
3140Sstevel@tonic-gate 	{0x19,	"PC_snoop_inv"},		\
3150Sstevel@tonic-gate 	{0x1a,	"PC_hard_hit"},			\
3160Sstevel@tonic-gate 	{0x1b,	"PC_port1_rd"},			\
3170Sstevel@tonic-gate 	{0x1c,	"SW_count_1"},			\
3180Sstevel@tonic-gate 	{0x1d,	"IU_Stat_Br_miss_untaken"},	\
3190Sstevel@tonic-gate 	{0x1e,	"IU_Stat_Br_count_untaken"},	\
3200Sstevel@tonic-gate 	{0x1f,	"PC_MS_misses"},		\
3210Sstevel@tonic-gate 	{0x26,	"Re_RAW_miss"},			\
3220Sstevel@tonic-gate 	{0x27,	"FM_pipe_completion"}
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate #define	US3_MC_EVENTS_1				\
3250Sstevel@tonic-gate 	{0x20,	"MC_writes_0"},			\
3260Sstevel@tonic-gate 	{0x21,	"MC_writes_1"},			\
3270Sstevel@tonic-gate 	{0x22,	"MC_writes_2"},			\
3280Sstevel@tonic-gate 	{0x23,	"MC_writes_3"},			\
3290Sstevel@tonic-gate 	{0x24,	"MC_stalls_1"},			\
3300Sstevel@tonic-gate 	{0x25,	"MC_stalls_3"}
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate #define	US3_I_MC_EVENTS_1			\
3330Sstevel@tonic-gate 	{0x20,	"MC_open_bank_cmds"},		\
3340Sstevel@tonic-gate 	{0x21,	"MC_reads"},			\
3350Sstevel@tonic-gate 	{0x22,	"MC_writes"},			\
3360Sstevel@tonic-gate 	{0x23,	"MC_page_close_stall"}
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate static const struct nametable US3_names1[] = {
3390Sstevel@tonic-gate 	USall_EVENTS_1,
3400Sstevel@tonic-gate 	US3all_EVENTS_1,
3410Sstevel@tonic-gate 	US3_MC_EVENTS_1,
3420Sstevel@tonic-gate 	{0x4,	"Re_endian_miss"},
3430Sstevel@tonic-gate 	{NT_END, ""}
3440Sstevel@tonic-gate };
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate static const struct nametable US3_PLUS_names1[] = {
3470Sstevel@tonic-gate 	USall_EVENTS_1,
3480Sstevel@tonic-gate 	US3all_EVENTS_1,
3490Sstevel@tonic-gate 	US3_MC_EVENTS_1,
3500Sstevel@tonic-gate 	{0x4,	"Re_DC_missovhd"},
3510Sstevel@tonic-gate 	{0x28,	"EC_miss_mtag_remote"},
3520Sstevel@tonic-gate 	{0x29,	"EC_miss_remote"},
3530Sstevel@tonic-gate 	{NT_END, ""}
3540Sstevel@tonic-gate };
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate static const struct nametable US3_I_names1[] = {
3570Sstevel@tonic-gate 	USall_EVENTS_1,
3580Sstevel@tonic-gate 	US3all_EVENTS_1,
3590Sstevel@tonic-gate 	US3_I_MC_EVENTS_1,
3600Sstevel@tonic-gate 	{0x4,	"Re_DC_missovhd"},
3610Sstevel@tonic-gate 	{NT_END, ""}
3620Sstevel@tonic-gate };
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate static const struct nametable US4_PLUS_names1[] = {
3650Sstevel@tonic-gate 	{0x0,   "Cycle_cnt"},
3660Sstevel@tonic-gate 	{0x1,   "Instr_cnt"},
3670Sstevel@tonic-gate 	{0x2,   "Dispatch0_other"},
3680Sstevel@tonic-gate 	{0x3,   "DC_wr"},
3690Sstevel@tonic-gate 	{0x4,   "Re_DC_missovhd"},
3700Sstevel@tonic-gate 	{0x5,   "Re_FPU_bypass"},
3710Sstevel@tonic-gate 	{0x6,   "L3_write_hit_RTO"},
3720Sstevel@tonic-gate 	{0x7,   "L2L3_snoop_inv_sh"},
3730Sstevel@tonic-gate 	{0x8,   "IC_L2_req"},
3740Sstevel@tonic-gate 	{0x9,   "DC_rd_miss"},
3750Sstevel@tonic-gate 	{0xa,   "L2_hit_I_state_sh"},
3760Sstevel@tonic-gate 	{0xb,   "L3_write_miss_RTO"},
3770Sstevel@tonic-gate 	{0xc,   "L2_miss"},
3780Sstevel@tonic-gate 	{0xd,   "SI_owned_sh"},
3790Sstevel@tonic-gate 	{0xe,   "SI_RTO_src_data"},
3800Sstevel@tonic-gate 	{0xf,   "SW_pf_duplicate"},
3810Sstevel@tonic-gate 	{0x10,  "IU_stat_jmp_mispred"},
3820Sstevel@tonic-gate 	{0x11,  "ITLB_miss"},
3830Sstevel@tonic-gate 	{0x12,  "DTLB_miss"},
3840Sstevel@tonic-gate 	{0x13,  "WC_miss"},
3850Sstevel@tonic-gate 	{0x14,  "IC_fill"},
3860Sstevel@tonic-gate 	{0x15,  "IU_stat_ret_mispred"},
3870Sstevel@tonic-gate 	{0x16,  "Re_L3_miss"},
3880Sstevel@tonic-gate 	{0x17,  "Re_PFQ_full"},
3890Sstevel@tonic-gate 	{0x18,  "PC_soft_hit"},
3900Sstevel@tonic-gate 	{0x19,  "PC_inv"},
3910Sstevel@tonic-gate 	{0x1a,  "PC_hard_hit"},
3920Sstevel@tonic-gate 	{0x1b,  "IC_pf"},
3930Sstevel@tonic-gate 	{0x1c,  "SW_count_NOP"},
3940Sstevel@tonic-gate 	{0x1d,  "IU_stat_br_miss_untaken"},
3950Sstevel@tonic-gate 	{0x1e,  "IU_stat_br_count_taken"},
3960Sstevel@tonic-gate 	{0x1f,  "PC_miss"},
3970Sstevel@tonic-gate 	{0x20,  "MC_writes_0_sh"},
3980Sstevel@tonic-gate 	{0x21,  "MC_writes_1_sh"},
3990Sstevel@tonic-gate 	{0x22,  "MC_writes_2_sh"},
4000Sstevel@tonic-gate 	{0x23,  "MC_writes_3_sh"},
4010Sstevel@tonic-gate 	{0x24,  "MC_stalls_1_sh"},
4020Sstevel@tonic-gate 	{0x25,  "MC_stalls_3_sh"},
4030Sstevel@tonic-gate 	{0x26,  "Re_RAW_miss"},
4040Sstevel@tonic-gate 	{0x27,  "FM_pipe_completion"},
4050Sstevel@tonic-gate 	{0x28,  "SSM_L3_miss_mtag_remote"},
4060Sstevel@tonic-gate 	{0x29,  "SSM_L3_miss_remote"},
4070Sstevel@tonic-gate 	{0x2a,  "SW_pf_exec"},
4080Sstevel@tonic-gate 	{0x2b,  "SW_pf_str_exec"},
4090Sstevel@tonic-gate 	{0x2c,  "SW_pf_dropped"},
4100Sstevel@tonic-gate 	{0x2d,  "SW_pf_L2_installed"},
4110Sstevel@tonic-gate 	{0x2f,  "L2_HW_pf_miss"},
4120Sstevel@tonic-gate 	{0x31,  "L3_miss"},
4130Sstevel@tonic-gate 	{0x32,  "L3_IC_miss"},
4140Sstevel@tonic-gate 	{0x33,  "L3_SW_pf_miss"},
4150Sstevel@tonic-gate 	{0x34,  "L3_hit_other_half"},
4160Sstevel@tonic-gate 	{0x35,  "L3_wb"},
4170Sstevel@tonic-gate 	{0x36,  "L3_wb_sh"},
4180Sstevel@tonic-gate 	{0x37,  "L2L3_snoop_cb_sh"},
4190Sstevel@tonic-gate 	{NT_END, ""}
4200Sstevel@tonic-gate };
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate static const struct nametable US12_names1[] = {
4230Sstevel@tonic-gate 	USall_EVENTS_1,
4240Sstevel@tonic-gate 	{0x3,	"Dispatch0_FP_use"},
4250Sstevel@tonic-gate 	{0x8,	"IC_hit"},
4260Sstevel@tonic-gate 	{0x9,	"DC_rd_hit"},
4270Sstevel@tonic-gate 	{0xa,	"DC_wr_hit"},
4280Sstevel@tonic-gate 	{0xb,	"Load_use_RAW"},
4290Sstevel@tonic-gate 	{0xc,	"EC_hit"},
4300Sstevel@tonic-gate 	{0xf,	"EC_ic_hit"},
4310Sstevel@tonic-gate 	{NT_END, ""}
4320Sstevel@tonic-gate };
4330Sstevel@tonic-gate 
4340Sstevel@tonic-gate static const struct nametable *US12_names[2] = {
4350Sstevel@tonic-gate 	US12_names0,
4360Sstevel@tonic-gate 	US12_names1
4370Sstevel@tonic-gate };
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate static const struct nametable *US3_names[2] = {
4400Sstevel@tonic-gate 	US3_names0,
4410Sstevel@tonic-gate 	US3_names1
4420Sstevel@tonic-gate };
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate static const struct nametable *US3_PLUS_names[2] = {
4450Sstevel@tonic-gate 	US3_PLUS_names0,
4460Sstevel@tonic-gate 	US3_PLUS_names1
4470Sstevel@tonic-gate };
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate static const struct nametable *US4_PLUS_names[2] = {
4500Sstevel@tonic-gate 	US4_PLUS_names0,
4510Sstevel@tonic-gate 	US4_PLUS_names1
4520Sstevel@tonic-gate };
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate static const struct nametable *US3_I_names[2] = {
4550Sstevel@tonic-gate 	US3_I_names0,
4560Sstevel@tonic-gate 	US3_I_names1
4570Sstevel@tonic-gate };
4580Sstevel@tonic-gate 
459*7640SJonathan.Haslam@Sun.COM static const us_generic_event_t US12_generic_names0[] = {
460*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_cyc",  "Cycle_cnt" },
461*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_ins",  "Instr_cnt" },
462*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_iis",  "Instr_cnt" },
463*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l1_dcr",   "DC_rd" },
464*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l1_dcw",   "DC_wr" },
465*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l1_ica",   "IC_ref" },
466*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l2_tca",   "EC_ref" },
467*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l2_dch",   "EC_rd_hit" },
468*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_ca_inv",   "EC_snoop_inv" },
469*7640SJonathan.Haslam@Sun.COM 	CPC_GEN_END
470*7640SJonathan.Haslam@Sun.COM };
471*7640SJonathan.Haslam@Sun.COM 
472*7640SJonathan.Haslam@Sun.COM static const us_generic_event_t US12_generic_names1[] = {
473*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_cyc",  "Cycle_cnt" },
474*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_ins",  "Instr_cnt" },
475*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_iis",  "Instr_cnt" },
476*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_br_msp",   "Dispatch0_mispred" },
477*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_ca_snp",   "EC_snoop_cb" },
478*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l1_ich",   "IC_hit" },
479*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l2_tch",   "EC_hit" },
480*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l2_ich",   "EC_ic_hit" },
481*7640SJonathan.Haslam@Sun.COM 	CPC_GEN_END
482*7640SJonathan.Haslam@Sun.COM };
483*7640SJonathan.Haslam@Sun.COM 
484*7640SJonathan.Haslam@Sun.COM static const us_generic_event_t US3_generic_names0[] = {
485*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_cyc",  "Cycle_cnt" },
486*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_ins",  "Instr_cnt" },
487*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_iis",  "Instr_cnt" },
488*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_fad_ins",  "FA_pipe_completion" },
489*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l1_dcr",   "DC_rd" },
490*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l1_dcw",   "DC_wr" },
491*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l1_ica",   "IC_ref" },
492*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l2_tca",   "EC_ref" },
493*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l2_ldm",   "EC_rd_miss" },
494*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_ca_inv",   "EC_snoop_inv" },
495*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_br_tkn",   "IU_Stat_Br_count_taken" },
496*7640SJonathan.Haslam@Sun.COM 	CPC_GEN_END
497*7640SJonathan.Haslam@Sun.COM };
498*7640SJonathan.Haslam@Sun.COM 
499*7640SJonathan.Haslam@Sun.COM static const us_generic_event_t US3_generic_names1[] = {
500*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_cyc",  "Cycle_cnt" },
501*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_ins",  "Instr_cnt" },
502*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_iis",  "Instr_cnt" },
503*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_fml_ins",  "FM_pipe_completion" },
504*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l1_icm",   "IC_miss" },
505*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l1_ldm",   "DC_rd_miss" },
506*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l1_stm",   "DC_wr_miss" },
507*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l2_tcm",   "EC_misses" },
508*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l2_icm",   "EC_ic_miss" },
509*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tlb_dm",   "DTLB_miss" },
510*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tlb_im",   "ITLB_miss" },
511*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_br_ntk",   "IU_Stat_Br_count_untaken" },
512*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_br_msp",   "Dispatch0_mispred" },
513*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_ca_snp",   "EC_snoop_cb" },
514*7640SJonathan.Haslam@Sun.COM 	CPC_GEN_END
515*7640SJonathan.Haslam@Sun.COM };
516*7640SJonathan.Haslam@Sun.COM 
517*7640SJonathan.Haslam@Sun.COM static const us_generic_event_t US4_PLUS_generic_names0[] = {
518*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_cyc",  "Cycle_cnt" },
519*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_ins",  "Instr_cnt" },
520*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_iis",  "Instr_cnt" },
521*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_fma_ins",  "FA_pipe_completion" },
522*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l1_dcr",   "DC_rd" },
523*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l1_stm",   "DC_wr_miss" },
524*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l1_ica",   "IC_ref" },
525*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l2_tca",   "L2_ref" },
526*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l2_ldm",   "L2_rd_miss" },
527*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l2_icm",   "L2_IC_miss" },
528*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l2_stm",   "L2_write_miss" },
529*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l3_ldm",   "L3_rd_miss" },
530*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_br_ntk",   "IU_stat_br_count_untaken" },
531*7640SJonathan.Haslam@Sun.COM 	CPC_GEN_END
532*7640SJonathan.Haslam@Sun.COM };
533*7640SJonathan.Haslam@Sun.COM 
534*7640SJonathan.Haslam@Sun.COM static const us_generic_event_t US4_PLUS_generic_names1[] = {
535*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_cyc", "Cycle_cnt" },
536*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_ins", "Instr_cnt" },
537*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tot_iis",  "Instr_cnt" },
538*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_fml_ins",  "FM_pipe_completion" },
539*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l1_icm",   "IC_L2_req" },
540*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l1_ldm",   "DC_rd_miss" },
541*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l1_dcw",   "DC_wr" },
542*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l2_tcm",   "L2_miss" },
543*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l3_tcm",   "L3_miss" },
544*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_l3_icm",   "L3_IC_miss" },
545*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tlb_im",   "ITLB_miss" },
546*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_tlb_dm",   "DTLB_miss" },
547*7640SJonathan.Haslam@Sun.COM 	{ "PAPI_br_tkn",   "IU_stat_br_count_taken" },
548*7640SJonathan.Haslam@Sun.COM 	CPC_GEN_END
549*7640SJonathan.Haslam@Sun.COM };
550*7640SJonathan.Haslam@Sun.COM 
551*7640SJonathan.Haslam@Sun.COM static const us_generic_event_t *US12_generic_names[2] = {
552*7640SJonathan.Haslam@Sun.COM 	US12_generic_names0,
553*7640SJonathan.Haslam@Sun.COM 	US12_generic_names1
554*7640SJonathan.Haslam@Sun.COM };
555*7640SJonathan.Haslam@Sun.COM 
556*7640SJonathan.Haslam@Sun.COM static const us_generic_event_t *US3_generic_names[2] = {
557*7640SJonathan.Haslam@Sun.COM 	US3_generic_names0,
558*7640SJonathan.Haslam@Sun.COM 	US3_generic_names1
559*7640SJonathan.Haslam@Sun.COM };
560*7640SJonathan.Haslam@Sun.COM 
561*7640SJonathan.Haslam@Sun.COM static const us_generic_event_t *US4_PLUS_generic_names[2] = {
562*7640SJonathan.Haslam@Sun.COM 	US4_PLUS_generic_names0,
563*7640SJonathan.Haslam@Sun.COM 	US4_PLUS_generic_names1
564*7640SJonathan.Haslam@Sun.COM };
565*7640SJonathan.Haslam@Sun.COM 
5660Sstevel@tonic-gate static const struct nametable **events;
567*7640SJonathan.Haslam@Sun.COM static const us_generic_event_t **generic_events;
5680Sstevel@tonic-gate static const char *us_impl_name;
5690Sstevel@tonic-gate static const char *us_cpuref;
5700Sstevel@tonic-gate static char *pic_events[2];
5710Sstevel@tonic-gate static uint16_t pcr_pic_mask;
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate #define	CPU_REF_URL " Documentation for Sun processors can be found at: " \
5740Sstevel@tonic-gate 			"http://www.sun.com/processors/manuals"
5750Sstevel@tonic-gate 
5760Sstevel@tonic-gate static const char *us_2_ref = "See the \"UltraSPARC I/II User\'s Manual\" "
5770Sstevel@tonic-gate 			"(Part No. 802-7220-02) "
5780Sstevel@tonic-gate 			"for descriptions of these events." CPU_REF_URL;
5790Sstevel@tonic-gate 
5800Sstevel@tonic-gate static const char *us_3cu_ref = "See the \"UltraSPARC III Cu User's Manual\" "
5810Sstevel@tonic-gate 			"for descriptions of these events." CPU_REF_URL;
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate static const char *us4_plus_ref = "See the \"UltraSPARC IV+ User's Manual\" "
5840Sstevel@tonic-gate 			"for descriptions of these events." CPU_REF_URL;
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate static const char *us_3i_ref = "See the \"UltraSPARC IIIi User's Manual\"  "
5870Sstevel@tonic-gate 			"for descriptions of these events." CPU_REF_URL;
5880Sstevel@tonic-gate 
5890Sstevel@tonic-gate static int
us_pcbe_init(void)5900Sstevel@tonic-gate us_pcbe_init(void)
5910Sstevel@tonic-gate {
592*7640SJonathan.Haslam@Sun.COM 	const struct nametable		*n;
593*7640SJonathan.Haslam@Sun.COM 	const us_generic_event_t	*gevp;
594*7640SJonathan.Haslam@Sun.COM 	int				i;
595*7640SJonathan.Haslam@Sun.COM 	size_t				size;
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate 	/*
5980Sstevel@tonic-gate 	 * Discover type of CPU
5990Sstevel@tonic-gate 	 *
6000Sstevel@tonic-gate 	 * Point nametable to that CPU's table
6010Sstevel@tonic-gate 	 */
6020Sstevel@tonic-gate 	switch (ULTRA_VER_IMPL(ultra_getver())) {
6030Sstevel@tonic-gate 	case SPITFIRE_IMPL:
6040Sstevel@tonic-gate 	case BLACKBIRD_IMPL:
6050Sstevel@tonic-gate 	case SABRE_IMPL:
6060Sstevel@tonic-gate 	case HUMMBRD_IMPL:
6070Sstevel@tonic-gate 		events = US12_names;
608*7640SJonathan.Haslam@Sun.COM 		generic_events = US12_generic_names;
6090Sstevel@tonic-gate 		us_impl_name = "UltraSPARC I&II";
6100Sstevel@tonic-gate 		us_cpuref = us_2_ref;
6110Sstevel@tonic-gate 		pcr_pic_mask = CPC_ULTRA2_PCR_PIC_MASK;
6120Sstevel@tonic-gate 		us_pcbe_ops.pcbe_caps &= ~CPC_CAP_OVERFLOW_INTERRUPT;
6130Sstevel@tonic-gate 		break;
6140Sstevel@tonic-gate 	case CHEETAH_IMPL:
6150Sstevel@tonic-gate 		events = US3_names;
616*7640SJonathan.Haslam@Sun.COM 		generic_events = US3_generic_names;
6170Sstevel@tonic-gate 		us_impl_name = "UltraSPARC III";
6180Sstevel@tonic-gate 		us_cpuref = us_3cu_ref;
6190Sstevel@tonic-gate 		pcr_pic_mask = CPC_ULTRA3_PCR_PIC_MASK;
6200Sstevel@tonic-gate 		break;
6210Sstevel@tonic-gate 	case CHEETAH_PLUS_IMPL:
6220Sstevel@tonic-gate 	case JAGUAR_IMPL:
6230Sstevel@tonic-gate 		events = US3_PLUS_names;
624*7640SJonathan.Haslam@Sun.COM 		generic_events = US3_generic_names;
6250Sstevel@tonic-gate 		us_impl_name = "UltraSPARC III+ & IV";
6260Sstevel@tonic-gate 		us_cpuref = us_3cu_ref;
6270Sstevel@tonic-gate 		pcr_pic_mask = CPC_ULTRA3_PCR_PIC_MASK;
6280Sstevel@tonic-gate 		break;
6290Sstevel@tonic-gate 	case PANTHER_IMPL:
6300Sstevel@tonic-gate 		events = US4_PLUS_names;
631*7640SJonathan.Haslam@Sun.COM 		generic_events = US4_PLUS_generic_names;
6320Sstevel@tonic-gate 		us_impl_name = "UltraSPARC IV+";
6330Sstevel@tonic-gate 		us_cpuref = us4_plus_ref;
6340Sstevel@tonic-gate 		pcr_pic_mask = CPC_ULTRA3_PCR_PIC_MASK;
6350Sstevel@tonic-gate 		break;
6360Sstevel@tonic-gate 	case JALAPENO_IMPL:
6370Sstevel@tonic-gate 	case SERRANO_IMPL:
6380Sstevel@tonic-gate 		events = US3_I_names;
639*7640SJonathan.Haslam@Sun.COM 		generic_events = US3_generic_names;
6400Sstevel@tonic-gate 		us_impl_name = "UltraSPARC IIIi & IIIi+";
6410Sstevel@tonic-gate 		us_cpuref = us_3i_ref;
6420Sstevel@tonic-gate 		pcr_pic_mask = CPC_ULTRA3_PCR_PIC_MASK;
6430Sstevel@tonic-gate 		break;
6440Sstevel@tonic-gate 	default:
6450Sstevel@tonic-gate 		return (-1);
6460Sstevel@tonic-gate 	}
6470Sstevel@tonic-gate 
6480Sstevel@tonic-gate 	/*
6490Sstevel@tonic-gate 	 * Initialize the list of events for each PIC.
6500Sstevel@tonic-gate 	 * Do two passes: one to compute the size necessary and another
6510Sstevel@tonic-gate 	 * to copy the strings. Need room for event, comma, and NULL terminator.
6520Sstevel@tonic-gate 	 */
6530Sstevel@tonic-gate 	for (i = 0; i < 2; i++) {
6540Sstevel@tonic-gate 		size = 0;
6550Sstevel@tonic-gate 		for (n = events[i]; n->bits != NT_END; n++)
6560Sstevel@tonic-gate 			size += strlen(n->name) + 1;
657*7640SJonathan.Haslam@Sun.COM 		for (gevp = generic_events[i]; gevp->name != NULL; gevp++)
658*7640SJonathan.Haslam@Sun.COM 			size += strlen(gevp->name) + 1;
6590Sstevel@tonic-gate 		pic_events[i] = kmem_alloc(size + 1, KM_SLEEP);
6600Sstevel@tonic-gate 		*pic_events[i] = '\0';
6610Sstevel@tonic-gate 		for (n = events[i]; n->bits != NT_END; n++) {
6620Sstevel@tonic-gate 			(void) strcat(pic_events[i], n->name);
6630Sstevel@tonic-gate 			(void) strcat(pic_events[i], ",");
6640Sstevel@tonic-gate 		}
665*7640SJonathan.Haslam@Sun.COM 		for (gevp = generic_events[i]; gevp->name != NULL; gevp++) {
666*7640SJonathan.Haslam@Sun.COM 			(void) strcat(pic_events[i], gevp->name);
667*7640SJonathan.Haslam@Sun.COM 			(void) strcat(pic_events[i], ",");
668*7640SJonathan.Haslam@Sun.COM 		}
669*7640SJonathan.Haslam@Sun.COM 
6700Sstevel@tonic-gate 		/*
6710Sstevel@tonic-gate 		 * Remove trailing comma.
6720Sstevel@tonic-gate 		 */
6730Sstevel@tonic-gate 		pic_events[i][size - 1] = '\0';
6740Sstevel@tonic-gate 	}
6750Sstevel@tonic-gate 
6760Sstevel@tonic-gate 	return (0);
6770Sstevel@tonic-gate }
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate static uint_t
us_pcbe_ncounters(void)6800Sstevel@tonic-gate us_pcbe_ncounters(void)
6810Sstevel@tonic-gate {
6820Sstevel@tonic-gate 	return (2);
6830Sstevel@tonic-gate }
6840Sstevel@tonic-gate 
6850Sstevel@tonic-gate static const char *
us_pcbe_impl_name(void)6860Sstevel@tonic-gate us_pcbe_impl_name(void)
6870Sstevel@tonic-gate {
6880Sstevel@tonic-gate 	return (us_impl_name);
6890Sstevel@tonic-gate }
6900Sstevel@tonic-gate 
6910Sstevel@tonic-gate static const char *
us_pcbe_cpuref(void)6920Sstevel@tonic-gate us_pcbe_cpuref(void)
6930Sstevel@tonic-gate {
6940Sstevel@tonic-gate 	return (us_cpuref);
6950Sstevel@tonic-gate }
6960Sstevel@tonic-gate 
6970Sstevel@tonic-gate static char *
us_pcbe_list_events(uint_t picnum)6980Sstevel@tonic-gate us_pcbe_list_events(uint_t picnum)
6990Sstevel@tonic-gate {
7000Sstevel@tonic-gate 	ASSERT(picnum >= 0 && picnum < cpc_ncounters);
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate 	return (pic_events[picnum]);
7030Sstevel@tonic-gate }
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate static char *
us_pcbe_list_attrs(void)7060Sstevel@tonic-gate us_pcbe_list_attrs(void)
7070Sstevel@tonic-gate {
7080Sstevel@tonic-gate 	return ("");
7090Sstevel@tonic-gate }
7100Sstevel@tonic-gate 
711*7640SJonathan.Haslam@Sun.COM static const us_generic_event_t *
find_generic_event(int regno,char * name)712*7640SJonathan.Haslam@Sun.COM find_generic_event(int regno, char *name)
713*7640SJonathan.Haslam@Sun.COM {
714*7640SJonathan.Haslam@Sun.COM 	const us_generic_event_t *gevp;
715*7640SJonathan.Haslam@Sun.COM 
716*7640SJonathan.Haslam@Sun.COM 	for (gevp = generic_events[regno]; gevp->name != NULL; gevp++)
717*7640SJonathan.Haslam@Sun.COM 		if (strcmp(name, gevp->name) == 0)
718*7640SJonathan.Haslam@Sun.COM 			return (gevp);
719*7640SJonathan.Haslam@Sun.COM 
720*7640SJonathan.Haslam@Sun.COM 	return (NULL);
721*7640SJonathan.Haslam@Sun.COM }
722*7640SJonathan.Haslam@Sun.COM 
7230Sstevel@tonic-gate static const struct nametable *
find_event(int regno,char * name)7240Sstevel@tonic-gate find_event(int regno, char *name)
7250Sstevel@tonic-gate {
7260Sstevel@tonic-gate 	const struct nametable *n;
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate 	n = events[regno];
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate 	for (; n->bits != NT_END; n++)
7310Sstevel@tonic-gate 		if (strcmp(name, n->name) == 0)
7320Sstevel@tonic-gate 			return (n);
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 	return (NULL);
7350Sstevel@tonic-gate }
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate static uint64_t
us_pcbe_event_coverage(char * event)7380Sstevel@tonic-gate us_pcbe_event_coverage(char *event)
7390Sstevel@tonic-gate {
7400Sstevel@tonic-gate 	uint64_t bitmap = 0;
7410Sstevel@tonic-gate 
742*7640SJonathan.Haslam@Sun.COM 	if ((find_event(0, event) != NULL) ||
743*7640SJonathan.Haslam@Sun.COM 	    (find_generic_event(0, event) != NULL))
7440Sstevel@tonic-gate 		bitmap = 0x1;
745*7640SJonathan.Haslam@Sun.COM 	if ((find_event(1, event) != NULL) ||
746*7640SJonathan.Haslam@Sun.COM 	    (find_generic_event(1, event) != NULL))
7470Sstevel@tonic-gate 		bitmap |= 0x2;
7480Sstevel@tonic-gate 
7490Sstevel@tonic-gate 	return (bitmap);
7500Sstevel@tonic-gate }
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate /*
7530Sstevel@tonic-gate  * These processors cannot tell which counter overflowed. The PCBE interface
7540Sstevel@tonic-gate  * requires such processors to act as if _all_ counters had overflowed.
7550Sstevel@tonic-gate  */
7560Sstevel@tonic-gate static uint64_t
us_pcbe_overflow_bitmap(void)7570Sstevel@tonic-gate us_pcbe_overflow_bitmap(void)
7580Sstevel@tonic-gate {
7590Sstevel@tonic-gate 	return (0x3);
7600Sstevel@tonic-gate }
7610Sstevel@tonic-gate 
7620Sstevel@tonic-gate /*ARGSUSED*/
7630Sstevel@tonic-gate static int
us_pcbe_configure(uint_t picnum,char * event,uint64_t preset,uint32_t flags,uint_t nattrs,kcpc_attr_t * attrs,void ** data,void * token)7640Sstevel@tonic-gate us_pcbe_configure(uint_t picnum, char *event, uint64_t preset, uint32_t flags,
7650Sstevel@tonic-gate     uint_t nattrs, kcpc_attr_t *attrs, void **data, void *token)
7660Sstevel@tonic-gate {
767*7640SJonathan.Haslam@Sun.COM 	us_pcbe_config_t		*conf;
768*7640SJonathan.Haslam@Sun.COM 	const struct nametable		*n;
769*7640SJonathan.Haslam@Sun.COM 	const us_generic_event_t	*gevp;
770*7640SJonathan.Haslam@Sun.COM 	us_pcbe_config_t		*other_config;
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate 	/*
7730Sstevel@tonic-gate 	 * If we've been handed an existing configuration, we need only preset
7740Sstevel@tonic-gate 	 * the counter value.
7750Sstevel@tonic-gate 	 */
7760Sstevel@tonic-gate 	if (*data != NULL) {
7770Sstevel@tonic-gate 		conf = *data;
7780Sstevel@tonic-gate 		conf->us_pic = (uint32_t)preset;
7790Sstevel@tonic-gate 		return (0);
7800Sstevel@tonic-gate 	}
7810Sstevel@tonic-gate 
7820Sstevel@tonic-gate 	if (picnum < 0 || picnum > 1)
7830Sstevel@tonic-gate 		return (CPC_INVALID_PICNUM);
7840Sstevel@tonic-gate 
7850Sstevel@tonic-gate 	if (nattrs != 0)
7860Sstevel@tonic-gate 		return (CPC_INVALID_ATTRIBUTE);
7870Sstevel@tonic-gate 
7880Sstevel@tonic-gate 	/*
7890Sstevel@tonic-gate 	 * Find other requests that will be programmed with this one, and ensure
7900Sstevel@tonic-gate 	 * the flags don't conflict.
7910Sstevel@tonic-gate 	 */
7920Sstevel@tonic-gate 	if (((other_config = kcpc_next_config(token, NULL, NULL)) != NULL) &&
7930Sstevel@tonic-gate 	    (other_config->us_flags != flags))
7940Sstevel@tonic-gate 		return (CPC_CONFLICTING_REQS);
7950Sstevel@tonic-gate 
796*7640SJonathan.Haslam@Sun.COM 	if ((n = find_event(picnum, event)) == NULL) {
797*7640SJonathan.Haslam@Sun.COM 		if ((gevp = find_generic_event(picnum, event)) != NULL) {
798*7640SJonathan.Haslam@Sun.COM 			n = find_event(picnum, gevp->event);
799*7640SJonathan.Haslam@Sun.COM 			ASSERT(n != NULL);
800*7640SJonathan.Haslam@Sun.COM 		} else {
801*7640SJonathan.Haslam@Sun.COM 			return (CPC_INVALID_EVENT);
802*7640SJonathan.Haslam@Sun.COM 		}
803*7640SJonathan.Haslam@Sun.COM 	}
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate 	conf = kmem_alloc(sizeof (us_pcbe_config_t), KM_SLEEP);
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate 	conf->us_picno = picnum;
8080Sstevel@tonic-gate 	conf->us_bits = (uint32_t)n->bits;
8090Sstevel@tonic-gate 	conf->us_flags = flags;
8100Sstevel@tonic-gate 	conf->us_pic = (uint32_t)preset;
8110Sstevel@tonic-gate 
8120Sstevel@tonic-gate 	*data = conf;
8130Sstevel@tonic-gate 	return (0);
8140Sstevel@tonic-gate }
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate static void
us_pcbe_program(void * token)8170Sstevel@tonic-gate us_pcbe_program(void *token)
8180Sstevel@tonic-gate {
8190Sstevel@tonic-gate 	us_pcbe_config_t	*pic0;
8200Sstevel@tonic-gate 	us_pcbe_config_t	*pic1;
8210Sstevel@tonic-gate 	us_pcbe_config_t	*tmp;
8220Sstevel@tonic-gate 	us_pcbe_config_t	empty = { 1, 0x1c, 0, 0 }; /* SW_count_1 */
8230Sstevel@tonic-gate 	uint64_t		pcr;
8240Sstevel@tonic-gate 	uint64_t		curpic;
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate 	if ((pic0 = (us_pcbe_config_t *)kcpc_next_config(token, NULL, NULL)) ==
8270Sstevel@tonic-gate 	    NULL)
8280Sstevel@tonic-gate 		panic("us_pcbe: token %p has no configs", token);
8290Sstevel@tonic-gate 
8300Sstevel@tonic-gate 	if ((pic1 = kcpc_next_config(token, pic0, NULL)) == NULL) {
8310Sstevel@tonic-gate 		pic1 = &empty;
8320Sstevel@tonic-gate 		empty.us_flags = pic0->us_flags;
8330Sstevel@tonic-gate 	}
8340Sstevel@tonic-gate 
8350Sstevel@tonic-gate 	if (pic0->us_picno != 0) {
8360Sstevel@tonic-gate 		/*
8370Sstevel@tonic-gate 		 * pic0 is counter 1, so if we need the empty config it should
8380Sstevel@tonic-gate 		 * be counter 0.
8390Sstevel@tonic-gate 		 */
8400Sstevel@tonic-gate 		empty.us_picno = 0;
8410Sstevel@tonic-gate 		empty.us_bits = 0x14; /* SW_count_0 - won't overflow */
8420Sstevel@tonic-gate 		tmp = pic0;
8430Sstevel@tonic-gate 		pic0 = pic1;
8440Sstevel@tonic-gate 		pic1 = tmp;
8450Sstevel@tonic-gate 	}
8460Sstevel@tonic-gate 
8470Sstevel@tonic-gate 	if (pic0->us_picno != 0 || pic1->us_picno != 1)
8480Sstevel@tonic-gate 		panic("us_pcbe: bad config on token %p\n", token);
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate 	/*
8510Sstevel@tonic-gate 	 * UltraSPARC does not allow pic0 to be configured differently
8520Sstevel@tonic-gate 	 * from pic1. If the flags on these two configurations are
8530Sstevel@tonic-gate 	 * different, they are incompatible. This condition should be
8540Sstevel@tonic-gate 	 * caught at configure time.
8550Sstevel@tonic-gate 	 */
8560Sstevel@tonic-gate 	ASSERT(pic0->us_flags == pic1->us_flags);
8570Sstevel@tonic-gate 
8580Sstevel@tonic-gate 	ultra_setpcr(allstopped);
8590Sstevel@tonic-gate 	ultra_setpic(((uint64_t)pic1->us_pic << 32) | (uint64_t)pic0->us_pic);
8600Sstevel@tonic-gate 
8610Sstevel@tonic-gate 	pcr = (pic0->us_bits & pcr_pic_mask) <<
8620Sstevel@tonic-gate 	    CPC_ULTRA_PCR_PIC0_SHIFT;
8630Sstevel@tonic-gate 	pcr |= (pic1->us_bits & pcr_pic_mask) <<
8640Sstevel@tonic-gate 	    CPC_ULTRA_PCR_PIC1_SHIFT;
8650Sstevel@tonic-gate 
8660Sstevel@tonic-gate 	if (pic0->us_flags & CPC_COUNT_USER)
8670Sstevel@tonic-gate 		pcr |= (1ull << CPC_ULTRA_PCR_USR);
8680Sstevel@tonic-gate 	if (pic0->us_flags & CPC_COUNT_SYSTEM)
8690Sstevel@tonic-gate 		pcr |= (1ull << CPC_ULTRA_PCR_SYS);
8700Sstevel@tonic-gate 
8710Sstevel@tonic-gate 	DTRACE_PROBE1(ultra__pcr, uint64_t, pcr);
8720Sstevel@tonic-gate 
8730Sstevel@tonic-gate 	ultra_setpcr(pcr);
8740Sstevel@tonic-gate 
8750Sstevel@tonic-gate 	/*
8760Sstevel@tonic-gate 	 * On UltraSPARC, only read-to-read counts are accurate. We cannot
8770Sstevel@tonic-gate 	 * expect the value we wrote into the PIC, above, to be there after
8780Sstevel@tonic-gate 	 * starting the counter. We must sample the counter value now and use
8790Sstevel@tonic-gate 	 * that as the baseline for future samples.
8800Sstevel@tonic-gate 	 */
8810Sstevel@tonic-gate 	curpic = ultra_getpic();
8820Sstevel@tonic-gate 	pic0->us_pic = (uint32_t)(curpic & PIC0_MASK);
8830Sstevel@tonic-gate 	pic1->us_pic = (uint32_t)(curpic >> 32);
8840Sstevel@tonic-gate }
8850Sstevel@tonic-gate 
8860Sstevel@tonic-gate static void
us_pcbe_allstop(void)8870Sstevel@tonic-gate us_pcbe_allstop(void)
8880Sstevel@tonic-gate {
8890Sstevel@tonic-gate 	ultra_setpcr(allstopped);
8900Sstevel@tonic-gate }
8910Sstevel@tonic-gate 
8920Sstevel@tonic-gate 
8930Sstevel@tonic-gate static void
us_pcbe_sample(void * token)8940Sstevel@tonic-gate us_pcbe_sample(void *token)
8950Sstevel@tonic-gate {
8960Sstevel@tonic-gate 	uint64_t		curpic;
8970Sstevel@tonic-gate 	int64_t			diff;
8980Sstevel@tonic-gate 	uint64_t		*pic0_data;
8990Sstevel@tonic-gate 	uint64_t		*pic1_data;
9000Sstevel@tonic-gate 	uint64_t		*dtmp;
9010Sstevel@tonic-gate 	uint64_t		tmp;
9020Sstevel@tonic-gate 	us_pcbe_config_t	*pic0;
9030Sstevel@tonic-gate 	us_pcbe_config_t	*pic1;
9040Sstevel@tonic-gate 	us_pcbe_config_t	empty = { 1, 0, 0, 0 };
9050Sstevel@tonic-gate 	us_pcbe_config_t	*ctmp;
9060Sstevel@tonic-gate 
9070Sstevel@tonic-gate 	curpic = ultra_getpic();
9080Sstevel@tonic-gate 
9090Sstevel@tonic-gate 	if ((pic0 = kcpc_next_config(token, NULL, &pic0_data)) == NULL)
9100Sstevel@tonic-gate 		panic("us_pcbe: token %p has no configs", token);
9110Sstevel@tonic-gate 
9120Sstevel@tonic-gate 	if ((pic1 = kcpc_next_config(token, pic0, &pic1_data)) == NULL) {
9130Sstevel@tonic-gate 		pic1 = &empty;
9140Sstevel@tonic-gate 		pic1_data = &tmp;
9150Sstevel@tonic-gate 	}
9160Sstevel@tonic-gate 
9170Sstevel@tonic-gate 	if (pic0->us_picno != 0) {
9180Sstevel@tonic-gate 		empty.us_picno = 0;
9190Sstevel@tonic-gate 		ctmp = pic0;
9200Sstevel@tonic-gate 		pic0 = pic1;
9210Sstevel@tonic-gate 		pic1 = ctmp;
9220Sstevel@tonic-gate 		dtmp = pic0_data;
9230Sstevel@tonic-gate 		pic0_data = pic1_data;
9240Sstevel@tonic-gate 		pic1_data = dtmp;
9250Sstevel@tonic-gate 	}
9260Sstevel@tonic-gate 
9270Sstevel@tonic-gate 	if (pic0->us_picno != 0 || pic1->us_picno != 1)
9280Sstevel@tonic-gate 		panic("us_pcbe: bad config on token %p\n", token);
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate 	diff = (curpic & PIC0_MASK) - (uint64_t)pic0->us_pic;
9310Sstevel@tonic-gate 	if (diff < 0)
9320Sstevel@tonic-gate 		diff += (1ll << 32);
9330Sstevel@tonic-gate 	*pic0_data += diff;
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 	diff = (curpic >> 32) - (uint64_t)pic1->us_pic;
9360Sstevel@tonic-gate 	if (diff < 0)
9370Sstevel@tonic-gate 		diff += (1ll << 32);
9380Sstevel@tonic-gate 	*pic1_data += diff;
9390Sstevel@tonic-gate 
9400Sstevel@tonic-gate 	pic0->us_pic = (uint32_t)(curpic & PIC0_MASK);
9410Sstevel@tonic-gate 	pic1->us_pic = (uint32_t)(curpic >> 32);
9420Sstevel@tonic-gate }
9430Sstevel@tonic-gate 
9440Sstevel@tonic-gate static void
us_pcbe_free(void * config)9450Sstevel@tonic-gate us_pcbe_free(void *config)
9460Sstevel@tonic-gate {
9470Sstevel@tonic-gate 	kmem_free(config, sizeof (us_pcbe_config_t));
9480Sstevel@tonic-gate }
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 
9510Sstevel@tonic-gate static struct modlpcbe modlpcbe = {
9520Sstevel@tonic-gate 	&mod_pcbeops,
9537258Skk208521 	"UltraSPARC Performance Counters",
9540Sstevel@tonic-gate 	&us_pcbe_ops
9550Sstevel@tonic-gate };
9560Sstevel@tonic-gate 
9570Sstevel@tonic-gate static struct modlinkage modl = {
9580Sstevel@tonic-gate 	MODREV_1,
9590Sstevel@tonic-gate 	&modlpcbe,
9600Sstevel@tonic-gate };
9610Sstevel@tonic-gate 
9620Sstevel@tonic-gate int
_init(void)9630Sstevel@tonic-gate _init(void)
9640Sstevel@tonic-gate {
9650Sstevel@tonic-gate 	if (us_pcbe_init() != 0)
9660Sstevel@tonic-gate 		return (ENOTSUP);
9670Sstevel@tonic-gate 	return (mod_install(&modl));
9680Sstevel@tonic-gate }
9690Sstevel@tonic-gate 
9700Sstevel@tonic-gate int
_fini(void)9710Sstevel@tonic-gate _fini(void)
9720Sstevel@tonic-gate {
9730Sstevel@tonic-gate 	return (mod_remove(&modl));
9740Sstevel@tonic-gate }
9750Sstevel@tonic-gate 
9760Sstevel@tonic-gate int
_info(struct modinfo * mi)9770Sstevel@tonic-gate _info(struct modinfo *mi)
9780Sstevel@tonic-gate {
9790Sstevel@tonic-gate 	return (mod_info(&modl, mi));
9800Sstevel@tonic-gate }
981