17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <sys/types.h>
287c478bd9Sstevel@tonic-gate #include <string.h>
297c478bd9Sstevel@tonic-gate #include <alloca.h>
307c478bd9Sstevel@tonic-gate #include <stdlib.h>
317c478bd9Sstevel@tonic-gate #include <stdio.h>
327c478bd9Sstevel@tonic-gate #include <libintl.h>
337c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include "libcpc.h"
367c478bd9Sstevel@tonic-gate #include "libcpc_impl.h"
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate  * Configuration data for UltraSPARC performance counters.
407c478bd9Sstevel@tonic-gate  *
41*23961e2bSvb70745  * Definitions taken from [1], [2], [3]  [4] and [5].  See the references to
427c478bd9Sstevel@tonic-gate  * understand what any of these settings actually means.
437c478bd9Sstevel@tonic-gate  *
447c478bd9Sstevel@tonic-gate  * Note that in the current draft of [2], there is some re-use
457c478bd9Sstevel@tonic-gate  * of existing bit assignments in the various fields of the %pcr
467c478bd9Sstevel@tonic-gate  * register - this may change before FCS.
477c478bd9Sstevel@tonic-gate  *
487c478bd9Sstevel@tonic-gate  * The following are the Internal Documents. Customers need to be
497c478bd9Sstevel@tonic-gate  * told about the Public docs in cpc_getcpuref().
507c478bd9Sstevel@tonic-gate  * [1] "UltraSPARC I & II User's Manual," January 1997.
517c478bd9Sstevel@tonic-gate  * [2] "UltraSPARC-III Programmer's Reference Manual," April 1999.
527c478bd9Sstevel@tonic-gate  * [3] "Cheetah+ Programmer's Reference Manual," November 2000.
537c478bd9Sstevel@tonic-gate  * [4] "UltraSPARC-IIIi Programmer's Reference Manual," November 2000.
54*23961e2bSvb70745  * [5] "UltraSPARC-IV+ Programmer's Reference Manual," October 2004.
557c478bd9Sstevel@tonic-gate  */
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate #define	V_US12		(1u << 0)	/* specific to UltraSPARC 1 and 2 */
587c478bd9Sstevel@tonic-gate #define	V_US3		(1u << 1)	/* specific to UltraSPARC 3 */
597c478bd9Sstevel@tonic-gate #define	V_US3_PLUS	(1u << 2)	/* specific to UltraSPARC 3 PLUS */
607c478bd9Sstevel@tonic-gate #define	V_US3_I		(1u << 3)	/* specific to UltraSPARC-IIIi */
61*23961e2bSvb70745 #define	V_US4_PLUS	(1u << 4)	/* specific to UltraSPARC-IV+ */
627c478bd9Sstevel@tonic-gate #define	V_END		(1u << 31)
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate /*
657c478bd9Sstevel@tonic-gate  * map from "cpu version" to flag bits
667c478bd9Sstevel@tonic-gate  */
677c478bd9Sstevel@tonic-gate static const uint_t cpuvermap[] = {
687c478bd9Sstevel@tonic-gate 	V_US12,			/* CPC_ULTRA1 */
697c478bd9Sstevel@tonic-gate 	V_US12,			/* CPC_ULTRA2 */
707c478bd9Sstevel@tonic-gate 	V_US3,			/* CPC_ULTRA3 */
717c478bd9Sstevel@tonic-gate 	V_US3_PLUS,		/* CPC_ULTRA3_PLUS */
72*23961e2bSvb70745 	V_US3_I,		/* CPC_ULTRA3I */
73*23961e2bSvb70745 	V_US4_PLUS		/* CPC_ULTRA4_PLUS */
747c478bd9Sstevel@tonic-gate };
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate struct nametable {
777c478bd9Sstevel@tonic-gate 	const uint_t	ver;
787c478bd9Sstevel@tonic-gate 	const uint8_t	bits;
797c478bd9Sstevel@tonic-gate 	const char	*name;
807c478bd9Sstevel@tonic-gate };
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate /*
837c478bd9Sstevel@tonic-gate  * Definitions for counter 0
847c478bd9Sstevel@tonic-gate  */
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate #define	USall_EVENTS_0(v)					\
877c478bd9Sstevel@tonic-gate 	{v,		0x0,	"Cycle_cnt"},			\
887c478bd9Sstevel@tonic-gate 	{v,		0x1,	"Instr_cnt"},			\
897c478bd9Sstevel@tonic-gate 	{v,		0x2,	"Dispatch0_IC_miss"},		\
907c478bd9Sstevel@tonic-gate 	{v,		0x8,	"IC_ref"},			\
917c478bd9Sstevel@tonic-gate 	{v,		0x9,	"DC_rd"},			\
927c478bd9Sstevel@tonic-gate 	{v,		0xa,	"DC_wr"},			\
937c478bd9Sstevel@tonic-gate 	{v,		0xc,	"EC_ref"},			\
947c478bd9Sstevel@tonic-gate 	{v,		0xe,	"EC_snoop_inv"}
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate static const struct nametable US12_names0[] = {
977c478bd9Sstevel@tonic-gate 	USall_EVENTS_0(V_US12),
987c478bd9Sstevel@tonic-gate 	{V_US12,	0x3,	"Dispatch0_storeBuf"},
997c478bd9Sstevel@tonic-gate 	{V_US12,	0xb,	"Load_use"},
1007c478bd9Sstevel@tonic-gate 	{V_US12,	0xd,	"EC_write_hit_RDO"},
1017c478bd9Sstevel@tonic-gate 	{V_US12,	0xf,	"EC_rd_hit"},
1027c478bd9Sstevel@tonic-gate 	{V_END}
1037c478bd9Sstevel@tonic-gate };
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate #define	US3all_EVENTS_0(v)					\
1067c478bd9Sstevel@tonic-gate 	{v,		0x3,	"Dispatch0_br_target"},		\
1077c478bd9Sstevel@tonic-gate 	{v,		0x4,	"Dispatch0_2nd_br"},		\
1087c478bd9Sstevel@tonic-gate 	{v,		0x5,	"Rstall_storeQ"},		\
1097c478bd9Sstevel@tonic-gate 	{v,		0x6,	"Rstall_IU_use"},		\
1107c478bd9Sstevel@tonic-gate 	{v,		0xd,	"EC_write_hit_RTO"},		\
1117c478bd9Sstevel@tonic-gate 	{v,		0xf,	"EC_rd_miss"},			\
1127c478bd9Sstevel@tonic-gate 	{v,		0x10,	"PC_port0_rd"},			\
1137c478bd9Sstevel@tonic-gate 	{v,		0x11,	"SI_snoop"},			\
1147c478bd9Sstevel@tonic-gate 	{v,		0x12,	"SI_ciq_flow"},			\
1157c478bd9Sstevel@tonic-gate 	{v,		0x13,	"SI_owned"},			\
1167c478bd9Sstevel@tonic-gate 	{v,		0x14,	"SW_count_0"},			\
1177c478bd9Sstevel@tonic-gate 	{v,		0x15,	"IU_Stat_Br_miss_taken"},	\
1187c478bd9Sstevel@tonic-gate 	{v,		0x16,	"IU_Stat_Br_count_taken"},	\
1197c478bd9Sstevel@tonic-gate 	{v,		0x17,	"Dispatch_rs_mispred"},		\
1207c478bd9Sstevel@tonic-gate 	{v,		0x18,	"FA_pipe_completion"}
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate #define	US3_MC_EVENTS_0(v)					\
1237c478bd9Sstevel@tonic-gate 	{v,		0x20,	"MC_reads_0"},			\
1247c478bd9Sstevel@tonic-gate 	{v,		0x21,	"MC_reads_1"},			\
1257c478bd9Sstevel@tonic-gate 	{v,		0x22,	"MC_reads_2"},			\
1267c478bd9Sstevel@tonic-gate 	{v,		0x23,	"MC_reads_3"},			\
1277c478bd9Sstevel@tonic-gate 	{v,		0x24,	"MC_stalls_0"},			\
1287c478bd9Sstevel@tonic-gate 	{v,		0x25,	"MC_stalls_2"}
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate #define	US3_I_MC_EVENTS_0(v)					\
1317c478bd9Sstevel@tonic-gate 	{v,		0x20,	"MC_read_dispatched"},		\
1327c478bd9Sstevel@tonic-gate 	{v,		0x21,	"MC_write_dispatched"},		\
1337c478bd9Sstevel@tonic-gate 	{v,		0x22,	"MC_read_returned_to_JBU"},	\
1347c478bd9Sstevel@tonic-gate 	{v,		0x23,	"MC_msl_busy_stall"},		\
1357c478bd9Sstevel@tonic-gate 	{v,		0x24,	"MC_mdb_overflow_stall"},	\
1367c478bd9Sstevel@tonic-gate 	{v,		0x25,	"MC_miu_spec_request"}
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate static const struct nametable US3_names0[] = {
1397c478bd9Sstevel@tonic-gate 	USall_EVENTS_0(V_US3),
1407c478bd9Sstevel@tonic-gate 	US3all_EVENTS_0(V_US3),
1417c478bd9Sstevel@tonic-gate 	US3_MC_EVENTS_0(V_US3),
1427c478bd9Sstevel@tonic-gate 	{V_END}
1437c478bd9Sstevel@tonic-gate };
1447c478bd9Sstevel@tonic-gate 
145*23961e2bSvb70745 static const struct nametable US4_PLUS_names0[] = {
146*23961e2bSvb70745 	{V_US4_PLUS,	0x0,   "Cycle_cnt"},
147*23961e2bSvb70745 	{V_US4_PLUS,	0x1,   "Instr_cnt"},
148*23961e2bSvb70745 	{V_US4_PLUS,	0x2,   "Dispatch0_IC_miss"},
149*23961e2bSvb70745 	{V_US4_PLUS,	0x3,   "IU_stat_jmp_correct_pred"},
150*23961e2bSvb70745 	{V_US4_PLUS,	0x4,   "Dispatch0_2nd_br"},
151*23961e2bSvb70745 	{V_US4_PLUS,	0x5,   "Rstall_storeQ"},
152*23961e2bSvb70745 	{V_US4_PLUS,	0x6,   "Rstall_IU_use"},
153*23961e2bSvb70745 	{V_US4_PLUS,	0x7,   "IU_stat_ret_correct_pred"},
154*23961e2bSvb70745 	{V_US4_PLUS,	0x8,   "IC_ref"},
155*23961e2bSvb70745 	{V_US4_PLUS,	0x9,   "DC_rd"},
156*23961e2bSvb70745 	{V_US4_PLUS,	0xa,   "Rstall_FP_use"},
157*23961e2bSvb70745 	{V_US4_PLUS,	0xb,   "SW_pf_instr"},
158*23961e2bSvb70745 	{V_US4_PLUS,	0xc,   "L2_ref"},
159*23961e2bSvb70745 	{V_US4_PLUS,	0xd,   "L2_write_hit_RTO"},
160*23961e2bSvb70745 	{V_US4_PLUS,	0xe,   "L2_snoop_inv_sh"},
161*23961e2bSvb70745 	{V_US4_PLUS,	0xf,   "L2_rd_miss"},
162*23961e2bSvb70745 	{V_US4_PLUS,	0x10,  "PC_rd"},
163*23961e2bSvb70745 	{V_US4_PLUS,	0x11,  "SI_snoop_sh"},
164*23961e2bSvb70745 	{V_US4_PLUS,	0x12,  "SI_ciq_flow_sh"},
165*23961e2bSvb70745 	{V_US4_PLUS,	0x13,  "Re_DC_miss"},
166*23961e2bSvb70745 	{V_US4_PLUS,	0x14,  "SW_count_NOP"},
167*23961e2bSvb70745 	{V_US4_PLUS,	0x15,  "IU_stat_br_miss_taken"},
168*23961e2bSvb70745 	{V_US4_PLUS,	0x16,  "IU_stat_br_count_untaken"},
169*23961e2bSvb70745 	{V_US4_PLUS,	0x17,  "HW_pf_exec"},
170*23961e2bSvb70745 	{V_US4_PLUS,	0x18,  "FA_pipe_completion"},
171*23961e2bSvb70745 	{V_US4_PLUS,	0x19,  "SSM_L3_wb_remote"},
172*23961e2bSvb70745 	{V_US4_PLUS,	0x1a,  "SSM_L3_miss_local"},
173*23961e2bSvb70745 	{V_US4_PLUS,	0x1b,  "SSM_L3_miss_mtag_remote"},
174*23961e2bSvb70745 	{V_US4_PLUS,	0x1c,  "SW_pf_str_trapped"},
175*23961e2bSvb70745 	{V_US4_PLUS,	0x1d,  "SW_pf_PC_installed"},
176*23961e2bSvb70745 	{V_US4_PLUS,	0x1e,  "IPB_to_IC_fill"},
177*23961e2bSvb70745 	{V_US4_PLUS,	0x1f,  "L2_write_miss"},
178*23961e2bSvb70745 	{V_US4_PLUS,	0x20,  "MC_reads_0_sh"},
179*23961e2bSvb70745 	{V_US4_PLUS,	0x21,  "MC_reads_1_sh"},
180*23961e2bSvb70745 	{V_US4_PLUS,	0x22,  "MC_reads_2_sh"},
181*23961e2bSvb70745 	{V_US4_PLUS,	0x23,  "MC_reads_3_sh"},
182*23961e2bSvb70745 	{V_US4_PLUS,	0x24,  "MC_stalls_0_sh"},
183*23961e2bSvb70745 	{V_US4_PLUS,	0x25,  "MC_stalls_2_sh"},
184*23961e2bSvb70745 	{V_US4_PLUS,	0x26,  "L2_hit_other_half"},
185*23961e2bSvb70745 	{V_US4_PLUS,	0x28,  "L3_rd_miss"},
186*23961e2bSvb70745 	{V_US4_PLUS,	0x29,  "Re_L2_miss"},
187*23961e2bSvb70745 	{V_US4_PLUS,	0x2a,  "IC_miss_cancelled"},
188*23961e2bSvb70745 	{V_US4_PLUS,	0x2b,  "DC_wr_miss"},
189*23961e2bSvb70745 	{V_US4_PLUS,	0x2c,  "L3_hit_I_state_sh"},
190*23961e2bSvb70745 	{V_US4_PLUS,	0x2d,  "SI_RTS_src_data"},
191*23961e2bSvb70745 	{V_US4_PLUS,	0x2e,  "L2_IC_miss"},
192*23961e2bSvb70745 	{V_US4_PLUS,	0x2f,  "SSM_new_transaction_sh"},
193*23961e2bSvb70745 	{V_US4_PLUS,	0x30,  "L2_SW_pf_miss"},
194*23961e2bSvb70745 	{V_US4_PLUS,	0x31,  "L2_wb"},
195*23961e2bSvb70745 	{V_US4_PLUS,	0x32,  "L2_wb_sh"},
196*23961e2bSvb70745 	{V_US4_PLUS,	0x33,  "L2_snoop_cb_sh"},
197*23961e2bSvb70745 	{V_END}
198*23961e2bSvb70745 };
199*23961e2bSvb70745 
2007c478bd9Sstevel@tonic-gate static const struct nametable US3_PLUS_names0[] = {
2017c478bd9Sstevel@tonic-gate 	USall_EVENTS_0(V_US3_PLUS),
2027c478bd9Sstevel@tonic-gate 	US3all_EVENTS_0(V_US3_PLUS),
2037c478bd9Sstevel@tonic-gate 	US3_MC_EVENTS_0(V_US3_PLUS),
2047c478bd9Sstevel@tonic-gate 	{V_US3_PLUS,	0x19,	"EC_wb_remote"},
2057c478bd9Sstevel@tonic-gate 	{V_US3_PLUS,	0x1a,	"EC_miss_local"},
2067c478bd9Sstevel@tonic-gate 	{V_US3_PLUS,	0x1b,	"EC_miss_mtag_remote"},
2077c478bd9Sstevel@tonic-gate 	{V_END}
2087c478bd9Sstevel@tonic-gate };
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate static const struct nametable US3_I_names0[] = {
2117c478bd9Sstevel@tonic-gate 	USall_EVENTS_0(V_US3_I),
2127c478bd9Sstevel@tonic-gate 	US3all_EVENTS_0(V_US3_I),
2137c478bd9Sstevel@tonic-gate 	US3_I_MC_EVENTS_0(V_US3_I),
2147c478bd9Sstevel@tonic-gate 	{V_US3_PLUS,	0x19,	"EC_wb_remote"},
2157c478bd9Sstevel@tonic-gate 	{V_US3_PLUS,	0x1a,	"EC_miss_local"},
2167c478bd9Sstevel@tonic-gate 	{V_US3_PLUS,	0x1b,	"EC_miss_mtag_remote"},
2177c478bd9Sstevel@tonic-gate 	{V_END}
2187c478bd9Sstevel@tonic-gate };
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate #undef	USall_EVENTS_0
2217c478bd9Sstevel@tonic-gate #undef	US3all_EVENTS_0
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate #define	USall_EVENTS_1(v)					\
2247c478bd9Sstevel@tonic-gate 	{v,		0x0,	"Cycle_cnt"},			\
2257c478bd9Sstevel@tonic-gate 	{v,		0x1,	"Instr_cnt"},			\
2267c478bd9Sstevel@tonic-gate 	{v,		0x2,	"Dispatch0_mispred"},		\
2277c478bd9Sstevel@tonic-gate 	{v,		0xd,	"EC_wb"},			\
2287c478bd9Sstevel@tonic-gate 	{v,		0xe,	"EC_snoop_cb"}
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate static const struct nametable US12_names1[] = {
2317c478bd9Sstevel@tonic-gate 	USall_EVENTS_1(V_US12),
2327c478bd9Sstevel@tonic-gate 	{V_US12,	0x3,	"Dispatch0_FP_use"},
2337c478bd9Sstevel@tonic-gate 	{V_US12,	0x8,	"IC_hit"},
2347c478bd9Sstevel@tonic-gate 	{V_US12,	0x9,	"DC_rd_hit"},
2357c478bd9Sstevel@tonic-gate 	{V_US12,	0xa,	"DC_wr_hit"},
2367c478bd9Sstevel@tonic-gate 	{V_US12,	0xb,	"Load_use_RAW"},
2377c478bd9Sstevel@tonic-gate 	{V_US12,	0xc,	"EC_hit"},
2387c478bd9Sstevel@tonic-gate 	{V_US12,	0xf,	"EC_ic_hit"},
2397c478bd9Sstevel@tonic-gate 	{V_END}
2407c478bd9Sstevel@tonic-gate };
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate #define	US3all_EVENTS_1(v)					\
2437c478bd9Sstevel@tonic-gate 	{v,		0x3,	"IC_miss_cancelled"},		\
2447c478bd9Sstevel@tonic-gate 	{v,		0x5,	"Re_FPU_bypass"},		\
2457c478bd9Sstevel@tonic-gate 	{v,		0x6,	"Re_DC_miss"},			\
2467c478bd9Sstevel@tonic-gate 	{v,		0x7,	"Re_EC_miss"},			\
2477c478bd9Sstevel@tonic-gate 	{v,		0x8,	"IC_miss"},			\
2487c478bd9Sstevel@tonic-gate 	{v,		0x9,	"DC_rd_miss"},			\
2497c478bd9Sstevel@tonic-gate 	{v,		0xa,	"DC_wr_miss"},			\
2507c478bd9Sstevel@tonic-gate 	{v,		0xb,	"Rstall_FP_use"},		\
2517c478bd9Sstevel@tonic-gate 	{v,		0xc,	"EC_misses"},			\
2527c478bd9Sstevel@tonic-gate 	{v,		0xf,	"EC_ic_miss"},			\
2537c478bd9Sstevel@tonic-gate 	{v,		0x10,	"Re_PC_miss"},			\
2547c478bd9Sstevel@tonic-gate 	{v,		0x11,	"ITLB_miss"},			\
2557c478bd9Sstevel@tonic-gate 	{v,		0x12,	"DTLB_miss"},			\
2567c478bd9Sstevel@tonic-gate 	{v,		0x13,	"WC_miss"},			\
2577c478bd9Sstevel@tonic-gate 	{v,		0x14,	"WC_snoop_cb"},			\
2587c478bd9Sstevel@tonic-gate 	{v,		0x15,	"WC_scrubbed"},			\
2597c478bd9Sstevel@tonic-gate 	{v,		0x16,	"WC_wb_wo_read"},		\
2607c478bd9Sstevel@tonic-gate 	{v,		0x18,	"PC_soft_hit"},			\
2617c478bd9Sstevel@tonic-gate 	{v,		0x19,	"PC_snoop_inv"},		\
2627c478bd9Sstevel@tonic-gate 	{v,		0x1a,	"PC_hard_hit"},			\
2637c478bd9Sstevel@tonic-gate 	{v,		0x1b,	"PC_port1_rd"},			\
2647c478bd9Sstevel@tonic-gate 	{v,		0x1c,	"SW_count_1"},			\
2657c478bd9Sstevel@tonic-gate 	{v,		0x1d,	"IU_Stat_Br_miss_untaken"},	\
2667c478bd9Sstevel@tonic-gate 	{v,		0x1e,	"IU_Stat_Br_count_untaken"},	\
2677c478bd9Sstevel@tonic-gate 	{v,		0x1f,	"PC_MS_misses"},		\
2687c478bd9Sstevel@tonic-gate 	{v,		0x26,	"Re_RAW_miss"},			\
2697c478bd9Sstevel@tonic-gate 	{v,		0x27,	"FM_pipe_completion"}
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate #define	US3_MC_EVENTS_1(v)					\
2727c478bd9Sstevel@tonic-gate 	{v,		0x20,	"MC_writes_0"},			\
2737c478bd9Sstevel@tonic-gate 	{v,		0x21,	"MC_writes_1"},			\
2747c478bd9Sstevel@tonic-gate 	{v,		0x22,	"MC_writes_2"},			\
2757c478bd9Sstevel@tonic-gate 	{v,		0x23,	"MC_writes_3"},			\
2767c478bd9Sstevel@tonic-gate 	{v,		0x24,	"MC_stalls_1"},			\
2777c478bd9Sstevel@tonic-gate 	{v,		0x25,	"MC_stalls_3"}
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate #define	US3_I_MC_EVENTS_1(v)					\
2807c478bd9Sstevel@tonic-gate 	{v,		0x20,	"MC_open_bank_cmds"},		\
2817c478bd9Sstevel@tonic-gate 	{v,		0x21,	"MC_reads"},			\
2827c478bd9Sstevel@tonic-gate 	{v,		0x22,	"MC_writes"},			\
2837c478bd9Sstevel@tonic-gate 	{v,		0x23,	"MC_page_close_stall"}
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate static const struct nametable US3_names1[] = {
2867c478bd9Sstevel@tonic-gate 	USall_EVENTS_1(V_US3),
2877c478bd9Sstevel@tonic-gate 	US3all_EVENTS_1(V_US3),
2887c478bd9Sstevel@tonic-gate 	US3_MC_EVENTS_1(V_US3),
2897c478bd9Sstevel@tonic-gate 	{V_US3,		0x4,	"Re_endian_miss"},
2907c478bd9Sstevel@tonic-gate 	{V_END}
2917c478bd9Sstevel@tonic-gate };
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate static const struct nametable US3_PLUS_names1[] = {
2947c478bd9Sstevel@tonic-gate 	USall_EVENTS_1(V_US3_PLUS),
2957c478bd9Sstevel@tonic-gate 	US3all_EVENTS_1(V_US3_PLUS),
2967c478bd9Sstevel@tonic-gate 	US3_MC_EVENTS_1(V_US3_PLUS),
2977c478bd9Sstevel@tonic-gate 	{V_US3_PLUS,	0x4,	"Re_DC_missovhd"},
2987c478bd9Sstevel@tonic-gate 	{V_US3_PLUS,	0x28,	"EC_miss_mtag_remote"},
2997c478bd9Sstevel@tonic-gate 	{V_US3_PLUS,	0x29,	"EC_miss_remote"},
3007c478bd9Sstevel@tonic-gate 	{V_END}
3017c478bd9Sstevel@tonic-gate };
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate static const struct nametable US3_I_names1[] = {
3047c478bd9Sstevel@tonic-gate 	USall_EVENTS_1(V_US3_I),
3057c478bd9Sstevel@tonic-gate 	US3all_EVENTS_1(V_US3_I),
3067c478bd9Sstevel@tonic-gate 	US3_I_MC_EVENTS_1(V_US3_I),
3077c478bd9Sstevel@tonic-gate 	{V_US3_I,	0x4,	"Re_DC_missovhd"},
3087c478bd9Sstevel@tonic-gate 	{V_END}
3097c478bd9Sstevel@tonic-gate };
310*23961e2bSvb70745 
311*23961e2bSvb70745 static const struct nametable US4_PLUS_names1[] = {
312*23961e2bSvb70745 	{V_US4_PLUS,	0x0,   "Cycle_cnt"},
313*23961e2bSvb70745 	{V_US4_PLUS,	0x1,   "Instr_cnt"},
314*23961e2bSvb70745 	{V_US4_PLUS,	0x2,   "Dispatch0_other"},
315*23961e2bSvb70745 	{V_US4_PLUS,	0x3,   "DC_wr"},
316*23961e2bSvb70745 	{V_US4_PLUS,	0x4,   "Re_DC_missovhd"},
317*23961e2bSvb70745 	{V_US4_PLUS,	0x5,   "Re_FPU_bypass"},
318*23961e2bSvb70745 	{V_US4_PLUS,	0x6,   "L3_write_hit_RTO"},
319*23961e2bSvb70745 	{V_US4_PLUS,	0x7,   "L2L3_snoop_inv_sh"},
320*23961e2bSvb70745 	{V_US4_PLUS,	0x8,   "IC_L2_req"},
321*23961e2bSvb70745 	{V_US4_PLUS,	0x9,   "DC_rd_miss"},
322*23961e2bSvb70745 	{V_US4_PLUS,	0xa,   "L2_hit_I_state_sh"},
323*23961e2bSvb70745 	{V_US4_PLUS,	0xb,   "L3_write_miss_RTO"},
324*23961e2bSvb70745 	{V_US4_PLUS,	0xc,   "L2_miss"},
325*23961e2bSvb70745 	{V_US4_PLUS,	0xd,   "SI_owned_sh"},
326*23961e2bSvb70745 	{V_US4_PLUS,	0xe,   "SI_RTO_src_data"},
327*23961e2bSvb70745 	{V_US4_PLUS,	0xf,   "SW_pf_duplicate"},
328*23961e2bSvb70745 	{V_US4_PLUS,	0x10,  "IU_stat_jmp_mispred"},
329*23961e2bSvb70745 	{V_US4_PLUS,	0x11,  "ITLB_miss"},
330*23961e2bSvb70745 	{V_US4_PLUS,	0x12,  "DTLB_miss"},
331*23961e2bSvb70745 	{V_US4_PLUS,	0x13,  "WC_miss"},
332*23961e2bSvb70745 	{V_US4_PLUS,	0x14,  "IC_fill"},
333*23961e2bSvb70745 	{V_US4_PLUS,	0x15,  "IU_stat_ret_mispred"},
334*23961e2bSvb70745 	{V_US4_PLUS,	0x16,  "Re_L3_miss"},
335*23961e2bSvb70745 	{V_US4_PLUS,	0x17,  "Re_PFQ_full"},
336*23961e2bSvb70745 	{V_US4_PLUS,	0x18,  "PC_soft_hit"},
337*23961e2bSvb70745 	{V_US4_PLUS,	0x19,  "PC_inv"},
338*23961e2bSvb70745 	{V_US4_PLUS,	0x1a,  "PC_hard_hit"},
339*23961e2bSvb70745 	{V_US4_PLUS,	0x1b,  "IC_pf"},
340*23961e2bSvb70745 	{V_US4_PLUS,	0x1c,  "SW_count_NOP"},
341*23961e2bSvb70745 	{V_US4_PLUS,	0x1d,  "IU_stat_br_miss_untaken"},
342*23961e2bSvb70745 	{V_US4_PLUS,	0x1e,  "IU_stat_br_count_taken"},
343*23961e2bSvb70745 	{V_US4_PLUS,	0x1f,  "PC_miss"},
344*23961e2bSvb70745 	{V_US4_PLUS,	0x20,  "MC_writes_0_sh"},
345*23961e2bSvb70745 	{V_US4_PLUS,	0x21,  "MC_writes_1_sh"},
346*23961e2bSvb70745 	{V_US4_PLUS,	0x22,  "MC_writes_2_sh"},
347*23961e2bSvb70745 	{V_US4_PLUS,	0x23,  "MC_writes_3_sh"},
348*23961e2bSvb70745 	{V_US4_PLUS,	0x24,  "MC_stalls_1_sh"},
349*23961e2bSvb70745 	{V_US4_PLUS,	0x25,  "MC_stalls_3_sh"},
350*23961e2bSvb70745 	{V_US4_PLUS,	0x26,  "Re_RAW_miss"},
351*23961e2bSvb70745 	{V_US4_PLUS,	0x27,  "FM_pipe_completion"},
352*23961e2bSvb70745 	{V_US4_PLUS,	0x28,  "SSM_L3_miss_mtag_remote"},
353*23961e2bSvb70745 	{V_US4_PLUS,	0x29,  "SSM_L3_miss_remote"},
354*23961e2bSvb70745 	{V_US4_PLUS,	0x2a,  "SW_pf_exec"},
355*23961e2bSvb70745 	{V_US4_PLUS,	0x2b,  "SW_pf_str_exec"},
356*23961e2bSvb70745 	{V_US4_PLUS,	0x2c,  "SW_pf_dropped"},
357*23961e2bSvb70745 	{V_US4_PLUS,	0x2d,  "SW_pf_L2_installed"},
358*23961e2bSvb70745 	{V_US4_PLUS,	0x2f,  "L2_HW_pf_miss"},
359*23961e2bSvb70745 	{V_US4_PLUS,	0x31,  "L3_miss"},
360*23961e2bSvb70745 	{V_US4_PLUS,	0x32,  "L3_IC_miss"},
361*23961e2bSvb70745 	{V_US4_PLUS,	0x33,  "L3_SW_pf_miss"},
362*23961e2bSvb70745 	{V_US4_PLUS,	0x34,  "L3_hit_other_half"},
363*23961e2bSvb70745 	{V_US4_PLUS,	0x35,  "L3_wb"},
364*23961e2bSvb70745 	{V_US4_PLUS,	0x36,  "L3_wb_sh"},
365*23961e2bSvb70745 	{V_US4_PLUS,	0x37,  "L2L3_snoop_cb_sh"},
366*23961e2bSvb70745 	{V_END}
367*23961e2bSvb70745 };
368*23961e2bSvb70745 
3697c478bd9Sstevel@tonic-gate #undef	USall_EVENTS_1
3707c478bd9Sstevel@tonic-gate #undef	US3all_EVENTS_1
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate static const struct nametable *US12_names[2] = {
3737c478bd9Sstevel@tonic-gate 	US12_names0,
3747c478bd9Sstevel@tonic-gate 	US12_names1
3757c478bd9Sstevel@tonic-gate };
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate static const struct nametable *US3_names[2] = {
3787c478bd9Sstevel@tonic-gate 	US3_names0,
3797c478bd9Sstevel@tonic-gate 	US3_names1
3807c478bd9Sstevel@tonic-gate };
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate static const struct nametable *US3_PLUS_names[2] = {
3837c478bd9Sstevel@tonic-gate 	US3_PLUS_names0,
3847c478bd9Sstevel@tonic-gate 	US3_PLUS_names1
3857c478bd9Sstevel@tonic-gate };
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate static const struct nametable *US3_I_names[2] = {
3887c478bd9Sstevel@tonic-gate 	US3_I_names0,
3897c478bd9Sstevel@tonic-gate 	US3_I_names1
3907c478bd9Sstevel@tonic-gate };
3917c478bd9Sstevel@tonic-gate 
392*23961e2bSvb70745 static const struct nametable *US4_PLUS_names[2] = {
393*23961e2bSvb70745 	US4_PLUS_names0,
394*23961e2bSvb70745 	US4_PLUS_names1
395*23961e2bSvb70745 };
396*23961e2bSvb70745 
3977c478bd9Sstevel@tonic-gate #define	MAPCPUVER(cpuver)	(cpuvermap[(cpuver) - CPC_ULTRA1])
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate static int
validargs(int cpuver,int regno)4007c478bd9Sstevel@tonic-gate validargs(int cpuver, int regno)
4017c478bd9Sstevel@tonic-gate {
4027c478bd9Sstevel@tonic-gate 	if (regno < 0 || regno > 1)
4037c478bd9Sstevel@tonic-gate 		return (0);
4047c478bd9Sstevel@tonic-gate 	cpuver -= CPC_ULTRA1;
4057c478bd9Sstevel@tonic-gate 	if (cpuver < 0 ||
4067c478bd9Sstevel@tonic-gate 	    cpuver >= sizeof (cpuvermap) / sizeof (cpuvermap[0]))
4077c478bd9Sstevel@tonic-gate 		return (0);
4087c478bd9Sstevel@tonic-gate 	return (1);
4097c478bd9Sstevel@tonic-gate }
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4127c478bd9Sstevel@tonic-gate static int
versionmatch(int cpuver,int regno,const struct nametable * n)4137c478bd9Sstevel@tonic-gate versionmatch(int cpuver, int regno, const struct nametable *n)
4147c478bd9Sstevel@tonic-gate {
4157c478bd9Sstevel@tonic-gate 	if (!validargs(cpuver, regno) || n->ver != MAPCPUVER(cpuver))
4167c478bd9Sstevel@tonic-gate 		return (0);
4177c478bd9Sstevel@tonic-gate 	return (1);
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate static const struct nametable *
getnametable(int cpuver,int regno)4217c478bd9Sstevel@tonic-gate getnametable(int cpuver, int regno)
4227c478bd9Sstevel@tonic-gate {
4237c478bd9Sstevel@tonic-gate 	const struct nametable *n;
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	if (!validargs(cpuver, regno))
4267c478bd9Sstevel@tonic-gate 		return (NULL);
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate 	switch (MAPCPUVER(cpuver)) {
4297c478bd9Sstevel@tonic-gate 	case V_US12:
4307c478bd9Sstevel@tonic-gate 		n = US12_names[regno];
4317c478bd9Sstevel@tonic-gate 		break;
4327c478bd9Sstevel@tonic-gate 	case V_US3:
4337c478bd9Sstevel@tonic-gate 		n = US3_names[regno];
4347c478bd9Sstevel@tonic-gate 		break;
4357c478bd9Sstevel@tonic-gate 	case V_US3_PLUS:
4367c478bd9Sstevel@tonic-gate 		n = US3_PLUS_names[regno];
4377c478bd9Sstevel@tonic-gate 		break;
4387c478bd9Sstevel@tonic-gate 	case V_US3_I:
4397c478bd9Sstevel@tonic-gate 		n = US3_I_names[regno];
4407c478bd9Sstevel@tonic-gate 		break;
441*23961e2bSvb70745 	case V_US4_PLUS:
442*23961e2bSvb70745 		n = US4_PLUS_names[regno];
443*23961e2bSvb70745 		break;
4447c478bd9Sstevel@tonic-gate 	default:
4457c478bd9Sstevel@tonic-gate 		n = NULL;
4467c478bd9Sstevel@tonic-gate 		break;
4477c478bd9Sstevel@tonic-gate 	}
4487c478bd9Sstevel@tonic-gate 	return (n);
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate void
cpc_walk_names(int cpuver,int regno,void * arg,void (* action)(void *,int,const char *,uint8_t))4527c478bd9Sstevel@tonic-gate cpc_walk_names(int cpuver, int regno, void *arg,
4537c478bd9Sstevel@tonic-gate     void (*action)(void *, int, const char *, uint8_t))
4547c478bd9Sstevel@tonic-gate {
4557c478bd9Sstevel@tonic-gate 	const struct nametable *n;
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	if ((n = getnametable(cpuver, regno)) == NULL)
4587c478bd9Sstevel@tonic-gate 		return;
4597c478bd9Sstevel@tonic-gate 	for (; n->ver != V_END; n++)
4607c478bd9Sstevel@tonic-gate 		if (versionmatch(cpuver, regno, n))
4617c478bd9Sstevel@tonic-gate 			action(arg, regno, n->name, n->bits);
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate const char *
__cpc_reg_to_name(int cpuver,int regno,uint8_t bits)4657c478bd9Sstevel@tonic-gate __cpc_reg_to_name(int cpuver, int regno, uint8_t bits)
4667c478bd9Sstevel@tonic-gate {
4677c478bd9Sstevel@tonic-gate 	const struct nametable *n;
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	if ((n = getnametable(cpuver, regno)) == NULL)
4707c478bd9Sstevel@tonic-gate 		return (NULL);
4717c478bd9Sstevel@tonic-gate 	for (; n->ver != V_END; n++)
4727c478bd9Sstevel@tonic-gate 		if (bits == n->bits && versionmatch(cpuver, regno, n))
4737c478bd9Sstevel@tonic-gate 			return (n->name);
4747c478bd9Sstevel@tonic-gate 	return (NULL);
4757c478bd9Sstevel@tonic-gate }
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate /*
4787c478bd9Sstevel@tonic-gate  * Register names can be specified as strings or even as numbers
4797c478bd9Sstevel@tonic-gate  */
4807c478bd9Sstevel@tonic-gate int
__cpc_name_to_reg(int cpuver,int regno,const char * name,uint8_t * bits)4817c478bd9Sstevel@tonic-gate __cpc_name_to_reg(int cpuver, int regno, const char *name, uint8_t *bits)
4827c478bd9Sstevel@tonic-gate {
4837c478bd9Sstevel@tonic-gate 	const struct nametable *n;
4847c478bd9Sstevel@tonic-gate 	char *eptr = NULL;
4857c478bd9Sstevel@tonic-gate 	long value;
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	if ((n = getnametable(cpuver, regno)) == NULL || name == NULL)
4887c478bd9Sstevel@tonic-gate 		return (-1);
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 	for (; n->ver != V_END; n++)
4917c478bd9Sstevel@tonic-gate 		if (strcmp(name, n->name) == 0 &&
4927c478bd9Sstevel@tonic-gate 		    versionmatch(cpuver, regno, n)) {
4937c478bd9Sstevel@tonic-gate 			*bits = n->bits;
4947c478bd9Sstevel@tonic-gate 			return (0);
4957c478bd9Sstevel@tonic-gate 		}
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	value = strtol(name, &eptr, 0);
4987c478bd9Sstevel@tonic-gate 	if (name != eptr && value >= 0 && value <= UINT8_MAX) {
4997c478bd9Sstevel@tonic-gate 		*bits = (uint8_t)value;
5007c478bd9Sstevel@tonic-gate 		return (0);
5017c478bd9Sstevel@tonic-gate 	}
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 	return (-1);
5047c478bd9Sstevel@tonic-gate }
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate const char *
cpc_getcciname(int cpuver)5077c478bd9Sstevel@tonic-gate cpc_getcciname(int cpuver)
5087c478bd9Sstevel@tonic-gate {
5097c478bd9Sstevel@tonic-gate 	if (validargs(cpuver, 0))
5107c478bd9Sstevel@tonic-gate 		switch (MAPCPUVER(cpuver)) {
5117c478bd9Sstevel@tonic-gate 		case V_US12:
5127c478bd9Sstevel@tonic-gate 			return ("UltraSPARC I&II");
5137c478bd9Sstevel@tonic-gate 		case V_US3:
5147c478bd9Sstevel@tonic-gate 			return ("UltraSPARC III");
5157c478bd9Sstevel@tonic-gate 		case V_US3_PLUS:
5167c478bd9Sstevel@tonic-gate 			return ("UltraSPARC III+ & IV");
5177c478bd9Sstevel@tonic-gate 		case V_US3_I:
5187c478bd9Sstevel@tonic-gate 			return ("UltraSPARC IIIi & IIIi+");
519*23961e2bSvb70745 		case V_US4_PLUS:
520*23961e2bSvb70745 			return ("UltraSPARC IV+");
5217c478bd9Sstevel@tonic-gate 		default:
5227c478bd9Sstevel@tonic-gate 			break;
5237c478bd9Sstevel@tonic-gate 		}
5247c478bd9Sstevel@tonic-gate 	return (NULL);
5257c478bd9Sstevel@tonic-gate }
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate #define	CPU_REF_URL " Documentation for Sun processors can be found at: " \
5287c478bd9Sstevel@tonic-gate 			"http://www.sun.com/processors/manuals"
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate const char *
cpc_getcpuref(int cpuver)5317c478bd9Sstevel@tonic-gate cpc_getcpuref(int cpuver)
5327c478bd9Sstevel@tonic-gate {
5337c478bd9Sstevel@tonic-gate 	if (validargs(cpuver, 0))
5347c478bd9Sstevel@tonic-gate 		switch (MAPCPUVER(cpuver)) {
5357c478bd9Sstevel@tonic-gate 		case V_US12:
5367c478bd9Sstevel@tonic-gate 			return (gettext(
5377c478bd9Sstevel@tonic-gate 			    "See the \"UltraSPARC I/II User\'s Manual\" "
5387c478bd9Sstevel@tonic-gate 			    "(Part No. 802-7220-02) "
5397c478bd9Sstevel@tonic-gate 			    "for descriptions of these events." CPU_REF_URL));
5407c478bd9Sstevel@tonic-gate 		case V_US3:
5417c478bd9Sstevel@tonic-gate 		case V_US3_PLUS:
5427c478bd9Sstevel@tonic-gate 			return (gettext(
5437c478bd9Sstevel@tonic-gate 			    "See the \"UltraSPARC III Cu User's Manual\" "
5447c478bd9Sstevel@tonic-gate 			    "for descriptions of these events." CPU_REF_URL));
5457c478bd9Sstevel@tonic-gate 		case V_US3_I:
5467c478bd9Sstevel@tonic-gate 			return (gettext(
5477c478bd9Sstevel@tonic-gate 			    "See the \"UltraSPARC IIIi User's Manual\"  "
5487c478bd9Sstevel@tonic-gate 			    "for descriptions of these events." CPU_REF_URL));
549*23961e2bSvb70745 		case V_US4_PLUS:
550*23961e2bSvb70745 			return (gettext(
551*23961e2bSvb70745 			    "See the \"UltraSPARC IV User's Manual"
552*23961e2bSvb70745 			    "Supplement\"  "
553*23961e2bSvb70745 			    "for descriptions of these events." CPU_REF_URL));
5547c478bd9Sstevel@tonic-gate 		default:
5557c478bd9Sstevel@tonic-gate 			break;
5567c478bd9Sstevel@tonic-gate 		}
5577c478bd9Sstevel@tonic-gate 	return (NULL);
5587c478bd9Sstevel@tonic-gate }
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate /*
5617c478bd9Sstevel@tonic-gate  * This is a functional interface to allow CPUs with fewer %pic registers
5627c478bd9Sstevel@tonic-gate  * to share the same data structure as those with more %pic registers
5637c478bd9Sstevel@tonic-gate  * within the same instruction family.
5647c478bd9Sstevel@tonic-gate  */
5657c478bd9Sstevel@tonic-gate uint_t
cpc_getnpic(int cpuver)5667c478bd9Sstevel@tonic-gate cpc_getnpic(int cpuver)
5677c478bd9Sstevel@tonic-gate {
5687c478bd9Sstevel@tonic-gate 	/*LINTED*/
5697c478bd9Sstevel@tonic-gate 	cpc_event_t *event;
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 	switch (cpuver) {
5727c478bd9Sstevel@tonic-gate 	case CPC_ULTRA1:
5737c478bd9Sstevel@tonic-gate 	case CPC_ULTRA2:
5747c478bd9Sstevel@tonic-gate 	case CPC_ULTRA3:
5757c478bd9Sstevel@tonic-gate 	case CPC_ULTRA3_PLUS:
5767c478bd9Sstevel@tonic-gate 	case CPC_ULTRA3_I:
577*23961e2bSvb70745 	case CPC_ULTRA4_PLUS:
5787c478bd9Sstevel@tonic-gate 		return (sizeof (event->ce_pic) / sizeof (event->ce_pic[0]));
5797c478bd9Sstevel@tonic-gate 	default:
5807c478bd9Sstevel@tonic-gate 		return (0);
5817c478bd9Sstevel@tonic-gate 	}
5827c478bd9Sstevel@tonic-gate }
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate /*
5857c478bd9Sstevel@tonic-gate  * Compares the given string against the list of all known CPU node names, and
5867c478bd9Sstevel@tonic-gate  * returns the CPC CPU version code if there is a match. If there is no match,
5877c478bd9Sstevel@tonic-gate  * returns -1.
5887c478bd9Sstevel@tonic-gate  */
5897c478bd9Sstevel@tonic-gate static int
node2ver(char * node)5907c478bd9Sstevel@tonic-gate node2ver(char *node)
5917c478bd9Sstevel@tonic-gate {
5927c478bd9Sstevel@tonic-gate 	if (strcmp(node, "SUNW,UltraSPARC") == 0 ||
5937c478bd9Sstevel@tonic-gate 	    strcmp(node, "SUNW,UltraSPARC-II") == 0 ||
5947c478bd9Sstevel@tonic-gate 	    strcmp(node, "SUNW,UltraSPARC-IIi") == 0 ||
5957c478bd9Sstevel@tonic-gate 	    strcmp(node, "SUNW,UltraSPARC-IIe") == 0) {
5967c478bd9Sstevel@tonic-gate 		return (CPC_ULTRA1);
5977c478bd9Sstevel@tonic-gate 	} else if (strcmp(node, "SUNW,UltraSPARC-III") == 0)
5987c478bd9Sstevel@tonic-gate 		return (CPC_ULTRA3);
5997c478bd9Sstevel@tonic-gate 	else if (strcmp(node, "SUNW,UltraSPARC-III+") == 0 ||
600*23961e2bSvb70745 	    strcmp(node, "SUNW,UltraSPARC-IV") == 0)
6017c478bd9Sstevel@tonic-gate 		return (CPC_ULTRA3_PLUS);
6027c478bd9Sstevel@tonic-gate 	else if (strcmp(node, "SUNW,UltraSPARC-IIIi") == 0 ||
6037c478bd9Sstevel@tonic-gate 	    strcmp(node, "SUNW,UltraSPARC-IIIi+") == 0)
6047c478bd9Sstevel@tonic-gate 		return (CPC_ULTRA3_I);
605*23961e2bSvb70745 	else if (strcmp(node, "SUNW,UltraSPARC-IV+") == 0)
606*23961e2bSvb70745 		return (CPC_ULTRA4_PLUS);
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	return (-1);
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate static int
cpc_get_cpu_ver(di_node_t di_node,void * arg)6127c478bd9Sstevel@tonic-gate cpc_get_cpu_ver(di_node_t di_node, void *arg)
6137c478bd9Sstevel@tonic-gate {
6147c478bd9Sstevel@tonic-gate 	char		*node_name, *compatible_array;
6157c478bd9Sstevel@tonic-gate 	int		n_names, i, found = 0;
6167c478bd9Sstevel@tonic-gate 	int		*ver = arg;
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 	node_name = di_node_name(di_node);
6197c478bd9Sstevel@tonic-gate 	if (node_name != NULL) {
6207c478bd9Sstevel@tonic-gate 		if ((*ver = node2ver(node_name)) != -1)
6217c478bd9Sstevel@tonic-gate 			found = 1;
6227c478bd9Sstevel@tonic-gate 		else if (strncmp(node_name, "cpu", 4) == 0) {
6237c478bd9Sstevel@tonic-gate 			/*
6247c478bd9Sstevel@tonic-gate 			 * CPU nodes associated with CMP use the generic name
6257c478bd9Sstevel@tonic-gate 			 * of "cpu".  We must look at the compatible property
6267c478bd9Sstevel@tonic-gate 			 * in order to find the implementation specific name.
6277c478bd9Sstevel@tonic-gate 			 */
6287c478bd9Sstevel@tonic-gate 			if ((n_names = di_compatible_names(di_node,
6297c478bd9Sstevel@tonic-gate 			    &compatible_array)) > 0) {
6307c478bd9Sstevel@tonic-gate 				for (i = 0; i < n_names; i++) {
6317c478bd9Sstevel@tonic-gate 					if ((*ver = node2ver(compatible_array))
6327c478bd9Sstevel@tonic-gate 					    != -1) {
6337c478bd9Sstevel@tonic-gate 						found = 1;
6347c478bd9Sstevel@tonic-gate 						break;
6357c478bd9Sstevel@tonic-gate 					}
6367c478bd9Sstevel@tonic-gate 					compatible_array +=
6377c478bd9Sstevel@tonic-gate 					    strlen(compatible_array) + 1;
6387c478bd9Sstevel@tonic-gate 				}
6397c478bd9Sstevel@tonic-gate 			}
6407c478bd9Sstevel@tonic-gate 		}
6417c478bd9Sstevel@tonic-gate 	}
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 	if (found == 0)
6447c478bd9Sstevel@tonic-gate 		return (DI_WALK_CONTINUE);
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 	return (DI_WALK_TERMINATE);
6477c478bd9Sstevel@tonic-gate }
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate /*
6507c478bd9Sstevel@tonic-gate  * Return the version of the current processor.
6517c478bd9Sstevel@tonic-gate  *
6527c478bd9Sstevel@tonic-gate  * Version -1 is defined as 'not performance counter capable'
6537c478bd9Sstevel@tonic-gate  *
6547c478bd9Sstevel@tonic-gate  * XXX  A better solution would be to use the di_prom_props for the cpu
6557c478bd9Sstevel@tonic-gate  * devinfo nodes. That way we could look at the 'device-type', 'sparc-version'
6567c478bd9Sstevel@tonic-gate  * and 'implementation#' properties in order to determine which version of
6577c478bd9Sstevel@tonic-gate  * UltraSPARC we are running on.
6587c478bd9Sstevel@tonic-gate  *
6597c478bd9Sstevel@tonic-gate  * The problem with this is that di_prom_init() requires root access to
6607c478bd9Sstevel@tonic-gate  * open /dev/openprom and cputrack is not a root-only application so
6617c478bd9Sstevel@tonic-gate  * we have to settle for the di_props that we can see as non-root users.
6627c478bd9Sstevel@tonic-gate  */
6637c478bd9Sstevel@tonic-gate int
cpc_getcpuver(void)6647c478bd9Sstevel@tonic-gate cpc_getcpuver(void)
6657c478bd9Sstevel@tonic-gate {
6667c478bd9Sstevel@tonic-gate 	static int ver = -1;
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 	if (ver == -1) {
6697c478bd9Sstevel@tonic-gate 		di_node_t	di_root_node;
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 		if ((di_root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL)
6727c478bd9Sstevel@tonic-gate 			return (-1);
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate 		(void) di_walk_node(di_root_node, DI_WALK_CLDFIRST,
6757c478bd9Sstevel@tonic-gate 			(void *)&ver, cpc_get_cpu_ver);
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate 		di_fini(di_root_node);
6787c478bd9Sstevel@tonic-gate 	}
6797c478bd9Sstevel@tonic-gate 	return (ver);
6807c478bd9Sstevel@tonic-gate }
681