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