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