1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <string.h> 31*7c478bd9Sstevel@tonic-gate #include <alloca.h> 32*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 33*7c478bd9Sstevel@tonic-gate #include <stdio.h> 34*7c478bd9Sstevel@tonic-gate #include <libintl.h> 35*7c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #include "libcpc.h" 38*7c478bd9Sstevel@tonic-gate #include "libcpc_impl.h" 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate /* 41*7c478bd9Sstevel@tonic-gate * Configuration data for UltraSPARC performance counters. 42*7c478bd9Sstevel@tonic-gate * 43*7c478bd9Sstevel@tonic-gate * Definitions taken from [1], [2], [3] and [4]. See the references to 44*7c478bd9Sstevel@tonic-gate * understand what any of these settings actually means. 45*7c478bd9Sstevel@tonic-gate * 46*7c478bd9Sstevel@tonic-gate * Note that in the current draft of [2], there is some re-use 47*7c478bd9Sstevel@tonic-gate * of existing bit assignments in the various fields of the %pcr 48*7c478bd9Sstevel@tonic-gate * register - this may change before FCS. 49*7c478bd9Sstevel@tonic-gate * 50*7c478bd9Sstevel@tonic-gate * The following are the Internal Documents. Customers need to be 51*7c478bd9Sstevel@tonic-gate * told about the Public docs in cpc_getcpuref(). 52*7c478bd9Sstevel@tonic-gate * [1] "UltraSPARC I & II User's Manual," January 1997. 53*7c478bd9Sstevel@tonic-gate * [2] "UltraSPARC-III Programmer's Reference Manual," April 1999. 54*7c478bd9Sstevel@tonic-gate * [3] "Cheetah+ Programmer's Reference Manual," November 2000. 55*7c478bd9Sstevel@tonic-gate * [4] "UltraSPARC-IIIi Programmer's Reference Manual," November 2000. 56*7c478bd9Sstevel@tonic-gate */ 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate #define V_US12 (1u << 0) /* specific to UltraSPARC 1 and 2 */ 59*7c478bd9Sstevel@tonic-gate #define V_US3 (1u << 1) /* specific to UltraSPARC 3 */ 60*7c478bd9Sstevel@tonic-gate #define V_US3_PLUS (1u << 2) /* specific to UltraSPARC 3 PLUS */ 61*7c478bd9Sstevel@tonic-gate #define V_US3_I (1u << 3) /* specific to UltraSPARC-IIIi */ 62*7c478bd9Sstevel@tonic-gate #define V_END (1u << 31) 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate /* 65*7c478bd9Sstevel@tonic-gate * map from "cpu version" to flag bits 66*7c478bd9Sstevel@tonic-gate */ 67*7c478bd9Sstevel@tonic-gate static const uint_t cpuvermap[] = { 68*7c478bd9Sstevel@tonic-gate V_US12, /* CPC_ULTRA1 */ 69*7c478bd9Sstevel@tonic-gate V_US12, /* CPC_ULTRA2 */ 70*7c478bd9Sstevel@tonic-gate V_US3, /* CPC_ULTRA3 */ 71*7c478bd9Sstevel@tonic-gate V_US3_PLUS, /* CPC_ULTRA3_PLUS */ 72*7c478bd9Sstevel@tonic-gate V_US3_I /* CPC_ULTRA3I */ 73*7c478bd9Sstevel@tonic-gate }; 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate struct nametable { 76*7c478bd9Sstevel@tonic-gate const uint_t ver; 77*7c478bd9Sstevel@tonic-gate const uint8_t bits; 78*7c478bd9Sstevel@tonic-gate const char *name; 79*7c478bd9Sstevel@tonic-gate }; 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate * Definitions for counter 0 83*7c478bd9Sstevel@tonic-gate */ 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate #define USall_EVENTS_0(v) \ 86*7c478bd9Sstevel@tonic-gate {v, 0x0, "Cycle_cnt"}, \ 87*7c478bd9Sstevel@tonic-gate {v, 0x1, "Instr_cnt"}, \ 88*7c478bd9Sstevel@tonic-gate {v, 0x2, "Dispatch0_IC_miss"}, \ 89*7c478bd9Sstevel@tonic-gate {v, 0x8, "IC_ref"}, \ 90*7c478bd9Sstevel@tonic-gate {v, 0x9, "DC_rd"}, \ 91*7c478bd9Sstevel@tonic-gate {v, 0xa, "DC_wr"}, \ 92*7c478bd9Sstevel@tonic-gate {v, 0xc, "EC_ref"}, \ 93*7c478bd9Sstevel@tonic-gate {v, 0xe, "EC_snoop_inv"} 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate static const struct nametable US12_names0[] = { 96*7c478bd9Sstevel@tonic-gate USall_EVENTS_0(V_US12), 97*7c478bd9Sstevel@tonic-gate {V_US12, 0x3, "Dispatch0_storeBuf"}, 98*7c478bd9Sstevel@tonic-gate {V_US12, 0xb, "Load_use"}, 99*7c478bd9Sstevel@tonic-gate {V_US12, 0xd, "EC_write_hit_RDO"}, 100*7c478bd9Sstevel@tonic-gate {V_US12, 0xf, "EC_rd_hit"}, 101*7c478bd9Sstevel@tonic-gate {V_END} 102*7c478bd9Sstevel@tonic-gate }; 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate #define US3all_EVENTS_0(v) \ 105*7c478bd9Sstevel@tonic-gate {v, 0x3, "Dispatch0_br_target"}, \ 106*7c478bd9Sstevel@tonic-gate {v, 0x4, "Dispatch0_2nd_br"}, \ 107*7c478bd9Sstevel@tonic-gate {v, 0x5, "Rstall_storeQ"}, \ 108*7c478bd9Sstevel@tonic-gate {v, 0x6, "Rstall_IU_use"}, \ 109*7c478bd9Sstevel@tonic-gate {v, 0xd, "EC_write_hit_RTO"}, \ 110*7c478bd9Sstevel@tonic-gate {v, 0xf, "EC_rd_miss"}, \ 111*7c478bd9Sstevel@tonic-gate {v, 0x10, "PC_port0_rd"}, \ 112*7c478bd9Sstevel@tonic-gate {v, 0x11, "SI_snoop"}, \ 113*7c478bd9Sstevel@tonic-gate {v, 0x12, "SI_ciq_flow"}, \ 114*7c478bd9Sstevel@tonic-gate {v, 0x13, "SI_owned"}, \ 115*7c478bd9Sstevel@tonic-gate {v, 0x14, "SW_count_0"}, \ 116*7c478bd9Sstevel@tonic-gate {v, 0x15, "IU_Stat_Br_miss_taken"}, \ 117*7c478bd9Sstevel@tonic-gate {v, 0x16, "IU_Stat_Br_count_taken"}, \ 118*7c478bd9Sstevel@tonic-gate {v, 0x17, "Dispatch_rs_mispred"}, \ 119*7c478bd9Sstevel@tonic-gate {v, 0x18, "FA_pipe_completion"} 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate #define US3_MC_EVENTS_0(v) \ 122*7c478bd9Sstevel@tonic-gate {v, 0x20, "MC_reads_0"}, \ 123*7c478bd9Sstevel@tonic-gate {v, 0x21, "MC_reads_1"}, \ 124*7c478bd9Sstevel@tonic-gate {v, 0x22, "MC_reads_2"}, \ 125*7c478bd9Sstevel@tonic-gate {v, 0x23, "MC_reads_3"}, \ 126*7c478bd9Sstevel@tonic-gate {v, 0x24, "MC_stalls_0"}, \ 127*7c478bd9Sstevel@tonic-gate {v, 0x25, "MC_stalls_2"} 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate #define US3_I_MC_EVENTS_0(v) \ 130*7c478bd9Sstevel@tonic-gate {v, 0x20, "MC_read_dispatched"}, \ 131*7c478bd9Sstevel@tonic-gate {v, 0x21, "MC_write_dispatched"}, \ 132*7c478bd9Sstevel@tonic-gate {v, 0x22, "MC_read_returned_to_JBU"}, \ 133*7c478bd9Sstevel@tonic-gate {v, 0x23, "MC_msl_busy_stall"}, \ 134*7c478bd9Sstevel@tonic-gate {v, 0x24, "MC_mdb_overflow_stall"}, \ 135*7c478bd9Sstevel@tonic-gate {v, 0x25, "MC_miu_spec_request"} 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate static const struct nametable US3_names0[] = { 138*7c478bd9Sstevel@tonic-gate USall_EVENTS_0(V_US3), 139*7c478bd9Sstevel@tonic-gate US3all_EVENTS_0(V_US3), 140*7c478bd9Sstevel@tonic-gate US3_MC_EVENTS_0(V_US3), 141*7c478bd9Sstevel@tonic-gate {V_END} 142*7c478bd9Sstevel@tonic-gate }; 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate static const struct nametable US3_PLUS_names0[] = { 145*7c478bd9Sstevel@tonic-gate USall_EVENTS_0(V_US3_PLUS), 146*7c478bd9Sstevel@tonic-gate US3all_EVENTS_0(V_US3_PLUS), 147*7c478bd9Sstevel@tonic-gate US3_MC_EVENTS_0(V_US3_PLUS), 148*7c478bd9Sstevel@tonic-gate {V_US3_PLUS, 0x19, "EC_wb_remote"}, 149*7c478bd9Sstevel@tonic-gate {V_US3_PLUS, 0x1a, "EC_miss_local"}, 150*7c478bd9Sstevel@tonic-gate {V_US3_PLUS, 0x1b, "EC_miss_mtag_remote"}, 151*7c478bd9Sstevel@tonic-gate {V_END} 152*7c478bd9Sstevel@tonic-gate }; 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate static const struct nametable US3_I_names0[] = { 155*7c478bd9Sstevel@tonic-gate USall_EVENTS_0(V_US3_I), 156*7c478bd9Sstevel@tonic-gate US3all_EVENTS_0(V_US3_I), 157*7c478bd9Sstevel@tonic-gate US3_I_MC_EVENTS_0(V_US3_I), 158*7c478bd9Sstevel@tonic-gate {V_US3_PLUS, 0x19, "EC_wb_remote"}, 159*7c478bd9Sstevel@tonic-gate {V_US3_PLUS, 0x1a, "EC_miss_local"}, 160*7c478bd9Sstevel@tonic-gate {V_US3_PLUS, 0x1b, "EC_miss_mtag_remote"}, 161*7c478bd9Sstevel@tonic-gate {V_END} 162*7c478bd9Sstevel@tonic-gate }; 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate #undef USall_EVENTS_0 165*7c478bd9Sstevel@tonic-gate #undef US3all_EVENTS_0 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate #define USall_EVENTS_1(v) \ 168*7c478bd9Sstevel@tonic-gate {v, 0x0, "Cycle_cnt"}, \ 169*7c478bd9Sstevel@tonic-gate {v, 0x1, "Instr_cnt"}, \ 170*7c478bd9Sstevel@tonic-gate {v, 0x2, "Dispatch0_mispred"}, \ 171*7c478bd9Sstevel@tonic-gate {v, 0xd, "EC_wb"}, \ 172*7c478bd9Sstevel@tonic-gate {v, 0xe, "EC_snoop_cb"} 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate static const struct nametable US12_names1[] = { 175*7c478bd9Sstevel@tonic-gate USall_EVENTS_1(V_US12), 176*7c478bd9Sstevel@tonic-gate {V_US12, 0x3, "Dispatch0_FP_use"}, 177*7c478bd9Sstevel@tonic-gate {V_US12, 0x8, "IC_hit"}, 178*7c478bd9Sstevel@tonic-gate {V_US12, 0x9, "DC_rd_hit"}, 179*7c478bd9Sstevel@tonic-gate {V_US12, 0xa, "DC_wr_hit"}, 180*7c478bd9Sstevel@tonic-gate {V_US12, 0xb, "Load_use_RAW"}, 181*7c478bd9Sstevel@tonic-gate {V_US12, 0xc, "EC_hit"}, 182*7c478bd9Sstevel@tonic-gate {V_US12, 0xf, "EC_ic_hit"}, 183*7c478bd9Sstevel@tonic-gate {V_END} 184*7c478bd9Sstevel@tonic-gate }; 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate #define US3all_EVENTS_1(v) \ 187*7c478bd9Sstevel@tonic-gate {v, 0x3, "IC_miss_cancelled"}, \ 188*7c478bd9Sstevel@tonic-gate {v, 0x5, "Re_FPU_bypass"}, \ 189*7c478bd9Sstevel@tonic-gate {v, 0x6, "Re_DC_miss"}, \ 190*7c478bd9Sstevel@tonic-gate {v, 0x7, "Re_EC_miss"}, \ 191*7c478bd9Sstevel@tonic-gate {v, 0x8, "IC_miss"}, \ 192*7c478bd9Sstevel@tonic-gate {v, 0x9, "DC_rd_miss"}, \ 193*7c478bd9Sstevel@tonic-gate {v, 0xa, "DC_wr_miss"}, \ 194*7c478bd9Sstevel@tonic-gate {v, 0xb, "Rstall_FP_use"}, \ 195*7c478bd9Sstevel@tonic-gate {v, 0xc, "EC_misses"}, \ 196*7c478bd9Sstevel@tonic-gate {v, 0xf, "EC_ic_miss"}, \ 197*7c478bd9Sstevel@tonic-gate {v, 0x10, "Re_PC_miss"}, \ 198*7c478bd9Sstevel@tonic-gate {v, 0x11, "ITLB_miss"}, \ 199*7c478bd9Sstevel@tonic-gate {v, 0x12, "DTLB_miss"}, \ 200*7c478bd9Sstevel@tonic-gate {v, 0x13, "WC_miss"}, \ 201*7c478bd9Sstevel@tonic-gate {v, 0x14, "WC_snoop_cb"}, \ 202*7c478bd9Sstevel@tonic-gate {v, 0x15, "WC_scrubbed"}, \ 203*7c478bd9Sstevel@tonic-gate {v, 0x16, "WC_wb_wo_read"}, \ 204*7c478bd9Sstevel@tonic-gate {v, 0x18, "PC_soft_hit"}, \ 205*7c478bd9Sstevel@tonic-gate {v, 0x19, "PC_snoop_inv"}, \ 206*7c478bd9Sstevel@tonic-gate {v, 0x1a, "PC_hard_hit"}, \ 207*7c478bd9Sstevel@tonic-gate {v, 0x1b, "PC_port1_rd"}, \ 208*7c478bd9Sstevel@tonic-gate {v, 0x1c, "SW_count_1"}, \ 209*7c478bd9Sstevel@tonic-gate {v, 0x1d, "IU_Stat_Br_miss_untaken"}, \ 210*7c478bd9Sstevel@tonic-gate {v, 0x1e, "IU_Stat_Br_count_untaken"}, \ 211*7c478bd9Sstevel@tonic-gate {v, 0x1f, "PC_MS_misses"}, \ 212*7c478bd9Sstevel@tonic-gate {v, 0x26, "Re_RAW_miss"}, \ 213*7c478bd9Sstevel@tonic-gate {v, 0x27, "FM_pipe_completion"} 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate #define US3_MC_EVENTS_1(v) \ 216*7c478bd9Sstevel@tonic-gate {v, 0x20, "MC_writes_0"}, \ 217*7c478bd9Sstevel@tonic-gate {v, 0x21, "MC_writes_1"}, \ 218*7c478bd9Sstevel@tonic-gate {v, 0x22, "MC_writes_2"}, \ 219*7c478bd9Sstevel@tonic-gate {v, 0x23, "MC_writes_3"}, \ 220*7c478bd9Sstevel@tonic-gate {v, 0x24, "MC_stalls_1"}, \ 221*7c478bd9Sstevel@tonic-gate {v, 0x25, "MC_stalls_3"} 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate #define US3_I_MC_EVENTS_1(v) \ 224*7c478bd9Sstevel@tonic-gate {v, 0x20, "MC_open_bank_cmds"}, \ 225*7c478bd9Sstevel@tonic-gate {v, 0x21, "MC_reads"}, \ 226*7c478bd9Sstevel@tonic-gate {v, 0x22, "MC_writes"}, \ 227*7c478bd9Sstevel@tonic-gate {v, 0x23, "MC_page_close_stall"} 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate static const struct nametable US3_names1[] = { 230*7c478bd9Sstevel@tonic-gate USall_EVENTS_1(V_US3), 231*7c478bd9Sstevel@tonic-gate US3all_EVENTS_1(V_US3), 232*7c478bd9Sstevel@tonic-gate US3_MC_EVENTS_1(V_US3), 233*7c478bd9Sstevel@tonic-gate {V_US3, 0x4, "Re_endian_miss"}, 234*7c478bd9Sstevel@tonic-gate {V_END} 235*7c478bd9Sstevel@tonic-gate }; 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate static const struct nametable US3_PLUS_names1[] = { 238*7c478bd9Sstevel@tonic-gate USall_EVENTS_1(V_US3_PLUS), 239*7c478bd9Sstevel@tonic-gate US3all_EVENTS_1(V_US3_PLUS), 240*7c478bd9Sstevel@tonic-gate US3_MC_EVENTS_1(V_US3_PLUS), 241*7c478bd9Sstevel@tonic-gate {V_US3_PLUS, 0x4, "Re_DC_missovhd"}, 242*7c478bd9Sstevel@tonic-gate {V_US3_PLUS, 0x28, "EC_miss_mtag_remote"}, 243*7c478bd9Sstevel@tonic-gate {V_US3_PLUS, 0x29, "EC_miss_remote"}, 244*7c478bd9Sstevel@tonic-gate {V_END} 245*7c478bd9Sstevel@tonic-gate }; 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate static const struct nametable US3_I_names1[] = { 248*7c478bd9Sstevel@tonic-gate USall_EVENTS_1(V_US3_I), 249*7c478bd9Sstevel@tonic-gate US3all_EVENTS_1(V_US3_I), 250*7c478bd9Sstevel@tonic-gate US3_I_MC_EVENTS_1(V_US3_I), 251*7c478bd9Sstevel@tonic-gate {V_US3_I, 0x4, "Re_DC_missovhd"}, 252*7c478bd9Sstevel@tonic-gate {V_END} 253*7c478bd9Sstevel@tonic-gate }; 254*7c478bd9Sstevel@tonic-gate #undef USall_EVENTS_1 255*7c478bd9Sstevel@tonic-gate #undef US3all_EVENTS_1 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate static const struct nametable *US12_names[2] = { 258*7c478bd9Sstevel@tonic-gate US12_names0, 259*7c478bd9Sstevel@tonic-gate US12_names1 260*7c478bd9Sstevel@tonic-gate }; 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate static const struct nametable *US3_names[2] = { 263*7c478bd9Sstevel@tonic-gate US3_names0, 264*7c478bd9Sstevel@tonic-gate US3_names1 265*7c478bd9Sstevel@tonic-gate }; 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate static const struct nametable *US3_PLUS_names[2] = { 268*7c478bd9Sstevel@tonic-gate US3_PLUS_names0, 269*7c478bd9Sstevel@tonic-gate US3_PLUS_names1 270*7c478bd9Sstevel@tonic-gate }; 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate static const struct nametable *US3_I_names[2] = { 273*7c478bd9Sstevel@tonic-gate US3_I_names0, 274*7c478bd9Sstevel@tonic-gate US3_I_names1 275*7c478bd9Sstevel@tonic-gate }; 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate #define MAPCPUVER(cpuver) (cpuvermap[(cpuver) - CPC_ULTRA1]) 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate static int 280*7c478bd9Sstevel@tonic-gate validargs(int cpuver, int regno) 281*7c478bd9Sstevel@tonic-gate { 282*7c478bd9Sstevel@tonic-gate if (regno < 0 || regno > 1) 283*7c478bd9Sstevel@tonic-gate return (0); 284*7c478bd9Sstevel@tonic-gate cpuver -= CPC_ULTRA1; 285*7c478bd9Sstevel@tonic-gate if (cpuver < 0 || 286*7c478bd9Sstevel@tonic-gate cpuver >= sizeof (cpuvermap) / sizeof (cpuvermap[0])) 287*7c478bd9Sstevel@tonic-gate return (0); 288*7c478bd9Sstevel@tonic-gate return (1); 289*7c478bd9Sstevel@tonic-gate } 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 292*7c478bd9Sstevel@tonic-gate static int 293*7c478bd9Sstevel@tonic-gate versionmatch(int cpuver, int regno, const struct nametable *n) 294*7c478bd9Sstevel@tonic-gate { 295*7c478bd9Sstevel@tonic-gate if (!validargs(cpuver, regno) || n->ver != MAPCPUVER(cpuver)) 296*7c478bd9Sstevel@tonic-gate return (0); 297*7c478bd9Sstevel@tonic-gate return (1); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate static const struct nametable * 301*7c478bd9Sstevel@tonic-gate getnametable(int cpuver, int regno) 302*7c478bd9Sstevel@tonic-gate { 303*7c478bd9Sstevel@tonic-gate const struct nametable *n; 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate if (!validargs(cpuver, regno)) 306*7c478bd9Sstevel@tonic-gate return (NULL); 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate switch (MAPCPUVER(cpuver)) { 309*7c478bd9Sstevel@tonic-gate case V_US12: 310*7c478bd9Sstevel@tonic-gate n = US12_names[regno]; 311*7c478bd9Sstevel@tonic-gate break; 312*7c478bd9Sstevel@tonic-gate case V_US3: 313*7c478bd9Sstevel@tonic-gate n = US3_names[regno]; 314*7c478bd9Sstevel@tonic-gate break; 315*7c478bd9Sstevel@tonic-gate case V_US3_PLUS: 316*7c478bd9Sstevel@tonic-gate n = US3_PLUS_names[regno]; 317*7c478bd9Sstevel@tonic-gate break; 318*7c478bd9Sstevel@tonic-gate case V_US3_I: 319*7c478bd9Sstevel@tonic-gate n = US3_I_names[regno]; 320*7c478bd9Sstevel@tonic-gate break; 321*7c478bd9Sstevel@tonic-gate default: 322*7c478bd9Sstevel@tonic-gate n = NULL; 323*7c478bd9Sstevel@tonic-gate break; 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate return (n); 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate void 329*7c478bd9Sstevel@tonic-gate cpc_walk_names(int cpuver, int regno, void *arg, 330*7c478bd9Sstevel@tonic-gate void (*action)(void *, int, const char *, uint8_t)) 331*7c478bd9Sstevel@tonic-gate { 332*7c478bd9Sstevel@tonic-gate const struct nametable *n; 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate if ((n = getnametable(cpuver, regno)) == NULL) 335*7c478bd9Sstevel@tonic-gate return; 336*7c478bd9Sstevel@tonic-gate for (; n->ver != V_END; n++) 337*7c478bd9Sstevel@tonic-gate if (versionmatch(cpuver, regno, n)) 338*7c478bd9Sstevel@tonic-gate action(arg, regno, n->name, n->bits); 339*7c478bd9Sstevel@tonic-gate } 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate const char * 342*7c478bd9Sstevel@tonic-gate __cpc_reg_to_name(int cpuver, int regno, uint8_t bits) 343*7c478bd9Sstevel@tonic-gate { 344*7c478bd9Sstevel@tonic-gate const struct nametable *n; 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate if ((n = getnametable(cpuver, regno)) == NULL) 347*7c478bd9Sstevel@tonic-gate return (NULL); 348*7c478bd9Sstevel@tonic-gate for (; n->ver != V_END; n++) 349*7c478bd9Sstevel@tonic-gate if (bits == n->bits && versionmatch(cpuver, regno, n)) 350*7c478bd9Sstevel@tonic-gate return (n->name); 351*7c478bd9Sstevel@tonic-gate return (NULL); 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate /* 355*7c478bd9Sstevel@tonic-gate * Register names can be specified as strings or even as numbers 356*7c478bd9Sstevel@tonic-gate */ 357*7c478bd9Sstevel@tonic-gate int 358*7c478bd9Sstevel@tonic-gate __cpc_name_to_reg(int cpuver, int regno, const char *name, uint8_t *bits) 359*7c478bd9Sstevel@tonic-gate { 360*7c478bd9Sstevel@tonic-gate const struct nametable *n; 361*7c478bd9Sstevel@tonic-gate char *eptr = NULL; 362*7c478bd9Sstevel@tonic-gate long value; 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate if ((n = getnametable(cpuver, regno)) == NULL || name == NULL) 365*7c478bd9Sstevel@tonic-gate return (-1); 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate for (; n->ver != V_END; n++) 368*7c478bd9Sstevel@tonic-gate if (strcmp(name, n->name) == 0 && 369*7c478bd9Sstevel@tonic-gate versionmatch(cpuver, regno, n)) { 370*7c478bd9Sstevel@tonic-gate *bits = n->bits; 371*7c478bd9Sstevel@tonic-gate return (0); 372*7c478bd9Sstevel@tonic-gate } 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate value = strtol(name, &eptr, 0); 375*7c478bd9Sstevel@tonic-gate if (name != eptr && value >= 0 && value <= UINT8_MAX) { 376*7c478bd9Sstevel@tonic-gate *bits = (uint8_t)value; 377*7c478bd9Sstevel@tonic-gate return (0); 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate return (-1); 381*7c478bd9Sstevel@tonic-gate } 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate const char * 384*7c478bd9Sstevel@tonic-gate cpc_getcciname(int cpuver) 385*7c478bd9Sstevel@tonic-gate { 386*7c478bd9Sstevel@tonic-gate if (validargs(cpuver, 0)) 387*7c478bd9Sstevel@tonic-gate switch (MAPCPUVER(cpuver)) { 388*7c478bd9Sstevel@tonic-gate case V_US12: 389*7c478bd9Sstevel@tonic-gate return ("UltraSPARC I&II"); 390*7c478bd9Sstevel@tonic-gate case V_US3: 391*7c478bd9Sstevel@tonic-gate return ("UltraSPARC III"); 392*7c478bd9Sstevel@tonic-gate case V_US3_PLUS: 393*7c478bd9Sstevel@tonic-gate return ("UltraSPARC III+ & IV"); 394*7c478bd9Sstevel@tonic-gate case V_US3_I: 395*7c478bd9Sstevel@tonic-gate return ("UltraSPARC IIIi & IIIi+"); 396*7c478bd9Sstevel@tonic-gate default: 397*7c478bd9Sstevel@tonic-gate break; 398*7c478bd9Sstevel@tonic-gate } 399*7c478bd9Sstevel@tonic-gate return (NULL); 400*7c478bd9Sstevel@tonic-gate } 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate #define CPU_REF_URL " Documentation for Sun processors can be found at: " \ 403*7c478bd9Sstevel@tonic-gate "http://www.sun.com/processors/manuals" 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate const char * 406*7c478bd9Sstevel@tonic-gate cpc_getcpuref(int cpuver) 407*7c478bd9Sstevel@tonic-gate { 408*7c478bd9Sstevel@tonic-gate if (validargs(cpuver, 0)) 409*7c478bd9Sstevel@tonic-gate switch (MAPCPUVER(cpuver)) { 410*7c478bd9Sstevel@tonic-gate case V_US12: 411*7c478bd9Sstevel@tonic-gate return (gettext( 412*7c478bd9Sstevel@tonic-gate "See the \"UltraSPARC I/II User\'s Manual\" " 413*7c478bd9Sstevel@tonic-gate "(Part No. 802-7220-02) " 414*7c478bd9Sstevel@tonic-gate "for descriptions of these events." CPU_REF_URL)); 415*7c478bd9Sstevel@tonic-gate case V_US3: 416*7c478bd9Sstevel@tonic-gate case V_US3_PLUS: 417*7c478bd9Sstevel@tonic-gate return (gettext( 418*7c478bd9Sstevel@tonic-gate "See the \"UltraSPARC III Cu User's Manual\" " 419*7c478bd9Sstevel@tonic-gate "for descriptions of these events." CPU_REF_URL)); 420*7c478bd9Sstevel@tonic-gate case V_US3_I: 421*7c478bd9Sstevel@tonic-gate return (gettext( 422*7c478bd9Sstevel@tonic-gate "See the \"UltraSPARC IIIi User's Manual\" " 423*7c478bd9Sstevel@tonic-gate "for descriptions of these events." CPU_REF_URL)); 424*7c478bd9Sstevel@tonic-gate default: 425*7c478bd9Sstevel@tonic-gate break; 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate return (NULL); 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate /* 431*7c478bd9Sstevel@tonic-gate * This is a functional interface to allow CPUs with fewer %pic registers 432*7c478bd9Sstevel@tonic-gate * to share the same data structure as those with more %pic registers 433*7c478bd9Sstevel@tonic-gate * within the same instruction family. 434*7c478bd9Sstevel@tonic-gate */ 435*7c478bd9Sstevel@tonic-gate uint_t 436*7c478bd9Sstevel@tonic-gate cpc_getnpic(int cpuver) 437*7c478bd9Sstevel@tonic-gate { 438*7c478bd9Sstevel@tonic-gate /*LINTED*/ 439*7c478bd9Sstevel@tonic-gate cpc_event_t *event; 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate switch (cpuver) { 442*7c478bd9Sstevel@tonic-gate case CPC_ULTRA1: 443*7c478bd9Sstevel@tonic-gate case CPC_ULTRA2: 444*7c478bd9Sstevel@tonic-gate case CPC_ULTRA3: 445*7c478bd9Sstevel@tonic-gate case CPC_ULTRA3_PLUS: 446*7c478bd9Sstevel@tonic-gate case CPC_ULTRA3_I: 447*7c478bd9Sstevel@tonic-gate return (sizeof (event->ce_pic) / sizeof (event->ce_pic[0])); 448*7c478bd9Sstevel@tonic-gate default: 449*7c478bd9Sstevel@tonic-gate return (0); 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate /* 454*7c478bd9Sstevel@tonic-gate * Compares the given string against the list of all known CPU node names, and 455*7c478bd9Sstevel@tonic-gate * returns the CPC CPU version code if there is a match. If there is no match, 456*7c478bd9Sstevel@tonic-gate * returns -1. 457*7c478bd9Sstevel@tonic-gate */ 458*7c478bd9Sstevel@tonic-gate static int 459*7c478bd9Sstevel@tonic-gate node2ver(char *node) 460*7c478bd9Sstevel@tonic-gate { 461*7c478bd9Sstevel@tonic-gate if (strcmp(node, "SUNW,UltraSPARC") == 0 || 462*7c478bd9Sstevel@tonic-gate strcmp(node, "SUNW,UltraSPARC-II") == 0 || 463*7c478bd9Sstevel@tonic-gate strcmp(node, "SUNW,UltraSPARC-IIi") == 0 || 464*7c478bd9Sstevel@tonic-gate strcmp(node, "SUNW,UltraSPARC-IIe") == 0) { 465*7c478bd9Sstevel@tonic-gate return (CPC_ULTRA1); 466*7c478bd9Sstevel@tonic-gate } else if (strcmp(node, "SUNW,UltraSPARC-III") == 0) 467*7c478bd9Sstevel@tonic-gate return (CPC_ULTRA3); 468*7c478bd9Sstevel@tonic-gate else if (strcmp(node, "SUNW,UltraSPARC-III+") == 0 || 469*7c478bd9Sstevel@tonic-gate strcmp(node, "SUNW,UltraSPARC-IV") == 0 || 470*7c478bd9Sstevel@tonic-gate strcmp(node, "SUNW,UltraSPARC-IV+") == 0) 471*7c478bd9Sstevel@tonic-gate return (CPC_ULTRA3_PLUS); 472*7c478bd9Sstevel@tonic-gate else if (strcmp(node, "SUNW,UltraSPARC-IIIi") == 0 || 473*7c478bd9Sstevel@tonic-gate strcmp(node, "SUNW,UltraSPARC-IIIi+") == 0) 474*7c478bd9Sstevel@tonic-gate return (CPC_ULTRA3_I); 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate return (-1); 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate static int 480*7c478bd9Sstevel@tonic-gate cpc_get_cpu_ver(di_node_t di_node, void *arg) 481*7c478bd9Sstevel@tonic-gate { 482*7c478bd9Sstevel@tonic-gate char *node_name, *compatible_array; 483*7c478bd9Sstevel@tonic-gate int n_names, i, found = 0; 484*7c478bd9Sstevel@tonic-gate int *ver = arg; 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate node_name = di_node_name(di_node); 487*7c478bd9Sstevel@tonic-gate if (node_name != NULL) { 488*7c478bd9Sstevel@tonic-gate if ((*ver = node2ver(node_name)) != -1) 489*7c478bd9Sstevel@tonic-gate found = 1; 490*7c478bd9Sstevel@tonic-gate else if (strncmp(node_name, "cpu", 4) == 0) { 491*7c478bd9Sstevel@tonic-gate /* 492*7c478bd9Sstevel@tonic-gate * CPU nodes associated with CMP use the generic name 493*7c478bd9Sstevel@tonic-gate * of "cpu". We must look at the compatible property 494*7c478bd9Sstevel@tonic-gate * in order to find the implementation specific name. 495*7c478bd9Sstevel@tonic-gate */ 496*7c478bd9Sstevel@tonic-gate if ((n_names = di_compatible_names(di_node, 497*7c478bd9Sstevel@tonic-gate &compatible_array)) > 0) { 498*7c478bd9Sstevel@tonic-gate for (i = 0; i < n_names; i++) { 499*7c478bd9Sstevel@tonic-gate if ((*ver = node2ver(compatible_array)) 500*7c478bd9Sstevel@tonic-gate != -1) { 501*7c478bd9Sstevel@tonic-gate found = 1; 502*7c478bd9Sstevel@tonic-gate break; 503*7c478bd9Sstevel@tonic-gate } 504*7c478bd9Sstevel@tonic-gate compatible_array += 505*7c478bd9Sstevel@tonic-gate strlen(compatible_array) + 1; 506*7c478bd9Sstevel@tonic-gate } 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate } 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate if (found == 0) 512*7c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 515*7c478bd9Sstevel@tonic-gate } 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate /* 518*7c478bd9Sstevel@tonic-gate * Return the version of the current processor. 519*7c478bd9Sstevel@tonic-gate * 520*7c478bd9Sstevel@tonic-gate * Version -1 is defined as 'not performance counter capable' 521*7c478bd9Sstevel@tonic-gate * 522*7c478bd9Sstevel@tonic-gate * XXX A better solution would be to use the di_prom_props for the cpu 523*7c478bd9Sstevel@tonic-gate * devinfo nodes. That way we could look at the 'device-type', 'sparc-version' 524*7c478bd9Sstevel@tonic-gate * and 'implementation#' properties in order to determine which version of 525*7c478bd9Sstevel@tonic-gate * UltraSPARC we are running on. 526*7c478bd9Sstevel@tonic-gate * 527*7c478bd9Sstevel@tonic-gate * The problem with this is that di_prom_init() requires root access to 528*7c478bd9Sstevel@tonic-gate * open /dev/openprom and cputrack is not a root-only application so 529*7c478bd9Sstevel@tonic-gate * we have to settle for the di_props that we can see as non-root users. 530*7c478bd9Sstevel@tonic-gate */ 531*7c478bd9Sstevel@tonic-gate int 532*7c478bd9Sstevel@tonic-gate cpc_getcpuver(void) 533*7c478bd9Sstevel@tonic-gate { 534*7c478bd9Sstevel@tonic-gate static int ver = -1; 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate if (ver == -1) { 537*7c478bd9Sstevel@tonic-gate di_node_t di_root_node; 538*7c478bd9Sstevel@tonic-gate 539*7c478bd9Sstevel@tonic-gate if ((di_root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) 540*7c478bd9Sstevel@tonic-gate return (-1); 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate (void) di_walk_node(di_root_node, DI_WALK_CLDFIRST, 543*7c478bd9Sstevel@tonic-gate (void *)&ver, cpc_get_cpu_ver); 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate di_fini(di_root_node); 546*7c478bd9Sstevel@tonic-gate } 547*7c478bd9Sstevel@tonic-gate return (ver); 548*7c478bd9Sstevel@tonic-gate } 549