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 2004 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 36*7c478bd9Sstevel@tonic-gate #include "libcpc.h" 37*7c478bd9Sstevel@tonic-gate #include "libcpc_impl.h" 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate /* 40*7c478bd9Sstevel@tonic-gate * Configuration data for Pentium Pro performance counters. 41*7c478bd9Sstevel@tonic-gate * 42*7c478bd9Sstevel@tonic-gate * Definitions taken from [3]. See the reference to 43*7c478bd9Sstevel@tonic-gate * understand what any of these settings actually means. 44*7c478bd9Sstevel@tonic-gate * 45*7c478bd9Sstevel@tonic-gate * [3] "Pentium Pro Family Developer's Manual, Volume 3: 46*7c478bd9Sstevel@tonic-gate * Operating Systems Writer's Manual," January 1996 47*7c478bd9Sstevel@tonic-gate */ 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #define V_P5 (1u << 0) /* specific to Pentium cpus */ 50*7c478bd9Sstevel@tonic-gate #define V_P5mmx (1u << 1) /* " MMX instructions */ 51*7c478bd9Sstevel@tonic-gate #define V_P6 (1u << 2) /* specific to Pentium II cpus */ 52*7c478bd9Sstevel@tonic-gate #define V_P6mmx (1u << 3) /* " MMX instructions */ 53*7c478bd9Sstevel@tonic-gate #define V_END 0 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate /* 56*7c478bd9Sstevel@tonic-gate * map from "cpu version" to flag bits 57*7c478bd9Sstevel@tonic-gate */ 58*7c478bd9Sstevel@tonic-gate static const uint_t cpuvermap[] = { 59*7c478bd9Sstevel@tonic-gate V_P5, /* CPC_PENTIUM */ 60*7c478bd9Sstevel@tonic-gate V_P5 | V_P5mmx, /* CPC_PENTIUM_MMX */ 61*7c478bd9Sstevel@tonic-gate V_P6, /* CPC_PENTIUM_PRO */ 62*7c478bd9Sstevel@tonic-gate V_P6 | V_P6mmx, /* CPC_PENTIUM_PRO_MMX */ 63*7c478bd9Sstevel@tonic-gate }; 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate struct nametable { 66*7c478bd9Sstevel@tonic-gate const uint_t ver; 67*7c478bd9Sstevel@tonic-gate const uint8_t bits; 68*7c478bd9Sstevel@tonic-gate const char *name; 69*7c478bd9Sstevel@tonic-gate }; 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate /* 72*7c478bd9Sstevel@tonic-gate * Basic Pentium events 73*7c478bd9Sstevel@tonic-gate */ 74*7c478bd9Sstevel@tonic-gate #define P5_EVENTS(v) \ 75*7c478bd9Sstevel@tonic-gate {v, 0x0, "data_read"}, \ 76*7c478bd9Sstevel@tonic-gate {v, 0x1, "data_write"}, \ 77*7c478bd9Sstevel@tonic-gate {v, 0x2, "data_tlb_miss"}, \ 78*7c478bd9Sstevel@tonic-gate {v, 0x3, "data_read_miss"}, \ 79*7c478bd9Sstevel@tonic-gate {v, 0x4, "data_write_miss"}, \ 80*7c478bd9Sstevel@tonic-gate {v, 0x5, "write_hit_to_M_or_E"}, \ 81*7c478bd9Sstevel@tonic-gate {v, 0x6, "dcache_lines_wrback"}, \ 82*7c478bd9Sstevel@tonic-gate {v, 0x7, "external_snoops"}, \ 83*7c478bd9Sstevel@tonic-gate {v, 0x8, "external_dcache_snoop_hits"}, \ 84*7c478bd9Sstevel@tonic-gate {v, 0x9, "memory_access_in_both_pipes"}, \ 85*7c478bd9Sstevel@tonic-gate {v, 0xa, "bank_conflicts"}, \ 86*7c478bd9Sstevel@tonic-gate {v, 0xb, "misaligned_ref"}, \ 87*7c478bd9Sstevel@tonic-gate {v, 0xc, "code_read"}, \ 88*7c478bd9Sstevel@tonic-gate {v, 0xd, "code_tlb_miss"}, \ 89*7c478bd9Sstevel@tonic-gate {v, 0xe, "code_cache_miss"}, \ 90*7c478bd9Sstevel@tonic-gate {v, 0xf, "any_segreg_loaded"}, \ 91*7c478bd9Sstevel@tonic-gate {v, 0x12, "branches"}, \ 92*7c478bd9Sstevel@tonic-gate {v, 0x13, "btb_hits"}, \ 93*7c478bd9Sstevel@tonic-gate {v, 0x14, "taken_or_btb_hit"}, \ 94*7c478bd9Sstevel@tonic-gate {v, 0x15, "pipeline_flushes"}, \ 95*7c478bd9Sstevel@tonic-gate {v, 0x16, "instr_exec"}, \ 96*7c478bd9Sstevel@tonic-gate {v, 0x17, "instr_exec_V_pipe"}, \ 97*7c478bd9Sstevel@tonic-gate {v, 0x18, "clks_bus_cycle"}, \ 98*7c478bd9Sstevel@tonic-gate {v, 0x19, "clks_full_wbufs"}, \ 99*7c478bd9Sstevel@tonic-gate {v, 0x1a, "pipe_stall_read"}, \ 100*7c478bd9Sstevel@tonic-gate {v, 0x1b, "stall_on_write_ME"}, \ 101*7c478bd9Sstevel@tonic-gate {v, 0x1c, "locked_bus_cycle"}, \ 102*7c478bd9Sstevel@tonic-gate {v, 0x1d, "io_rw_cycles"}, \ 103*7c478bd9Sstevel@tonic-gate {v, 0x1e, "reads_noncache_mem"}, \ 104*7c478bd9Sstevel@tonic-gate {v, 0x1f, "pipeline_agi_stalls"}, \ 105*7c478bd9Sstevel@tonic-gate {v, 0x22, "flops"}, \ 106*7c478bd9Sstevel@tonic-gate {v, 0x23, "bp_match_dr0"}, \ 107*7c478bd9Sstevel@tonic-gate {v, 0x24, "bp_match_dr1"}, \ 108*7c478bd9Sstevel@tonic-gate {v, 0x25, "bp_match_dr2"}, \ 109*7c478bd9Sstevel@tonic-gate {v, 0x26, "bp_match_dr3"}, \ 110*7c478bd9Sstevel@tonic-gate {v, 0x27, "hw_intrs"}, \ 111*7c478bd9Sstevel@tonic-gate {v, 0x28, "data_rw"}, \ 112*7c478bd9Sstevel@tonic-gate {v, 0x29, "data_rw_miss"} 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate static const struct nametable P5mmx_names0[] = { 115*7c478bd9Sstevel@tonic-gate P5_EVENTS(V_P5), 116*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x2a, "bus_ownership_latency"}, 117*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x2b, "mmx_instr_upipe"}, 118*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x2c, "cache_M_line_sharing"}, 119*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x2d, "emms_instr"}, 120*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x2e, "bus_util_processor"}, 121*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x2f, "sat_mmx_instr"}, 122*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x30, "clks_not_HLT"}, 123*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x31, "mmx_data_read"}, 124*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x32, "clks_fp_stall"}, 125*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x33, "d1_starv_fifo_0"}, 126*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x34, "mmx_data_write"}, 127*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x35, "pipe_flush_wbp"}, 128*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x36, "mmx_misalign_data_refs"}, 129*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x37, "rets_pred_incorrect"}, 130*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x38, "mmx_multiply_unit_interlock"}, 131*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x39, "rets"}, 132*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x3a, "btb_false_entries"}, 133*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x3b, "clocks_stall_full_wb"}, 134*7c478bd9Sstevel@tonic-gate {V_END} 135*7c478bd9Sstevel@tonic-gate }; 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate static const struct nametable P5mmx_names1[] = { 138*7c478bd9Sstevel@tonic-gate P5_EVENTS(V_P5), 139*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x2a, "bus_ownership_transfers"}, 140*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x2b, "mmx_instr_vpipe"}, 141*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x2c, "cache_lint_sharing"}, 142*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x2d, "mmx_fp_transitions"}, 143*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x2e, "writes_noncache_mem"}, 144*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x2f, "sats_performed"}, 145*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x30, "clks_dcache_tlb_miss"}, 146*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x31, "mmx_data_read_miss"}, 147*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x32, "taken_br"}, 148*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x33, "d1_starv_fifo_1"}, 149*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x34, "mmx_data_write_miss"}, 150*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x35, "pipe_flush_wbp_wb"}, 151*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x36, "mmx_pipe_stall_data_read"}, 152*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x37, "rets_pred"}, 153*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x38, "movd_movq_stall"}, 154*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x39, "rsb_overflow"}, 155*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x3a, "btb_mispred_nt"}, 156*7c478bd9Sstevel@tonic-gate {V_P5mmx, 0x3b, "mmx_stall_write_ME"}, 157*7c478bd9Sstevel@tonic-gate {V_END} 158*7c478bd9Sstevel@tonic-gate }; 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate static const struct nametable *P5mmx_names[2] = { 161*7c478bd9Sstevel@tonic-gate P5mmx_names0, 162*7c478bd9Sstevel@tonic-gate P5mmx_names1 163*7c478bd9Sstevel@tonic-gate }; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * Pentium Pro and Pentium II events 167*7c478bd9Sstevel@tonic-gate */ 168*7c478bd9Sstevel@tonic-gate static const struct nametable P6_names[] = { 169*7c478bd9Sstevel@tonic-gate /* 170*7c478bd9Sstevel@tonic-gate * Data cache unit 171*7c478bd9Sstevel@tonic-gate */ 172*7c478bd9Sstevel@tonic-gate {V_P6, 0x43, "data_mem_refs"}, 173*7c478bd9Sstevel@tonic-gate {V_P6, 0x45, "dcu_lines_in"}, 174*7c478bd9Sstevel@tonic-gate {V_P6, 0x46, "dcu_m_lines_in"}, 175*7c478bd9Sstevel@tonic-gate {V_P6, 0x47, "dcu_m_lines_out"}, 176*7c478bd9Sstevel@tonic-gate {V_P6, 0x48, "dcu_miss_outstanding"}, 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate /* 179*7c478bd9Sstevel@tonic-gate * Instruction fetch unit 180*7c478bd9Sstevel@tonic-gate */ 181*7c478bd9Sstevel@tonic-gate {V_P6, 0x80, "ifu_ifetch"}, 182*7c478bd9Sstevel@tonic-gate {V_P6, 0x81, "ifu_ifetch_miss"}, 183*7c478bd9Sstevel@tonic-gate {V_P6, 0x85, "itlb_miss"}, 184*7c478bd9Sstevel@tonic-gate {V_P6, 0x86, "ifu_mem_stall"}, 185*7c478bd9Sstevel@tonic-gate {V_P6, 0x87, "ild_stall"}, 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate /* 188*7c478bd9Sstevel@tonic-gate * L2 cache 189*7c478bd9Sstevel@tonic-gate */ 190*7c478bd9Sstevel@tonic-gate {V_P6, 0x28, "l2_ifetch"}, 191*7c478bd9Sstevel@tonic-gate {V_P6, 0x29, "l2_ld"}, 192*7c478bd9Sstevel@tonic-gate {V_P6, 0x2a, "l2_st"}, 193*7c478bd9Sstevel@tonic-gate {V_P6, 0x24, "l2_lines_in"}, 194*7c478bd9Sstevel@tonic-gate {V_P6, 0x26, "l2_lines_out"}, 195*7c478bd9Sstevel@tonic-gate {V_P6, 0x25, "l2_m_lines_inm"}, 196*7c478bd9Sstevel@tonic-gate {V_P6, 0x27, "l2_m_lines_outm"}, 197*7c478bd9Sstevel@tonic-gate {V_P6, 0x2e, "l2_rqsts"}, 198*7c478bd9Sstevel@tonic-gate {V_P6, 0x21, "l2_ads"}, 199*7c478bd9Sstevel@tonic-gate {V_P6, 0x22, "l2_dbus_busy"}, 200*7c478bd9Sstevel@tonic-gate {V_P6, 0x23, "l2_dbus_busy_rd"}, 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate /* 203*7c478bd9Sstevel@tonic-gate * External bus logic 204*7c478bd9Sstevel@tonic-gate */ 205*7c478bd9Sstevel@tonic-gate {V_P6, 0x62, "bus_drdy_clocks"}, 206*7c478bd9Sstevel@tonic-gate {V_P6, 0x63, "bus_lock_clocks"}, 207*7c478bd9Sstevel@tonic-gate {V_P6, 0x60, "bus_req_outstanding"}, 208*7c478bd9Sstevel@tonic-gate {V_P6, 0x65, "bus_tran_brd"}, 209*7c478bd9Sstevel@tonic-gate {V_P6, 0x66, "bus_tran_rfo"}, 210*7c478bd9Sstevel@tonic-gate {V_P6, 0x67, "bus_trans_wb"}, 211*7c478bd9Sstevel@tonic-gate {V_P6, 0x68, "bus_tran_ifetch"}, 212*7c478bd9Sstevel@tonic-gate {V_P6, 0x69, "bus_tran_inval"}, 213*7c478bd9Sstevel@tonic-gate {V_P6, 0x6a, "bus_tran_pwr"}, 214*7c478bd9Sstevel@tonic-gate {V_P6, 0x6b, "bus_trans_p"}, 215*7c478bd9Sstevel@tonic-gate {V_P6, 0x6c, "bus_trans_io"}, 216*7c478bd9Sstevel@tonic-gate {V_P6, 0x6d, "bus_tran_def"}, 217*7c478bd9Sstevel@tonic-gate {V_P6, 0x6e, "bus_tran_burst"}, 218*7c478bd9Sstevel@tonic-gate {V_P6, 0x70, "bus_tran_any"}, 219*7c478bd9Sstevel@tonic-gate {V_P6, 0x6f, "bus_tran_mem"}, 220*7c478bd9Sstevel@tonic-gate {V_P6, 0x64, "bus_data_rcv"}, 221*7c478bd9Sstevel@tonic-gate {V_P6, 0x61, "bus_bnr_drv"}, 222*7c478bd9Sstevel@tonic-gate {V_P6, 0x7a, "bus_hit_drv"}, 223*7c478bd9Sstevel@tonic-gate {V_P6, 0x7b, "bus_hitm_drv"}, 224*7c478bd9Sstevel@tonic-gate {V_P6, 0x7e, "bus_snoop_stall"}, 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate /* 227*7c478bd9Sstevel@tonic-gate * Floating point unit 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate {V_P6, 0xc1, "flops"}, /* 0 only */ 230*7c478bd9Sstevel@tonic-gate {V_P6, 0x10, "fp_comp_ops_exe"}, /* 0 only */ 231*7c478bd9Sstevel@tonic-gate {V_P6, 0x11, "fp_assist"}, /* 1 only */ 232*7c478bd9Sstevel@tonic-gate {V_P6, 0x12, "mul"}, /* 1 only */ 233*7c478bd9Sstevel@tonic-gate {V_P6, 0x13, "div"}, /* 1 only */ 234*7c478bd9Sstevel@tonic-gate {V_P6, 0x14, "cycles_div_busy"}, /* 0 only */ 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate /* 237*7c478bd9Sstevel@tonic-gate * Memory ordering 238*7c478bd9Sstevel@tonic-gate */ 239*7c478bd9Sstevel@tonic-gate {V_P6, 0x3, "ld_blocks"}, 240*7c478bd9Sstevel@tonic-gate {V_P6, 0x4, "sb_drains"}, 241*7c478bd9Sstevel@tonic-gate {V_P6, 0x5, "misalign_mem_ref"}, 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate /* 244*7c478bd9Sstevel@tonic-gate * Instruction decoding and retirement 245*7c478bd9Sstevel@tonic-gate */ 246*7c478bd9Sstevel@tonic-gate {V_P6, 0xc0, "inst_retired"}, 247*7c478bd9Sstevel@tonic-gate {V_P6, 0xc2, "uops_retired"}, 248*7c478bd9Sstevel@tonic-gate {V_P6, 0xd0, "inst_decoder"}, 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate /* 251*7c478bd9Sstevel@tonic-gate * Interrupts 252*7c478bd9Sstevel@tonic-gate */ 253*7c478bd9Sstevel@tonic-gate {V_P6, 0xc8, "hw_int_rx"}, 254*7c478bd9Sstevel@tonic-gate {V_P6, 0xc6, "cycles_int_masked"}, 255*7c478bd9Sstevel@tonic-gate {V_P6, 0xc7, "cycles_int_pending_and_masked"}, 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate /* 258*7c478bd9Sstevel@tonic-gate * Branches 259*7c478bd9Sstevel@tonic-gate */ 260*7c478bd9Sstevel@tonic-gate {V_P6, 0xc4, "br_inst_retired"}, 261*7c478bd9Sstevel@tonic-gate {V_P6, 0xc5, "br_miss_pred_retired"}, 262*7c478bd9Sstevel@tonic-gate {V_P6, 0xc9, "br_taken_retired"}, 263*7c478bd9Sstevel@tonic-gate {V_P6, 0xca, "br_miss_pred_taken_ret"}, 264*7c478bd9Sstevel@tonic-gate {V_P6, 0xe0, "br_inst_decoded"}, 265*7c478bd9Sstevel@tonic-gate {V_P6, 0xe2, "btb_misses"}, 266*7c478bd9Sstevel@tonic-gate {V_P6, 0xe4, "br_bogus"}, 267*7c478bd9Sstevel@tonic-gate {V_P6, 0xe6, "baclears"}, 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate /* 270*7c478bd9Sstevel@tonic-gate * Stalls 271*7c478bd9Sstevel@tonic-gate */ 272*7c478bd9Sstevel@tonic-gate {V_P6, 0xa2, "resource_stalls"}, 273*7c478bd9Sstevel@tonic-gate {V_P6, 0xd2, "partial_rat_stalls"}, 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate /* 276*7c478bd9Sstevel@tonic-gate * Segment register loads 277*7c478bd9Sstevel@tonic-gate */ 278*7c478bd9Sstevel@tonic-gate {V_P6, 0x6, "segment_reg_loads"}, 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate /* 281*7c478bd9Sstevel@tonic-gate * Clocks 282*7c478bd9Sstevel@tonic-gate */ 283*7c478bd9Sstevel@tonic-gate {V_P6, 0x79, "cpu_clk_unhalted"}, 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate /* 286*7c478bd9Sstevel@tonic-gate * MMX 287*7c478bd9Sstevel@tonic-gate */ 288*7c478bd9Sstevel@tonic-gate {V_P6mmx, 0xb0, "mmx_instr_exec"}, 289*7c478bd9Sstevel@tonic-gate {V_P6mmx, 0xb1, "mmx_sat_instr_exec"}, 290*7c478bd9Sstevel@tonic-gate {V_P6mmx, 0xb2, "mmx_uops_exec"}, 291*7c478bd9Sstevel@tonic-gate {V_P6mmx, 0xb3, "mmx_instr_type_exec"}, 292*7c478bd9Sstevel@tonic-gate {V_P6mmx, 0xcc, "fp_mmx_trans"}, 293*7c478bd9Sstevel@tonic-gate {V_P6mmx, 0xcd, "mmx_assists"}, 294*7c478bd9Sstevel@tonic-gate {V_P6mmx, 0xce, "mmx_instr_ret"}, 295*7c478bd9Sstevel@tonic-gate {V_P6mmx, 0xd4, "seg_rename_stalls"}, 296*7c478bd9Sstevel@tonic-gate {V_P6mmx, 0xd5, "seg_reg_renames"}, 297*7c478bd9Sstevel@tonic-gate {V_P6mmx, 0xd6, "ret_seg_renames"}, 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate {V_END} 300*7c478bd9Sstevel@tonic-gate }; 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate #define MAPCPUVER(cpuver) (cpuvermap[(cpuver) - CPC_PENTIUM]) 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate static int 305*7c478bd9Sstevel@tonic-gate validargs(int cpuver, int regno) 306*7c478bd9Sstevel@tonic-gate { 307*7c478bd9Sstevel@tonic-gate if (regno < 0 || regno > 1) 308*7c478bd9Sstevel@tonic-gate return (0); 309*7c478bd9Sstevel@tonic-gate cpuver -= CPC_PENTIUM; 310*7c478bd9Sstevel@tonic-gate if (cpuver < 0 || 311*7c478bd9Sstevel@tonic-gate cpuver >= sizeof (cpuvermap) / sizeof (cpuvermap[0])) 312*7c478bd9Sstevel@tonic-gate return (0); 313*7c478bd9Sstevel@tonic-gate return (1); 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 317*7c478bd9Sstevel@tonic-gate static int 318*7c478bd9Sstevel@tonic-gate versionmatch(int cpuver, int regno, const struct nametable *n) 319*7c478bd9Sstevel@tonic-gate { 320*7c478bd9Sstevel@tonic-gate if (!validargs(cpuver, regno) || (n->ver & MAPCPUVER(cpuver)) == 0) 321*7c478bd9Sstevel@tonic-gate return (0); 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate switch (MAPCPUVER(cpuver)) { 324*7c478bd9Sstevel@tonic-gate case V_P5: 325*7c478bd9Sstevel@tonic-gate case V_P5 | V_P5mmx: 326*7c478bd9Sstevel@tonic-gate break; 327*7c478bd9Sstevel@tonic-gate case V_P6: 328*7c478bd9Sstevel@tonic-gate case V_P6 | V_P6mmx: 329*7c478bd9Sstevel@tonic-gate switch (n->bits) { 330*7c478bd9Sstevel@tonic-gate case 0xc1: /* flops */ 331*7c478bd9Sstevel@tonic-gate case 0x10: /* fp_comp_ops_exe */ 332*7c478bd9Sstevel@tonic-gate case 0x14: /* cycles_div_busy */ 333*7c478bd9Sstevel@tonic-gate /* only reg0 counts these */ 334*7c478bd9Sstevel@tonic-gate if (regno == 1) 335*7c478bd9Sstevel@tonic-gate return (0); 336*7c478bd9Sstevel@tonic-gate break; 337*7c478bd9Sstevel@tonic-gate case 0x11: /* fp_assist */ 338*7c478bd9Sstevel@tonic-gate case 0x12: /* mul */ 339*7c478bd9Sstevel@tonic-gate case 0x13: /* div */ 340*7c478bd9Sstevel@tonic-gate /* only 1 can count these */ 341*7c478bd9Sstevel@tonic-gate if (regno == 0) 342*7c478bd9Sstevel@tonic-gate return (0); 343*7c478bd9Sstevel@tonic-gate break; 344*7c478bd9Sstevel@tonic-gate default: 345*7c478bd9Sstevel@tonic-gate break; 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate break; 348*7c478bd9Sstevel@tonic-gate default: 349*7c478bd9Sstevel@tonic-gate return (0); 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate return (1); 353*7c478bd9Sstevel@tonic-gate } 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate static const struct nametable * 356*7c478bd9Sstevel@tonic-gate getnametable(int cpuver, int regno) 357*7c478bd9Sstevel@tonic-gate { 358*7c478bd9Sstevel@tonic-gate const struct nametable *n; 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate if (!validargs(cpuver, regno)) 361*7c478bd9Sstevel@tonic-gate return (NULL); 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate switch (MAPCPUVER(cpuver)) { 364*7c478bd9Sstevel@tonic-gate case V_P5: 365*7c478bd9Sstevel@tonic-gate case V_P5 | V_P5mmx: 366*7c478bd9Sstevel@tonic-gate n = P5mmx_names[regno]; 367*7c478bd9Sstevel@tonic-gate break; 368*7c478bd9Sstevel@tonic-gate case V_P6: 369*7c478bd9Sstevel@tonic-gate case V_P6 | V_P6mmx: 370*7c478bd9Sstevel@tonic-gate n = P6_names; 371*7c478bd9Sstevel@tonic-gate break; 372*7c478bd9Sstevel@tonic-gate default: 373*7c478bd9Sstevel@tonic-gate n = NULL; 374*7c478bd9Sstevel@tonic-gate break; 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate return (n); 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate void 381*7c478bd9Sstevel@tonic-gate cpc_walk_names(int cpuver, int regno, void *arg, 382*7c478bd9Sstevel@tonic-gate void (*action)(void *, int, const char *, uint8_t)) 383*7c478bd9Sstevel@tonic-gate { 384*7c478bd9Sstevel@tonic-gate const struct nametable *n; 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate if ((n = getnametable(cpuver, regno)) == NULL) 387*7c478bd9Sstevel@tonic-gate return; 388*7c478bd9Sstevel@tonic-gate for (; n->ver != V_END; n++) 389*7c478bd9Sstevel@tonic-gate if (versionmatch(cpuver, regno, n)) 390*7c478bd9Sstevel@tonic-gate action(arg, regno, n->name, n->bits); 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate const char * 394*7c478bd9Sstevel@tonic-gate __cpc_reg_to_name(int cpuver, int regno, uint8_t bits) 395*7c478bd9Sstevel@tonic-gate { 396*7c478bd9Sstevel@tonic-gate const struct nametable *n; 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate if ((n = getnametable(cpuver, regno)) == NULL) 399*7c478bd9Sstevel@tonic-gate return (NULL); 400*7c478bd9Sstevel@tonic-gate for (; n->ver != V_END; n++) 401*7c478bd9Sstevel@tonic-gate if (bits == n->bits && versionmatch(cpuver, regno, n)) 402*7c478bd9Sstevel@tonic-gate return (n->name); 403*7c478bd9Sstevel@tonic-gate return (NULL); 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate /* 407*7c478bd9Sstevel@tonic-gate * Register names can be specified as strings or even as numbers 408*7c478bd9Sstevel@tonic-gate */ 409*7c478bd9Sstevel@tonic-gate int 410*7c478bd9Sstevel@tonic-gate __cpc_name_to_reg(int cpuver, int regno, const char *name, uint8_t *bits) 411*7c478bd9Sstevel@tonic-gate { 412*7c478bd9Sstevel@tonic-gate const struct nametable *n; 413*7c478bd9Sstevel@tonic-gate char *eptr = NULL; 414*7c478bd9Sstevel@tonic-gate long value; 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate if ((n = getnametable(cpuver, regno)) == NULL || name == NULL) 417*7c478bd9Sstevel@tonic-gate return (-1); 418*7c478bd9Sstevel@tonic-gate for (; n->ver != V_END; n++) 419*7c478bd9Sstevel@tonic-gate if (strcmp(name, n->name) == 0 && 420*7c478bd9Sstevel@tonic-gate versionmatch(cpuver, regno, n)) { 421*7c478bd9Sstevel@tonic-gate *bits = n->bits; 422*7c478bd9Sstevel@tonic-gate return (0); 423*7c478bd9Sstevel@tonic-gate } 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate value = strtol(name, &eptr, 0); 426*7c478bd9Sstevel@tonic-gate if (name != eptr && value >= 0 && value <= UINT8_MAX) { 427*7c478bd9Sstevel@tonic-gate *bits = (uint8_t)value; 428*7c478bd9Sstevel@tonic-gate return (0); 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate return (-1); 432*7c478bd9Sstevel@tonic-gate } 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate const char * 435*7c478bd9Sstevel@tonic-gate cpc_getcciname(int cpuver) 436*7c478bd9Sstevel@tonic-gate { 437*7c478bd9Sstevel@tonic-gate if (validargs(cpuver, 0)) 438*7c478bd9Sstevel@tonic-gate switch (MAPCPUVER(cpuver)) { 439*7c478bd9Sstevel@tonic-gate case V_P5: 440*7c478bd9Sstevel@tonic-gate return ("Pentium"); 441*7c478bd9Sstevel@tonic-gate case V_P5 | V_P5mmx: 442*7c478bd9Sstevel@tonic-gate return ("Pentium with MMX"); 443*7c478bd9Sstevel@tonic-gate case V_P6: 444*7c478bd9Sstevel@tonic-gate return ("Pentium Pro, Pentium II"); 445*7c478bd9Sstevel@tonic-gate case V_P6 | V_P6mmx: 446*7c478bd9Sstevel@tonic-gate return ("Pentium Pro with MMX, Pentium II"); 447*7c478bd9Sstevel@tonic-gate default: 448*7c478bd9Sstevel@tonic-gate break; 449*7c478bd9Sstevel@tonic-gate } 450*7c478bd9Sstevel@tonic-gate return (NULL); 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate const char * 454*7c478bd9Sstevel@tonic-gate cpc_getcpuref(int cpuver) 455*7c478bd9Sstevel@tonic-gate { 456*7c478bd9Sstevel@tonic-gate if (validargs(cpuver, 0)) 457*7c478bd9Sstevel@tonic-gate switch (MAPCPUVER(cpuver)) { 458*7c478bd9Sstevel@tonic-gate case V_P5: 459*7c478bd9Sstevel@tonic-gate case V_P5 | V_P5mmx: 460*7c478bd9Sstevel@tonic-gate return (gettext( 461*7c478bd9Sstevel@tonic-gate "See Appendix A.2 of the \"Intel Architecture " 462*7c478bd9Sstevel@tonic-gate "Software Developer's Manual,\" 243192, 1997")); 463*7c478bd9Sstevel@tonic-gate case V_P6: 464*7c478bd9Sstevel@tonic-gate case V_P6 | V_P6mmx: 465*7c478bd9Sstevel@tonic-gate return (gettext( 466*7c478bd9Sstevel@tonic-gate "See Appendix A.1 of the \"Intel Architecture " 467*7c478bd9Sstevel@tonic-gate "Software Developer's Manual,\" 243192, 1997")); 468*7c478bd9Sstevel@tonic-gate default: 469*7c478bd9Sstevel@tonic-gate break; 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate return (NULL); 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate /* 475*7c478bd9Sstevel@tonic-gate * This is a functional interface to allow CPUs with fewer %pic registers 476*7c478bd9Sstevel@tonic-gate * to share the same data structure as those with more %pic registers 477*7c478bd9Sstevel@tonic-gate * within the same instruction set family. 478*7c478bd9Sstevel@tonic-gate */ 479*7c478bd9Sstevel@tonic-gate uint_t 480*7c478bd9Sstevel@tonic-gate cpc_getnpic(int cpuver) 481*7c478bd9Sstevel@tonic-gate { 482*7c478bd9Sstevel@tonic-gate switch (cpuver) { 483*7c478bd9Sstevel@tonic-gate case CPC_PENTIUM: 484*7c478bd9Sstevel@tonic-gate case CPC_PENTIUM_MMX: 485*7c478bd9Sstevel@tonic-gate case CPC_PENTIUM_PRO: 486*7c478bd9Sstevel@tonic-gate case CPC_PENTIUM_PRO_MMX: 487*7c478bd9Sstevel@tonic-gate #define EVENT ((cpc_event_t *)0) 488*7c478bd9Sstevel@tonic-gate return (sizeof (EVENT->ce_pic) / sizeof (EVENT->ce_pic[0])); 489*7c478bd9Sstevel@tonic-gate #undef EVENT 490*7c478bd9Sstevel@tonic-gate default: 491*7c478bd9Sstevel@tonic-gate return (0); 492*7c478bd9Sstevel@tonic-gate } 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate #define BITS(v, u, l) \ 496*7c478bd9Sstevel@tonic-gate (((v) >> (l)) & ((1 << (1 + (u) - (l))) - 1)) 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate #include "getcpuid.h" 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate /* 501*7c478bd9Sstevel@tonic-gate * Return the version of the current processor. 502*7c478bd9Sstevel@tonic-gate * 503*7c478bd9Sstevel@tonic-gate * Version -1 is defined as 'not performance counter capable' 504*7c478bd9Sstevel@tonic-gate */ 505*7c478bd9Sstevel@tonic-gate int 506*7c478bd9Sstevel@tonic-gate cpc_getcpuver(void) 507*7c478bd9Sstevel@tonic-gate { 508*7c478bd9Sstevel@tonic-gate static int ver = -1; 509*7c478bd9Sstevel@tonic-gate uint32_t maxeax; 510*7c478bd9Sstevel@tonic-gate uint32_t vbuf[4]; 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate if (ver != -1) 513*7c478bd9Sstevel@tonic-gate return (ver); 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate maxeax = cpc_getcpuid(0, &vbuf[0], &vbuf[2], &vbuf[1]); 516*7c478bd9Sstevel@tonic-gate { 517*7c478bd9Sstevel@tonic-gate char *vendor = (char *)vbuf; 518*7c478bd9Sstevel@tonic-gate vendor[12] = '\0'; 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate if (strcmp(vendor, "GenuineIntel") != 0) 521*7c478bd9Sstevel@tonic-gate return (ver); 522*7c478bd9Sstevel@tonic-gate } 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate if (maxeax >= 1) { 525*7c478bd9Sstevel@tonic-gate int family, model; 526*7c478bd9Sstevel@tonic-gate uint32_t eax, ebx, ecx, edx; 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate eax = cpc_getcpuid(1, &ebx, &ecx, &edx); 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate if ((family = BITS(eax, 11, 8)) == 0xf) 531*7c478bd9Sstevel@tonic-gate family = BITS(eax, 27, 20); 532*7c478bd9Sstevel@tonic-gate if ((model = BITS(eax, 7, 4)) == 0xf) 533*7c478bd9Sstevel@tonic-gate model = BITS(eax, 19, 16); 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate /* 536*7c478bd9Sstevel@tonic-gate * map family and model into the performance 537*7c478bd9Sstevel@tonic-gate * counter architectures we currently understand. 538*7c478bd9Sstevel@tonic-gate * 539*7c478bd9Sstevel@tonic-gate * See application note AP485 (from developer.intel.com) 540*7c478bd9Sstevel@tonic-gate * for further explanation. 541*7c478bd9Sstevel@tonic-gate */ 542*7c478bd9Sstevel@tonic-gate switch (family) { 543*7c478bd9Sstevel@tonic-gate case 5: /* Pentium and Pentium with MMX */ 544*7c478bd9Sstevel@tonic-gate ver = model < 4 ? 545*7c478bd9Sstevel@tonic-gate CPC_PENTIUM : CPC_PENTIUM_MMX; 546*7c478bd9Sstevel@tonic-gate break; 547*7c478bd9Sstevel@tonic-gate case 6: /* Pentium Pro and Pentium II and III */ 548*7c478bd9Sstevel@tonic-gate ver = BITS(edx, 23, 23) ? /* mmx check */ 549*7c478bd9Sstevel@tonic-gate CPC_PENTIUM_PRO_MMX : CPC_PENTIUM_PRO; 550*7c478bd9Sstevel@tonic-gate break; 551*7c478bd9Sstevel@tonic-gate default: 552*7c478bd9Sstevel@tonic-gate case 0xf: /* Pentium IV */ 553*7c478bd9Sstevel@tonic-gate break; 554*7c478bd9Sstevel@tonic-gate } 555*7c478bd9Sstevel@tonic-gate } 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate return (ver); 558*7c478bd9Sstevel@tonic-gate } 559