125cf1a30Sjl139090 /* 225cf1a30Sjl139090 * CDDL HEADER START 325cf1a30Sjl139090 * 425cf1a30Sjl139090 * The contents of this file are subject to the terms of the 525cf1a30Sjl139090 * Common Development and Distribution License (the "License"). 625cf1a30Sjl139090 * You may not use this file except in compliance with the License. 725cf1a30Sjl139090 * 825cf1a30Sjl139090 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 925cf1a30Sjl139090 * or http://www.opensolaris.org/os/licensing. 1025cf1a30Sjl139090 * See the License for the specific language governing permissions 1125cf1a30Sjl139090 * and limitations under the License. 1225cf1a30Sjl139090 * 1325cf1a30Sjl139090 * When distributing Covered Code, include this CDDL HEADER in each 1425cf1a30Sjl139090 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1525cf1a30Sjl139090 * If applicable, add the following below this CDDL HEADER, with the 1625cf1a30Sjl139090 * fields enclosed by brackets "[]" replaced with your own identifying 1725cf1a30Sjl139090 * information: Portions Copyright [yyyy] [name of copyright owner] 1825cf1a30Sjl139090 * 1925cf1a30Sjl139090 * CDDL HEADER END 2025cf1a30Sjl139090 */ 2125cf1a30Sjl139090 /* 2231632b73Swh31274 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2325cf1a30Sjl139090 * Use is subject to license terms. 2425cf1a30Sjl139090 */ 2525cf1a30Sjl139090 2625cf1a30Sjl139090 /* 27*c7a079a8SJonathan Haslam * This file contains preset event names from the Performance Application 28*c7a079a8SJonathan Haslam * Programming Interface v3.5 which included the following notice: 29*c7a079a8SJonathan Haslam * 30*c7a079a8SJonathan Haslam * Copyright (c) 2005,6 31*c7a079a8SJonathan Haslam * Innovative Computing Labs 32*c7a079a8SJonathan Haslam * Computer Science Department, 33*c7a079a8SJonathan Haslam * University of Tennessee, 34*c7a079a8SJonathan Haslam * Knoxville, TN. 35*c7a079a8SJonathan Haslam * All Rights Reserved. 36*c7a079a8SJonathan Haslam * 37*c7a079a8SJonathan Haslam * 38*c7a079a8SJonathan Haslam * Redistribution and use in source and binary forms, with or without 39*c7a079a8SJonathan Haslam * modification, are permitted provided that the following conditions are met: 40*c7a079a8SJonathan Haslam * 41*c7a079a8SJonathan Haslam * * Redistributions of source code must retain the above copyright notice, 42*c7a079a8SJonathan Haslam * this list of conditions and the following disclaimer. 43*c7a079a8SJonathan Haslam * * Redistributions in binary form must reproduce the above copyright 44*c7a079a8SJonathan Haslam * notice, this list of conditions and the following disclaimer in the 45*c7a079a8SJonathan Haslam * documentation and/or other materials provided with the distribution. 46*c7a079a8SJonathan Haslam * * Neither the name of the University of Tennessee nor the names of its 47*c7a079a8SJonathan Haslam * contributors may be used to endorse or promote products derived from 48*c7a079a8SJonathan Haslam * this software without specific prior written permission. 49*c7a079a8SJonathan Haslam * 50*c7a079a8SJonathan Haslam * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 51*c7a079a8SJonathan Haslam * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52*c7a079a8SJonathan Haslam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53*c7a079a8SJonathan Haslam * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 54*c7a079a8SJonathan Haslam * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 55*c7a079a8SJonathan Haslam * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 56*c7a079a8SJonathan Haslam * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 57*c7a079a8SJonathan Haslam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 58*c7a079a8SJonathan Haslam * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 59*c7a079a8SJonathan Haslam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 60*c7a079a8SJonathan Haslam * POSSIBILITY OF SUCH DAMAGE. 61*c7a079a8SJonathan Haslam * 62*c7a079a8SJonathan Haslam * 63*c7a079a8SJonathan Haslam * This open source software license conforms to the BSD License template. 6425cf1a30Sjl139090 */ 6525cf1a30Sjl139090 66*c7a079a8SJonathan Haslam /* 67*c7a079a8SJonathan Haslam * SPARC64 VI & VII Performance Counter Backend 68*c7a079a8SJonathan Haslam */ 6925cf1a30Sjl139090 7025cf1a30Sjl139090 #include <sys/cpuvar.h> 7125cf1a30Sjl139090 #include <sys/systm.h> 7225cf1a30Sjl139090 #include <sys/cmn_err.h> 7325cf1a30Sjl139090 #include <sys/cpc_impl.h> 7425cf1a30Sjl139090 #include <sys/cpc_pcbe.h> 7525cf1a30Sjl139090 #include <sys/modctl.h> 7625cf1a30Sjl139090 #include <sys/machsystm.h> 7725cf1a30Sjl139090 #include <sys/sdt.h> 7825cf1a30Sjl139090 #include <sys/cpu_impl.h> 7925cf1a30Sjl139090 8025cf1a30Sjl139090 static int opl_pcbe_init(void); 8125cf1a30Sjl139090 static uint_t opl_pcbe_ncounters(void); 8225cf1a30Sjl139090 static const char *opl_pcbe_impl_name(void); 8325cf1a30Sjl139090 static const char *opl_pcbe_cpuref(void); 8425cf1a30Sjl139090 static char *opl_pcbe_list_events(uint_t picnum); 8525cf1a30Sjl139090 static char *opl_pcbe_list_attrs(void); 8625cf1a30Sjl139090 static uint64_t opl_pcbe_event_coverage(char *event); 8725cf1a30Sjl139090 static uint64_t opl_pcbe_overflow_bitmap(void); 8825cf1a30Sjl139090 static int opl_pcbe_configure(uint_t picnum, char *event, uint64_t preset, 8925cf1a30Sjl139090 uint32_t flags, uint_t nattrs, kcpc_attr_t *attrs, void **data, 9025cf1a30Sjl139090 void *token); 9125cf1a30Sjl139090 static void opl_pcbe_program(void *token); 9225cf1a30Sjl139090 static void opl_pcbe_allstop(void); 9325cf1a30Sjl139090 static void opl_pcbe_sample(void *token); 9425cf1a30Sjl139090 static void opl_pcbe_free(void *config); 9525cf1a30Sjl139090 9625cf1a30Sjl139090 extern void ultra_setpcr(uint64_t); 9725cf1a30Sjl139090 extern uint64_t ultra_getpcr(void); 9825cf1a30Sjl139090 extern void ultra_setpic(uint64_t); 9925cf1a30Sjl139090 extern uint64_t ultra_getpic(void); 10025cf1a30Sjl139090 extern uint64_t ultra_gettick(void); 10125cf1a30Sjl139090 10225cf1a30Sjl139090 pcbe_ops_t opl_pcbe_ops = { 10325cf1a30Sjl139090 PCBE_VER_1, 10425cf1a30Sjl139090 CPC_CAP_OVERFLOW_INTERRUPT, 10525cf1a30Sjl139090 opl_pcbe_ncounters, 10625cf1a30Sjl139090 opl_pcbe_impl_name, 10725cf1a30Sjl139090 opl_pcbe_cpuref, 10825cf1a30Sjl139090 opl_pcbe_list_events, 10925cf1a30Sjl139090 opl_pcbe_list_attrs, 11025cf1a30Sjl139090 opl_pcbe_event_coverage, 11125cf1a30Sjl139090 opl_pcbe_overflow_bitmap, 11225cf1a30Sjl139090 opl_pcbe_configure, 11325cf1a30Sjl139090 opl_pcbe_program, 11425cf1a30Sjl139090 opl_pcbe_allstop, 11525cf1a30Sjl139090 opl_pcbe_sample, 11625cf1a30Sjl139090 opl_pcbe_free 11725cf1a30Sjl139090 }; 11825cf1a30Sjl139090 11925cf1a30Sjl139090 typedef struct _opl_pcbe_config { 12025cf1a30Sjl139090 uint8_t opl_picno; /* From 0 to 7 */ 12125cf1a30Sjl139090 uint32_t opl_bits; /* %pcr event code unshifted */ 12225cf1a30Sjl139090 uint32_t opl_flags; /* user/system/priv */ 12325cf1a30Sjl139090 uint32_t opl_pic; /* unshifted raw %pic value */ 12425cf1a30Sjl139090 } opl_pcbe_config_t; 12525cf1a30Sjl139090 12625cf1a30Sjl139090 struct nametable { 12725cf1a30Sjl139090 const uint8_t bits; 12825cf1a30Sjl139090 const char *name; 12925cf1a30Sjl139090 }; 13025cf1a30Sjl139090 131*c7a079a8SJonathan Haslam typedef struct _opl_generic_event { 132*c7a079a8SJonathan Haslam char *name; 133*c7a079a8SJonathan Haslam char *event; 134*c7a079a8SJonathan Haslam } opl_generic_event_t; 135*c7a079a8SJonathan Haslam 136d1e4508aSsubhan /* 137d1e4508aSsubhan * Performance Control Register (PCR) 138d1e4508aSsubhan * 139d1e4508aSsubhan * +----------+-----+-----+------+----+ 140d1e4508aSsubhan * | 0 | OVF | 0 | OVR0 | 0 | 141d1e4508aSsubhan * +----------+-----+-----+------+----+ 142d1e4508aSsubhan * 63 48 47:32 31:27 26 25 143d1e4508aSsubhan * 144d1e4508aSsubhan * +----+----+--- -+----+-----+---+-----+-----+----+----+----+ 145d1e4508aSsubhan * | NC | 0 | SC | 0 | SU | 0 | SL |ULRO | UT | ST |PRIV| 146d1e4508aSsubhan * +----+----+-----+----+-----+---+-----+-----+----+----+----+ 147d1e4508aSsubhan * 24:22 21 20:18 17 16:11 10 9:4 3 2 1 0 148d1e4508aSsubhan * 1495a1b32ccSsubhan * ULRO and OVRO bits should be on upon accessing pcr unless 1505a1b32ccSsubhan * those fields need to be updated. 1515a1b32ccSsubhan * Turn off these bits when updating SU/SL or OVF field 1525a1b32ccSsubhan * (during initialization, etc.). 1535a1b32ccSsubhan * 154d1e4508aSsubhan * 155d1e4508aSsubhan * Performance Instrumentation Counter (PIC) 156e98fafb9Sjl139090 * Four PICs are implemented in SPARC64 VI and VII, 157d1e4508aSsubhan * each PIC is accessed using PCR.SC as a select field. 158d1e4508aSsubhan * 159d1e4508aSsubhan * +------------------------+--------------------------+ 160d1e4508aSsubhan * | PICU | PICL | 161d1e4508aSsubhan * +------------------------+--------------------------+ 162d1e4508aSsubhan * 63 32 31 0 163d1e4508aSsubhan */ 164d1e4508aSsubhan 16525cf1a30Sjl139090 #define PIC_MASK (((uint64_t)1 << 32) - 1) 16625cf1a30Sjl139090 167d1e4508aSsubhan #define SPARC64_VI_PCR_PRIVPIC UINT64_C(0) 16825cf1a30Sjl139090 16925cf1a30Sjl139090 #define CPC_SPARC64_VI_PCR_SYS_SHIFT 1 170d1e4508aSsubhan #define CPC_SPARC64_VI_PCR_USR_SHIFT 2 17125cf1a30Sjl139090 17225cf1a30Sjl139090 #define CPC_SPARC64_VI_PCR_PICL_SHIFT 4 17325cf1a30Sjl139090 #define CPC_SPARC64_VI_PCR_PICU_SHIFT 11 174d1e4508aSsubhan #define CPC_SPARC64_VI_PCR_PIC_MASK UINT64_C(0x3F) 17525cf1a30Sjl139090 17625cf1a30Sjl139090 #define CPC_SPARC64_VI_NPIC 8 17725cf1a30Sjl139090 17825cf1a30Sjl139090 #define CPC_SPARC64_VI_PCR_ULRO_SHIFT 3 17925cf1a30Sjl139090 #define CPC_SPARC64_VI_PCR_SC_SHIFT 18 18025cf1a30Sjl139090 #define CPC_SPARC64_VI_PCR_SC_MASK UINT64_C(0x7) 18125cf1a30Sjl139090 #define CPC_SPARC64_VI_PCR_NC_SHIFT 22 18225cf1a30Sjl139090 #define CPC_SPARC64_VI_PCR_NC_MASK UINT64_C(0x7) 18325cf1a30Sjl139090 #define CPC_SPARC64_VI_PCR_OVRO_SHIFT 26 18425cf1a30Sjl139090 #define CPC_SPARC64_VI_PCR_OVF_SHIFT 32 18525cf1a30Sjl139090 #define CPC_SPARC64_VI_PCR_OVF_MASK UINT64_C(0xffff) 18625cf1a30Sjl139090 18725cf1a30Sjl139090 #define SPARC64_VI_PCR_SYS (UINT64_C(1) << CPC_SPARC64_VI_PCR_SYS_SHIFT) 18825cf1a30Sjl139090 #define SPARC64_VI_PCR_USR (UINT64_C(1) << CPC_SPARC64_VI_PCR_USR_SHIFT) 18925cf1a30Sjl139090 #define SPARC64_VI_PCR_ULRO (UINT64_C(1) << CPC_SPARC64_VI_PCR_ULRO_SHIFT) 19025cf1a30Sjl139090 #define SPARC64_VI_PCR_OVRO (UINT64_C(1) << CPC_SPARC64_VI_PCR_OVRO_SHIFT) 19125cf1a30Sjl139090 #define SPARC64_VI_PCR_OVF (CPC_SPARC64_VI_PCR_OVF_MASK << \ 19225cf1a30Sjl139090 CPC_SPARC64_VI_PCR_OVF_SHIFT) 19325cf1a30Sjl139090 19425cf1a30Sjl139090 #define SPARC64_VI_NUM_PIC_PAIRS 4 19525cf1a30Sjl139090 19625cf1a30Sjl139090 #define SPARC64_VI_PCR_SEL_PIC(pcr, picno) { \ 19725cf1a30Sjl139090 pcr &= ~((CPC_SPARC64_VI_PCR_SC_MASK \ 19825cf1a30Sjl139090 << CPC_SPARC64_VI_PCR_SC_SHIFT)); \ 19925cf1a30Sjl139090 \ 20025cf1a30Sjl139090 pcr |= (((picno) & CPC_SPARC64_VI_PCR_SC_MASK) \ 20125cf1a30Sjl139090 << CPC_SPARC64_VI_PCR_SC_SHIFT); \ 20225cf1a30Sjl139090 } 20325cf1a30Sjl139090 20425cf1a30Sjl139090 #define SPARC64_VI_PCR_SEL_EVENT(pcr, sl, su) { \ 20525cf1a30Sjl139090 pcr &= ~((CPC_SPARC64_VI_PCR_PIC_MASK \ 20625cf1a30Sjl139090 << CPC_SPARC64_VI_PCR_PICL_SHIFT) \ 20725cf1a30Sjl139090 | (CPC_SPARC64_VI_PCR_PIC_MASK \ 20825cf1a30Sjl139090 << CPC_SPARC64_VI_PCR_PICU_SHIFT)); \ 20925cf1a30Sjl139090 \ 21025cf1a30Sjl139090 pcr |= (((sl) & CPC_SPARC64_VI_PCR_PIC_MASK) \ 21125cf1a30Sjl139090 << CPC_SPARC64_VI_PCR_PICL_SHIFT); \ 21225cf1a30Sjl139090 pcr |= (((su) & CPC_SPARC64_VI_PCR_PIC_MASK) \ 21325cf1a30Sjl139090 << CPC_SPARC64_VI_PCR_PICU_SHIFT); \ 21425cf1a30Sjl139090 } 21525cf1a30Sjl139090 2165a1b32ccSsubhan #define SPARC64_VI_CHK_OVF(pcr, picno) \ 2175a1b32ccSsubhan ((pcr) & (UINT64_C(1) << (CPC_SPARC64_VI_PCR_OVF_SHIFT + picno))) 2185a1b32ccSsubhan 2195a1b32ccSsubhan #define SPARC64_VI_CLR_OVF(pcr, picno) { \ 2205a1b32ccSsubhan pcr &= ~(UINT64_C(1) << (CPC_SPARC64_VI_PCR_OVF_SHIFT + picno)); \ 2215a1b32ccSsubhan } 2225a1b32ccSsubhan 22325cf1a30Sjl139090 #define NT_END 0xFF 224*c7a079a8SJonathan Haslam #define CPC_GEN_END { NULL, NULL } 22525cf1a30Sjl139090 22625cf1a30Sjl139090 static const uint64_t allstopped = SPARC64_VI_PCR_PRIVPIC | 22725cf1a30Sjl139090 SPARC64_VI_PCR_ULRO | SPARC64_VI_PCR_OVRO; 22825cf1a30Sjl139090 2295a1b32ccSsubhan #define SPARC64_VI_EVENTS_comm_0 \ 23025cf1a30Sjl139090 {0x0, "cycle_counts"}, \ 2315a1b32ccSsubhan {0x1, "instruction_counts"} 2325a1b32ccSsubhan 2335a1b32ccSsubhan #define SPARC64_VI_EVENTS_comm_1 \ 2345a1b32ccSsubhan {0x5, "op_stv_wait"}, \ 23525cf1a30Sjl139090 {0x8, "load_store_instructions"}, \ 23625cf1a30Sjl139090 {0x9, "branch_instructions"}, \ 23725cf1a30Sjl139090 {0xa, "floating_instructions"}, \ 23825cf1a30Sjl139090 {0xb, "impdep2_instructions"}, \ 23925cf1a30Sjl139090 {0xc, "prefetch_instructions"} 24025cf1a30Sjl139090 2415a1b32ccSsubhan #define SPARC64_VI_EVENTS_comm_2 \ 2425a1b32ccSsubhan {0x1a, "active_cycle_count"} 2435a1b32ccSsubhan 24425cf1a30Sjl139090 static const struct nametable SPARC64_VI_names_l0[] = { 2455a1b32ccSsubhan SPARC64_VI_EVENTS_comm_0, 246e98fafb9Sjl139090 {0x2, "only_this_thread_active"}, 247e98fafb9Sjl139090 {0x3, "w_cse_window_empty"}, 248e98fafb9Sjl139090 {0x4, "w_op_stv_wait_nc_pend"}, 2495a1b32ccSsubhan SPARC64_VI_EVENTS_comm_1, 2505a1b32ccSsubhan {0x12, "flush_rs"}, 2515a1b32ccSsubhan {0x13, "2iid_use"}, 252caf02165Ssubhan {0x15, "toq_rsbr_phantom"}, 25325cf1a30Sjl139090 {0x16, "trap_int_vector"}, 2545a1b32ccSsubhan {0x18, "ts_by_sxmiss"}, 255e98fafb9Sjl139090 {0x18, "both_threads_active"}, 2565a1b32ccSsubhan SPARC64_VI_EVENTS_comm_2, 2575a1b32ccSsubhan {0x1d, "op_stv_wait_sxmiss"}, 258caf02165Ssubhan {0x1e, "eu_comp_wait"}, 259e98fafb9Sjl139090 {0x23, "op_l1_thrashing"}, 2605a1b32ccSsubhan {0x24, "swpf_fail_all"}, 26125cf1a30Sjl139090 {0x30, "sx_miss_wait_pf"}, 26225cf1a30Sjl139090 {0x31, "jbus_cpi_count"}, 2635a1b32ccSsubhan {0x36, "jbus_reqbus1_busy"}, 26425cf1a30Sjl139090 {NT_END, ""} 26525cf1a30Sjl139090 }; 26625cf1a30Sjl139090 26725cf1a30Sjl139090 static const struct nametable SPARC64_VI_names_u0[] = { 2685a1b32ccSsubhan SPARC64_VI_EVENTS_comm_0, 2695a1b32ccSsubhan {0x2, "instruction_flow_counts"}, 2705a1b32ccSsubhan {0x3, "iwr_empty"}, 2715a1b32ccSsubhan SPARC64_VI_EVENTS_comm_1, 2725a1b32ccSsubhan {0x12, "rs1"}, 2735a1b32ccSsubhan {0x13, "1iid_use"}, 27425cf1a30Sjl139090 {0x16, "trap_all"}, 2755a1b32ccSsubhan {0x18, "thread_switch_all"}, 276e98fafb9Sjl139090 {0x18, "only_this_thread_active"}, 2775a1b32ccSsubhan SPARC64_VI_EVENTS_comm_2, 27831632b73Swh31274 {0x1b, "rsf_pmmi"}, 2795a1b32ccSsubhan {0x1d, "act_thread_suspend"}, 2805a1b32ccSsubhan {0x1e, "cse_window_empty"}, 2815a1b32ccSsubhan {0x1f, "inh_cmit_gpr_2write"}, 282e98fafb9Sjl139090 {0x23, "if_l1_thrashing"}, 2835a1b32ccSsubhan {0x24, "swpf_success_all"}, 28425cf1a30Sjl139090 {0x30, "sx_miss_wait_dm"}, 28525cf1a30Sjl139090 {0x31, "jbus_bi_count"}, 2865a1b32ccSsubhan {0x34, "lost_softpf_pfp_full"}, 2875a1b32ccSsubhan {0x36, "jbus_reqbus0_busy"}, 28825cf1a30Sjl139090 {NT_END, ""} 28925cf1a30Sjl139090 }; 29025cf1a30Sjl139090 29125cf1a30Sjl139090 static const struct nametable SPARC64_VI_names_l1[] = { 2925a1b32ccSsubhan SPARC64_VI_EVENTS_comm_0, 293e98fafb9Sjl139090 {0x2, "single_mode_instructions"}, 294e98fafb9Sjl139090 {0x3, "w_branch_comp_wait"}, 295e98fafb9Sjl139090 {0x4, "w_op_stv_wait_sxmiss_ex"}, 2965a1b32ccSsubhan SPARC64_VI_EVENTS_comm_1, 2975a1b32ccSsubhan {0x13, "4iid_use"}, 2985a1b32ccSsubhan {0x15, "flush_rs"}, 29925cf1a30Sjl139090 {0x16, "trap_spill"}, 3005a1b32ccSsubhan {0x18, "ts_by_timer"}, 3015a1b32ccSsubhan SPARC64_VI_EVENTS_comm_2, 3025a1b32ccSsubhan {0x1b, "0iid_use"}, 3035a1b32ccSsubhan {0x1d, "op_stv_wait_nc_pend"}, 3045a1b32ccSsubhan {0x1e, "0endop"}, 30525cf1a30Sjl139090 {0x20, "write_op_uTLB"}, 30625cf1a30Sjl139090 {0x30, "sx_miss_count_pf"}, 30725cf1a30Sjl139090 {0x31, "jbus_cpd_count"}, 3085a1b32ccSsubhan {0x32, "snres_64"}, 3095a1b32ccSsubhan {0x36, "jbus_reqbus3_busy"}, 31025cf1a30Sjl139090 {NT_END, ""} 31125cf1a30Sjl139090 }; 31225cf1a30Sjl139090 31325cf1a30Sjl139090 static const struct nametable SPARC64_VI_names_u1[] = { 3145a1b32ccSsubhan SPARC64_VI_EVENTS_comm_0, 315e98fafb9Sjl139090 {0x2, "single_mode_cycle_counts"}, 316e98fafb9Sjl139090 {0x3, "w_eu_comp_wait"}, 317e98fafb9Sjl139090 {0x4, "w_op_stv_wait_sxmiss"}, 3185a1b32ccSsubhan SPARC64_VI_EVENTS_comm_1, 3195a1b32ccSsubhan {0x13, "3iid_use"}, 32025cf1a30Sjl139090 {0x16, "trap_int_level"}, 3215a1b32ccSsubhan {0x18, "ts_by_data_arrive"}, 322e98fafb9Sjl139090 {0x18, "both_threads_empty"}, 3235a1b32ccSsubhan SPARC64_VI_EVENTS_comm_2, 3245a1b32ccSsubhan {0x1b, "op_stv_wait_nc_pend"}, 3255a1b32ccSsubhan {0x1d, "op_stv_wait_sxmiss_ex"}, 326caf02165Ssubhan {0x1e, "branch_comp_wait"}, 32725cf1a30Sjl139090 {0x20, "write_if_uTLB"}, 32825cf1a30Sjl139090 {0x30, "sx_miss_count_dm"}, 32925cf1a30Sjl139090 {0x31, "jbus_cpb_count"}, 3305a1b32ccSsubhan {0x32, "snres_256"}, 3315a1b32ccSsubhan {0x34, "lost_softpf_by_abort"}, 3325a1b32ccSsubhan {0x36, "jbus_reqbus2_busy"}, 33325cf1a30Sjl139090 {NT_END, ""} 33425cf1a30Sjl139090 }; 33525cf1a30Sjl139090 33625cf1a30Sjl139090 static const struct nametable SPARC64_VI_names_l2[] = { 3375a1b32ccSsubhan SPARC64_VI_EVENTS_comm_0, 338e98fafb9Sjl139090 {0x2, "d_move_wait"}, 339e98fafb9Sjl139090 {0x3, "w_op_stv_wait"}, 340e98fafb9Sjl139090 {0x4, "w_fl_comp_wait"}, 3415a1b32ccSsubhan SPARC64_VI_EVENTS_comm_1, 3425a1b32ccSsubhan {0x13, "sync_intlk"}, 34325cf1a30Sjl139090 {0x16, "trap_trap_inst"}, 3445a1b32ccSsubhan {0x18, "ts_by_if"}, 3455a1b32ccSsubhan SPARC64_VI_EVENTS_comm_2, 3465a1b32ccSsubhan {0x1e, "fl_comp_wait"}, 34725cf1a30Sjl139090 {0x20, "op_r_iu_req_mi_go"}, 34825cf1a30Sjl139090 {0x30, "sx_read_count_pf"}, 349caf02165Ssubhan {0x31, "jbus_odrbus_busy"}, 3505a1b32ccSsubhan {0x33, "sx_miss_count_dm_if"}, 3515a1b32ccSsubhan {0x36, "jbus_odrbus1_busy"}, 35225cf1a30Sjl139090 {NT_END, ""} 35325cf1a30Sjl139090 }; 35425cf1a30Sjl139090 35525cf1a30Sjl139090 static const struct nametable SPARC64_VI_names_u2[] = { 3565a1b32ccSsubhan SPARC64_VI_EVENTS_comm_0, 3575a1b32ccSsubhan {0x2, "instruction_flow_counts"}, 3585a1b32ccSsubhan {0x3, "iwr_empty"}, 3595a1b32ccSsubhan SPARC64_VI_EVENTS_comm_1, 36025cf1a30Sjl139090 {0x16, "trap_fill"}, 3615a1b32ccSsubhan {0x18, "ts_by_intr"}, 3625a1b32ccSsubhan SPARC64_VI_EVENTS_comm_2, 3635a1b32ccSsubhan {0x1b, "flush_rs"}, 3645a1b32ccSsubhan {0x1d, "cse_window_empty_sp_full"}, 3655a1b32ccSsubhan {0x1e, "op_stv_wait_ex"}, 3665a1b32ccSsubhan {0x1f, "3endop"}, 36725cf1a30Sjl139090 {0x20, "if_r_iu_req_mi_go"}, 3685a1b32ccSsubhan {0x24, "swpf_lbs_hit"}, 36925cf1a30Sjl139090 {0x30, "sx_read_count_dm"}, 3705a1b32ccSsubhan {0x31, "jbus_reqbus_busy"}, 3715a1b32ccSsubhan {0x33, "sx_btc_count"}, 3725a1b32ccSsubhan {0x36, "jbus_odrbus0_busy"}, 37325cf1a30Sjl139090 {NT_END, ""} 37425cf1a30Sjl139090 }; 37525cf1a30Sjl139090 37625cf1a30Sjl139090 static const struct nametable SPARC64_VI_names_l3[] = { 3775a1b32ccSsubhan SPARC64_VI_EVENTS_comm_0, 378e98fafb9Sjl139090 {0x2, "xma_inst"}, 379e98fafb9Sjl139090 {0x3, "w_0endop"}, 380e98fafb9Sjl139090 {0x4, "w_op_stv_wait_ex"}, 3815a1b32ccSsubhan SPARC64_VI_EVENTS_comm_1, 38225cf1a30Sjl139090 {0x16, "trap_DMMU_miss"}, 3835a1b32ccSsubhan {0x18, "ts_by_suspend"}, 3845a1b32ccSsubhan {0x19, "ts_by_other"}, 3855a1b32ccSsubhan SPARC64_VI_EVENTS_comm_2, 3865a1b32ccSsubhan {0x1b, "decall_intlk"}, 3875a1b32ccSsubhan {0x1e, "2endop"}, 3885a1b32ccSsubhan {0x1f, "op_stv_wait_sxmiss"}, 38925cf1a30Sjl139090 {0x20, "op_wait_all"}, 39025cf1a30Sjl139090 {0x30, "dvp_count_pf"}, 3915a1b32ccSsubhan {0x33, "sx_miss_count_dm_opex"}, 3925a1b32ccSsubhan {0x36, "jbus_odrbus3_busy"}, 39325cf1a30Sjl139090 {NT_END, ""} 39425cf1a30Sjl139090 }; 39525cf1a30Sjl139090 39625cf1a30Sjl139090 static const struct nametable SPARC64_VI_names_u3[] = { 3975a1b32ccSsubhan SPARC64_VI_EVENTS_comm_0, 398e98fafb9Sjl139090 {0x2, "cse_priority_wait"}, 399e98fafb9Sjl139090 {0x3, "w_d_move"}, 400e98fafb9Sjl139090 {0x4, "w_cse_window_empty_sp_full"}, 4015a1b32ccSsubhan SPARC64_VI_EVENTS_comm_1, 4025a1b32ccSsubhan {0x13, "regwin_intlk"}, 4035a1b32ccSsubhan {0x15, "rs1"}, 40425cf1a30Sjl139090 {0x16, "trap_IMMU_miss"}, 4055a1b32ccSsubhan SPARC64_VI_EVENTS_comm_2, 406e98fafb9Sjl139090 {0x1d, "both_threads_suspended"}, 4075a1b32ccSsubhan {0x1e, "1endop"}, 4085a1b32ccSsubhan {0x1f, "op_stv_wait_sxmiss_ex"}, 40925cf1a30Sjl139090 {0x20, "if_wait_all"}, 41025cf1a30Sjl139090 {0x30, "dvp_count_dm"}, 4115a1b32ccSsubhan {0x33, "sx_miss_count_dm_opsh"}, 4125a1b32ccSsubhan {0x36, "jbus_odrbus2_busy"}, 41325cf1a30Sjl139090 {NT_END, ""} 41425cf1a30Sjl139090 }; 41525cf1a30Sjl139090 4165a1b32ccSsubhan #undef SPARC64_VI_EVENTS_comm_0 4175a1b32ccSsubhan #undef SPARC64_VI_EVENTS_comm_1 4185a1b32ccSsubhan #undef SPARC64_VI_EVENTS_comm_2 41925cf1a30Sjl139090 42025cf1a30Sjl139090 static const struct nametable *SPARC64_VI_names[CPC_SPARC64_VI_NPIC] = { 42125cf1a30Sjl139090 SPARC64_VI_names_l0, 42225cf1a30Sjl139090 SPARC64_VI_names_u0, 42325cf1a30Sjl139090 SPARC64_VI_names_l1, 42425cf1a30Sjl139090 SPARC64_VI_names_u1, 42525cf1a30Sjl139090 SPARC64_VI_names_l2, 42625cf1a30Sjl139090 SPARC64_VI_names_u2, 42725cf1a30Sjl139090 SPARC64_VI_names_l3, 42825cf1a30Sjl139090 SPARC64_VI_names_u3 42925cf1a30Sjl139090 }; 43025cf1a30Sjl139090 43125cf1a30Sjl139090 opl_pcbe_config_t nullpic[CPC_SPARC64_VI_NPIC] = { 43225cf1a30Sjl139090 {0, 0x3f, 0, 0}, 43325cf1a30Sjl139090 {1, 0x3f, 0, 0}, 43425cf1a30Sjl139090 {2, 0x3f, 0, 0}, 43525cf1a30Sjl139090 {3, 0x3f, 0, 0}, 43625cf1a30Sjl139090 {4, 0x3f, 0, 0}, 43725cf1a30Sjl139090 {5, 0x3f, 0, 0}, 43825cf1a30Sjl139090 {6, 0x3f, 0, 0}, 43925cf1a30Sjl139090 {7, 0x3f, 0, 0} 44025cf1a30Sjl139090 }; 44125cf1a30Sjl139090 442*c7a079a8SJonathan Haslam #define SPARC64_VI_GENERIC_EVENTS_comm \ 443*c7a079a8SJonathan Haslam { "PAPI_tot_cyc", "cycle_counts" }, \ 444*c7a079a8SJonathan Haslam { "PAPI_tot_ins", "instruction_counts" }, \ 445*c7a079a8SJonathan Haslam { "PAPI_br_tkn", "branch_instructions" }, \ 446*c7a079a8SJonathan Haslam { "PAPI_fp_ops", "floating_instructions" }, \ 447*c7a079a8SJonathan Haslam { "PAPI_fma_ins", "impdep2_instructions" } 448*c7a079a8SJonathan Haslam 449*c7a079a8SJonathan Haslam static const opl_generic_event_t SPARC64_VI_generic_names_l0[] = { 450*c7a079a8SJonathan Haslam SPARC64_VI_GENERIC_EVENTS_comm, 451*c7a079a8SJonathan Haslam CPC_GEN_END 452*c7a079a8SJonathan Haslam }; 453*c7a079a8SJonathan Haslam 454*c7a079a8SJonathan Haslam static const opl_generic_event_t SPARC64_VI_generic_names_u0[] = { 455*c7a079a8SJonathan Haslam SPARC64_VI_GENERIC_EVENTS_comm, 456*c7a079a8SJonathan Haslam CPC_GEN_END 457*c7a079a8SJonathan Haslam }; 458*c7a079a8SJonathan Haslam 459*c7a079a8SJonathan Haslam static const opl_generic_event_t SPARC64_VI_generic_names_l1[] = { 460*c7a079a8SJonathan Haslam SPARC64_VI_GENERIC_EVENTS_comm, 461*c7a079a8SJonathan Haslam CPC_GEN_END 462*c7a079a8SJonathan Haslam }; 463*c7a079a8SJonathan Haslam 464*c7a079a8SJonathan Haslam static const opl_generic_event_t SPARC64_VI_generic_names_u1[] = { 465*c7a079a8SJonathan Haslam SPARC64_VI_GENERIC_EVENTS_comm, 466*c7a079a8SJonathan Haslam CPC_GEN_END 467*c7a079a8SJonathan Haslam }; 468*c7a079a8SJonathan Haslam 469*c7a079a8SJonathan Haslam static const opl_generic_event_t SPARC64_VI_generic_names_l2[] = { 470*c7a079a8SJonathan Haslam SPARC64_VI_GENERIC_EVENTS_comm, 471*c7a079a8SJonathan Haslam { "PAPI_l1_dcm", "op_r_iu_req_mi_go" }, 472*c7a079a8SJonathan Haslam CPC_GEN_END 473*c7a079a8SJonathan Haslam }; 474*c7a079a8SJonathan Haslam 475*c7a079a8SJonathan Haslam static const opl_generic_event_t SPARC64_VI_generic_names_u2[] = { 476*c7a079a8SJonathan Haslam SPARC64_VI_GENERIC_EVENTS_comm, 477*c7a079a8SJonathan Haslam { "PAPI_l1_icm", "if_r_iu_req_mi_go" }, 478*c7a079a8SJonathan Haslam CPC_GEN_END 479*c7a079a8SJonathan Haslam }; 480*c7a079a8SJonathan Haslam 481*c7a079a8SJonathan Haslam static const opl_generic_event_t SPARC64_VI_generic_names_l3[] = { 482*c7a079a8SJonathan Haslam SPARC64_VI_GENERIC_EVENTS_comm, 483*c7a079a8SJonathan Haslam { "PAPI_tlb_dm", "trap_DMMU_miss" }, 484*c7a079a8SJonathan Haslam CPC_GEN_END 485*c7a079a8SJonathan Haslam }; 486*c7a079a8SJonathan Haslam 487*c7a079a8SJonathan Haslam static const opl_generic_event_t SPARC64_VI_generic_names_u3[] = { 488*c7a079a8SJonathan Haslam SPARC64_VI_GENERIC_EVENTS_comm, 489*c7a079a8SJonathan Haslam { "PAPI_tlb_im", "trap_IMMU_miss" }, 490*c7a079a8SJonathan Haslam CPC_GEN_END 491*c7a079a8SJonathan Haslam }; 492*c7a079a8SJonathan Haslam 493*c7a079a8SJonathan Haslam static const opl_generic_event_t 494*c7a079a8SJonathan Haslam *SPARC64_VI_generic_names[CPC_SPARC64_VI_NPIC] = { 495*c7a079a8SJonathan Haslam SPARC64_VI_generic_names_l0, 496*c7a079a8SJonathan Haslam SPARC64_VI_generic_names_u0, 497*c7a079a8SJonathan Haslam SPARC64_VI_generic_names_l1, 498*c7a079a8SJonathan Haslam SPARC64_VI_generic_names_u1, 499*c7a079a8SJonathan Haslam SPARC64_VI_generic_names_l2, 500*c7a079a8SJonathan Haslam SPARC64_VI_generic_names_u2, 501*c7a079a8SJonathan Haslam SPARC64_VI_generic_names_l3, 502*c7a079a8SJonathan Haslam SPARC64_VI_generic_names_u3 503*c7a079a8SJonathan Haslam }; 504*c7a079a8SJonathan Haslam 50525cf1a30Sjl139090 static const struct nametable **events; 506*c7a079a8SJonathan Haslam static const opl_generic_event_t **generic_events; 50725cf1a30Sjl139090 static const char *opl_impl_name; 50825cf1a30Sjl139090 static const char *opl_cpuref; 50925cf1a30Sjl139090 static char *pic_events[CPC_SPARC64_VI_NPIC]; 51025cf1a30Sjl139090 511e98fafb9Sjl139090 static const char *sp_6_ref = "See the \"SPARC64 VI extensions\" and " 512e98fafb9Sjl139090 "\"SPARC64 VII extensions\" for descriptions of these events."; 51325cf1a30Sjl139090 51425cf1a30Sjl139090 static int 51525cf1a30Sjl139090 opl_pcbe_init(void) 51625cf1a30Sjl139090 { 51725cf1a30Sjl139090 const struct nametable *n; 518*c7a079a8SJonathan Haslam const opl_generic_event_t *gevp; 51925cf1a30Sjl139090 int i; 52025cf1a30Sjl139090 size_t size; 52125cf1a30Sjl139090 52225cf1a30Sjl139090 /* 52325cf1a30Sjl139090 * Discover type of CPU 52425cf1a30Sjl139090 * 52525cf1a30Sjl139090 * Point nametable to that CPU's table 52625cf1a30Sjl139090 */ 52725cf1a30Sjl139090 switch (ULTRA_VER_IMPL(ultra_getver())) { 52825cf1a30Sjl139090 case OLYMPUS_C_IMPL: 529e98fafb9Sjl139090 case JUPITER_IMPL: 53025cf1a30Sjl139090 events = SPARC64_VI_names; 531*c7a079a8SJonathan Haslam generic_events = SPARC64_VI_generic_names; 532e98fafb9Sjl139090 opl_impl_name = "SPARC64 VI & VII"; 53325cf1a30Sjl139090 opl_cpuref = sp_6_ref; 53425cf1a30Sjl139090 break; 53525cf1a30Sjl139090 default: 53625cf1a30Sjl139090 return (-1); 53725cf1a30Sjl139090 } 53825cf1a30Sjl139090 53925cf1a30Sjl139090 /* 54025cf1a30Sjl139090 * Initialize the list of events for each PIC. 54125cf1a30Sjl139090 * Do two passes: one to compute the size necessary and another 54225cf1a30Sjl139090 * to copy the strings. Need room for event, comma, and NULL terminator. 54325cf1a30Sjl139090 */ 54425cf1a30Sjl139090 for (i = 0; i < CPC_SPARC64_VI_NPIC; i++) { 54525cf1a30Sjl139090 size = 0; 54625cf1a30Sjl139090 for (n = events[i]; n->bits != NT_END; n++) 54725cf1a30Sjl139090 size += strlen(n->name) + 1; 548*c7a079a8SJonathan Haslam for (gevp = generic_events[i]; gevp->name != NULL; gevp++) 549*c7a079a8SJonathan Haslam size += strlen(gevp->name) + 1; 55025cf1a30Sjl139090 pic_events[i] = kmem_alloc(size + 1, KM_SLEEP); 55125cf1a30Sjl139090 *pic_events[i] = '\0'; 55225cf1a30Sjl139090 for (n = events[i]; n->bits != NT_END; n++) { 55325cf1a30Sjl139090 (void) strcat(pic_events[i], n->name); 55425cf1a30Sjl139090 (void) strcat(pic_events[i], ","); 55525cf1a30Sjl139090 } 556*c7a079a8SJonathan Haslam for (gevp = generic_events[i]; gevp->name != NULL; gevp++) { 557*c7a079a8SJonathan Haslam (void) strcat(pic_events[i], gevp->name); 558*c7a079a8SJonathan Haslam (void) strcat(pic_events[i], ","); 559*c7a079a8SJonathan Haslam } 560*c7a079a8SJonathan Haslam 56125cf1a30Sjl139090 /* 56225cf1a30Sjl139090 * Remove trailing comma. 56325cf1a30Sjl139090 */ 56425cf1a30Sjl139090 pic_events[i][size - 1] = '\0'; 56525cf1a30Sjl139090 } 56625cf1a30Sjl139090 56725cf1a30Sjl139090 return (0); 56825cf1a30Sjl139090 } 56925cf1a30Sjl139090 57025cf1a30Sjl139090 static uint_t 57125cf1a30Sjl139090 opl_pcbe_ncounters(void) 57225cf1a30Sjl139090 { 57325cf1a30Sjl139090 return (CPC_SPARC64_VI_NPIC); 57425cf1a30Sjl139090 } 57525cf1a30Sjl139090 57625cf1a30Sjl139090 static const char * 57725cf1a30Sjl139090 opl_pcbe_impl_name(void) 57825cf1a30Sjl139090 { 57925cf1a30Sjl139090 return (opl_impl_name); 58025cf1a30Sjl139090 } 58125cf1a30Sjl139090 58225cf1a30Sjl139090 static const char * 58325cf1a30Sjl139090 opl_pcbe_cpuref(void) 58425cf1a30Sjl139090 { 58525cf1a30Sjl139090 return (opl_cpuref); 58625cf1a30Sjl139090 } 58725cf1a30Sjl139090 58825cf1a30Sjl139090 static char * 58925cf1a30Sjl139090 opl_pcbe_list_events(uint_t picnum) 59025cf1a30Sjl139090 { 59125cf1a30Sjl139090 ASSERT(picnum >= 0 && picnum < cpc_ncounters); 59225cf1a30Sjl139090 59325cf1a30Sjl139090 return (pic_events[picnum]); 59425cf1a30Sjl139090 } 59525cf1a30Sjl139090 59625cf1a30Sjl139090 static char * 59725cf1a30Sjl139090 opl_pcbe_list_attrs(void) 59825cf1a30Sjl139090 { 59925cf1a30Sjl139090 return (""); 60025cf1a30Sjl139090 } 60125cf1a30Sjl139090 602*c7a079a8SJonathan Haslam static const opl_generic_event_t * 603*c7a079a8SJonathan Haslam find_generic_event(int regno, char *name) 604*c7a079a8SJonathan Haslam { 605*c7a079a8SJonathan Haslam const opl_generic_event_t *gevp; 606*c7a079a8SJonathan Haslam 607*c7a079a8SJonathan Haslam for (gevp = generic_events[regno]; gevp->name != NULL; gevp++) 608*c7a079a8SJonathan Haslam if (strcmp(name, gevp->name) == 0) 609*c7a079a8SJonathan Haslam return (gevp); 610*c7a079a8SJonathan Haslam 611*c7a079a8SJonathan Haslam return (NULL); 612*c7a079a8SJonathan Haslam } 613*c7a079a8SJonathan Haslam 61425cf1a30Sjl139090 static const struct nametable * 61525cf1a30Sjl139090 find_event(int regno, char *name) 61625cf1a30Sjl139090 { 61725cf1a30Sjl139090 const struct nametable *n; 61825cf1a30Sjl139090 61925cf1a30Sjl139090 n = events[regno]; 62025cf1a30Sjl139090 62125cf1a30Sjl139090 for (; n->bits != NT_END; n++) 62225cf1a30Sjl139090 if (strcmp(name, n->name) == 0) 62325cf1a30Sjl139090 return (n); 62425cf1a30Sjl139090 62525cf1a30Sjl139090 return (NULL); 62625cf1a30Sjl139090 } 62725cf1a30Sjl139090 62825cf1a30Sjl139090 static uint64_t 62925cf1a30Sjl139090 opl_pcbe_event_coverage(char *event) 63025cf1a30Sjl139090 { 63125cf1a30Sjl139090 uint64_t bitmap = 0; 63225cf1a30Sjl139090 63325cf1a30Sjl139090 int i; 63425cf1a30Sjl139090 for (i = 0; i < CPC_SPARC64_VI_NPIC; i++) { 635*c7a079a8SJonathan Haslam if ((find_event(i, event) != NULL) || 636*c7a079a8SJonathan Haslam (find_generic_event(i, event) != NULL)) 63725cf1a30Sjl139090 bitmap |= (1 << i); 63825cf1a30Sjl139090 } 63925cf1a30Sjl139090 64025cf1a30Sjl139090 return (bitmap); 64125cf1a30Sjl139090 } 64225cf1a30Sjl139090 64325cf1a30Sjl139090 /* 644d1e4508aSsubhan * Check if counter overflow and clear it. 64525cf1a30Sjl139090 */ 64625cf1a30Sjl139090 static uint64_t 64725cf1a30Sjl139090 opl_pcbe_overflow_bitmap(void) 64825cf1a30Sjl139090 { 6495a1b32ccSsubhan uint64_t pcr; 65025cf1a30Sjl139090 65125cf1a30Sjl139090 pcr = ultra_getpcr(); 652d1e4508aSsubhan DTRACE_PROBE1(sparc64__getpcr, uint64_t, pcr); 653d1e4508aSsubhan 6545a1b32ccSsubhan return ((pcr & SPARC64_VI_PCR_OVF) >> CPC_SPARC64_VI_PCR_OVF_SHIFT); 65525cf1a30Sjl139090 } 65625cf1a30Sjl139090 65725cf1a30Sjl139090 /*ARGSUSED*/ 65825cf1a30Sjl139090 static int 65925cf1a30Sjl139090 opl_pcbe_configure(uint_t picnum, char *event, uint64_t preset, uint32_t flags, 66025cf1a30Sjl139090 uint_t nattrs, kcpc_attr_t *attrs, void **data, void *token) 66125cf1a30Sjl139090 { 66225cf1a30Sjl139090 opl_pcbe_config_t *conf; 66325cf1a30Sjl139090 const struct nametable *n; 664*c7a079a8SJonathan Haslam const opl_generic_event_t *gevp; 66525cf1a30Sjl139090 opl_pcbe_config_t *other_config; 66625cf1a30Sjl139090 66725cf1a30Sjl139090 /* 66825cf1a30Sjl139090 * If we've been handed an existing configuration, we need only preset 66925cf1a30Sjl139090 * the counter value. 67025cf1a30Sjl139090 */ 67125cf1a30Sjl139090 if (*data != NULL) { 67225cf1a30Sjl139090 conf = *data; 67325cf1a30Sjl139090 conf->opl_pic = (uint32_t)preset; 67425cf1a30Sjl139090 return (0); 67525cf1a30Sjl139090 } 67625cf1a30Sjl139090 67725cf1a30Sjl139090 if (picnum < 0 || picnum >= CPC_SPARC64_VI_NPIC) 67825cf1a30Sjl139090 return (CPC_INVALID_PICNUM); 67925cf1a30Sjl139090 68025cf1a30Sjl139090 if (nattrs != 0) 68125cf1a30Sjl139090 return (CPC_INVALID_ATTRIBUTE); 68225cf1a30Sjl139090 68325cf1a30Sjl139090 /* 68425cf1a30Sjl139090 * Find other requests that will be programmed with this one, and ensure 68525cf1a30Sjl139090 * the flags don't conflict. 68625cf1a30Sjl139090 */ 68725cf1a30Sjl139090 if (((other_config = kcpc_next_config(token, NULL, NULL)) != NULL) && 68825cf1a30Sjl139090 (other_config->opl_flags != flags)) 68925cf1a30Sjl139090 return (CPC_CONFLICTING_REQS); 69025cf1a30Sjl139090 691*c7a079a8SJonathan Haslam if ((n = find_event(picnum, event)) == NULL) { 692*c7a079a8SJonathan Haslam if ((gevp = find_generic_event(picnum, event)) != NULL) { 693*c7a079a8SJonathan Haslam n = find_event(picnum, gevp->event); 694*c7a079a8SJonathan Haslam ASSERT(n != NULL); 695*c7a079a8SJonathan Haslam } else { 69625cf1a30Sjl139090 return (CPC_INVALID_EVENT); 697*c7a079a8SJonathan Haslam } 698*c7a079a8SJonathan Haslam } 69925cf1a30Sjl139090 70025cf1a30Sjl139090 conf = kmem_alloc(sizeof (opl_pcbe_config_t), KM_SLEEP); 70125cf1a30Sjl139090 70225cf1a30Sjl139090 conf->opl_picno = picnum; 70325cf1a30Sjl139090 conf->opl_bits = (uint32_t)n->bits; 70425cf1a30Sjl139090 conf->opl_flags = flags; 70525cf1a30Sjl139090 conf->opl_pic = (uint32_t)preset; 70625cf1a30Sjl139090 70725cf1a30Sjl139090 *data = conf; 70825cf1a30Sjl139090 return (0); 70925cf1a30Sjl139090 } 71025cf1a30Sjl139090 71125cf1a30Sjl139090 static void 71225cf1a30Sjl139090 opl_pcbe_program(void *token) 71325cf1a30Sjl139090 { 71425cf1a30Sjl139090 opl_pcbe_config_t *pic[CPC_SPARC64_VI_NPIC]; 71525cf1a30Sjl139090 opl_pcbe_config_t *firstconfig; 71625cf1a30Sjl139090 opl_pcbe_config_t *tmp; 71725cf1a30Sjl139090 uint64_t pcr; 71825cf1a30Sjl139090 uint64_t curpic; 71925cf1a30Sjl139090 uint8_t bitmap = 0; /* for used pic config */ 72025cf1a30Sjl139090 int i; 72125cf1a30Sjl139090 opl_pcbe_config_t dummypic[CPC_SPARC64_VI_NPIC]; 72225cf1a30Sjl139090 72325cf1a30Sjl139090 /* Get next pic config */ 72425cf1a30Sjl139090 firstconfig = tmp = kcpc_next_config(token, NULL, NULL); 72525cf1a30Sjl139090 72625cf1a30Sjl139090 while (tmp != NULL) { 72725cf1a30Sjl139090 ASSERT(tmp->opl_picno < CPC_SPARC64_VI_NPIC); 72825cf1a30Sjl139090 ASSERT(firstconfig->opl_flags == tmp->opl_flags); 72925cf1a30Sjl139090 pic[tmp->opl_picno] = tmp; 73025cf1a30Sjl139090 bitmap |= (uint8_t)(1 << tmp->opl_picno); 73125cf1a30Sjl139090 tmp = kcpc_next_config(token, tmp, NULL); 73225cf1a30Sjl139090 } 73325cf1a30Sjl139090 if (bitmap == 0) 73425cf1a30Sjl139090 panic("opl_pcbe: token %p has no configs", token); 73525cf1a30Sjl139090 73625cf1a30Sjl139090 /* Fill in unused pic config */ 73725cf1a30Sjl139090 for (i = 0; i < CPC_SPARC64_VI_NPIC; i++) { 73825cf1a30Sjl139090 if (bitmap & (1 << i)) 73925cf1a30Sjl139090 continue; 74025cf1a30Sjl139090 74125cf1a30Sjl139090 dummypic[i] = nullpic[i]; 74225cf1a30Sjl139090 dummypic[i].opl_flags = firstconfig->opl_flags; 743d1e4508aSsubhan pic[i] = &dummypic[i]; 74425cf1a30Sjl139090 } 74525cf1a30Sjl139090 74625cf1a30Sjl139090 /* 74725cf1a30Sjl139090 * For each counter pair, initialize event settings and 74825cf1a30Sjl139090 * counter values. 74925cf1a30Sjl139090 */ 75025cf1a30Sjl139090 ultra_setpcr(allstopped); 75125cf1a30Sjl139090 pcr = allstopped; 75225cf1a30Sjl139090 pcr &= ~SPARC64_VI_PCR_ULRO; 75325cf1a30Sjl139090 for (i = 0; i < SPARC64_VI_NUM_PIC_PAIRS; i++) { 75425cf1a30Sjl139090 SPARC64_VI_PCR_SEL_PIC(pcr, i); 75525cf1a30Sjl139090 SPARC64_VI_PCR_SEL_EVENT(pcr, pic[i*2]->opl_bits, 75625cf1a30Sjl139090 pic[i*2 + 1]->opl_bits); 75725cf1a30Sjl139090 75825cf1a30Sjl139090 ultra_setpcr(pcr); 75925cf1a30Sjl139090 curpic = (uint64_t)(pic[i*2]->opl_pic | 76025cf1a30Sjl139090 ((uint64_t)pic[i*2 + 1]->opl_pic << 32)); 76125cf1a30Sjl139090 ultra_setpic(curpic); 76225cf1a30Sjl139090 } 76325cf1a30Sjl139090 76425cf1a30Sjl139090 /* 76525cf1a30Sjl139090 * For each counter pair, enable the trace flags to start 76625cf1a30Sjl139090 * counting. Re-read the counters to sample the counter value now 76725cf1a30Sjl139090 * and use that as the baseline for future samples. 76825cf1a30Sjl139090 */ 76925cf1a30Sjl139090 770d1e4508aSsubhan /* Get PCR */ 77125cf1a30Sjl139090 pcr = ultra_getpcr(); 7725a1b32ccSsubhan pcr |= SPARC64_VI_PCR_ULRO; 7735a1b32ccSsubhan pcr &= ~(SPARC64_VI_PCR_OVRO | SPARC64_VI_PCR_OVF); 774d1e4508aSsubhan 77525cf1a30Sjl139090 if (pic[0]->opl_flags & CPC_COUNT_USER) 77625cf1a30Sjl139090 pcr |= SPARC64_VI_PCR_USR; 77725cf1a30Sjl139090 if (pic[0]->opl_flags & CPC_COUNT_SYSTEM) 77825cf1a30Sjl139090 pcr |= SPARC64_VI_PCR_SYS; 77925cf1a30Sjl139090 78025cf1a30Sjl139090 /* Set counter values */ 781d1e4508aSsubhan 78225cf1a30Sjl139090 for (i = 0; i < SPARC64_VI_NUM_PIC_PAIRS; i++) { 78325cf1a30Sjl139090 SPARC64_VI_PCR_SEL_PIC(pcr, i); 78425cf1a30Sjl139090 SPARC64_VI_PCR_SEL_EVENT(pcr, pic[i*2]->opl_bits, 78525cf1a30Sjl139090 pic[i*2 + 1]->opl_bits); 78625cf1a30Sjl139090 78725cf1a30Sjl139090 ultra_setpcr(pcr); 788d1e4508aSsubhan DTRACE_PROBE1(sparc64__setpcr, uint64_t, pcr); 789d1e4508aSsubhan 79025cf1a30Sjl139090 curpic = ultra_getpic(); 791d1e4508aSsubhan DTRACE_PROBE1(sparc64__newpic, uint64_t, curpic); 79225cf1a30Sjl139090 pic[i*2]->opl_pic = (uint32_t)(curpic & PIC_MASK); 79325cf1a30Sjl139090 pic[i*2 + 1]->opl_pic = (uint32_t)(curpic >> 32); 79425cf1a30Sjl139090 } 7955a1b32ccSsubhan pcr |= SPARC64_VI_PCR_OVRO; 7965a1b32ccSsubhan ultra_setpcr(pcr); 79725cf1a30Sjl139090 } 79825cf1a30Sjl139090 79925cf1a30Sjl139090 static void 80025cf1a30Sjl139090 opl_pcbe_allstop(void) 80125cf1a30Sjl139090 { 80225cf1a30Sjl139090 ultra_setpcr(allstopped); 80325cf1a30Sjl139090 } 80425cf1a30Sjl139090 80525cf1a30Sjl139090 80625cf1a30Sjl139090 static void 80725cf1a30Sjl139090 opl_pcbe_sample(void *token) 80825cf1a30Sjl139090 { 80925cf1a30Sjl139090 uint64_t curpic; 81025cf1a30Sjl139090 uint64_t pcr; 8115a1b32ccSsubhan uint64_t overflow; 81225cf1a30Sjl139090 int64_t diff; 81325cf1a30Sjl139090 uint64_t *pic_data[CPC_SPARC64_VI_NPIC]; 81425cf1a30Sjl139090 uint64_t *dtmp; 81525cf1a30Sjl139090 opl_pcbe_config_t *pic[CPC_SPARC64_VI_NPIC]; 81625cf1a30Sjl139090 opl_pcbe_config_t *ctmp; 81725cf1a30Sjl139090 opl_pcbe_config_t *firstconfig; 81825cf1a30Sjl139090 uint8_t bitmap = 0; /* for used pic config */ 81925cf1a30Sjl139090 int i; 82025cf1a30Sjl139090 opl_pcbe_config_t dummypic[CPC_SPARC64_VI_NPIC]; 82125cf1a30Sjl139090 uint64_t dummypic_data[CPC_SPARC64_VI_NPIC]; 82225cf1a30Sjl139090 82325cf1a30Sjl139090 /* Get next pic config */ 82425cf1a30Sjl139090 firstconfig = ctmp = kcpc_next_config(token, NULL, &dtmp); 82525cf1a30Sjl139090 82625cf1a30Sjl139090 while (ctmp != NULL) { 82725cf1a30Sjl139090 ASSERT(ctmp->opl_picno < CPC_SPARC64_VI_NPIC); 82825cf1a30Sjl139090 ASSERT(firstconfig->opl_flags == ctmp->opl_flags); 82925cf1a30Sjl139090 pic[ctmp->opl_picno] = ctmp; 83025cf1a30Sjl139090 pic_data[ctmp->opl_picno] = dtmp; 83125cf1a30Sjl139090 bitmap |= (uint8_t)(1 << ctmp->opl_picno); 83225cf1a30Sjl139090 ctmp = kcpc_next_config(token, ctmp, &dtmp); 83325cf1a30Sjl139090 } 83425cf1a30Sjl139090 if (bitmap == 0) 83525cf1a30Sjl139090 panic("opl_pcbe: token %p has no configs", token); 83625cf1a30Sjl139090 83725cf1a30Sjl139090 /* Fill in unuse pic config */ 83825cf1a30Sjl139090 for (i = 0; i < CPC_SPARC64_VI_NPIC; i++) { 83925cf1a30Sjl139090 if (bitmap & (1 << i)) 84025cf1a30Sjl139090 continue; 84125cf1a30Sjl139090 84225cf1a30Sjl139090 dummypic[i] = nullpic[i]; 84325cf1a30Sjl139090 dummypic[i].opl_flags = firstconfig->opl_flags; 84425cf1a30Sjl139090 pic[i] = &dummypic[i]; 84525cf1a30Sjl139090 84625cf1a30Sjl139090 dummypic_data[i] = 0; 84725cf1a30Sjl139090 pic_data[i] = &dummypic_data[i]; 84825cf1a30Sjl139090 } 84925cf1a30Sjl139090 85025cf1a30Sjl139090 pcr = ultra_getpcr(); 8515a1b32ccSsubhan pcr &= ~SPARC64_VI_PCR_OVRO; 8525a1b32ccSsubhan pcr |= SPARC64_VI_PCR_ULRO; 85325cf1a30Sjl139090 85425cf1a30Sjl139090 for (i = 0; i < SPARC64_VI_NUM_PIC_PAIRS; i++) { 85525cf1a30Sjl139090 SPARC64_VI_PCR_SEL_PIC(pcr, i); 85625cf1a30Sjl139090 SPARC64_VI_PCR_SEL_EVENT(pcr, pic[i*2]->opl_bits, 85725cf1a30Sjl139090 pic[i*2 + 1]->opl_bits); 85825cf1a30Sjl139090 85925cf1a30Sjl139090 ultra_setpcr(pcr); 860d1e4508aSsubhan 86125cf1a30Sjl139090 curpic = ultra_getpic(); 862d1e4508aSsubhan DTRACE_PROBE1(sparc64__getpic, unit64_t, curpic); 86325cf1a30Sjl139090 8645a1b32ccSsubhan diff = (curpic & PIC_MASK) - (uint64_t)pic[i*2]->opl_pic; 8655a1b32ccSsubhan overflow = SPARC64_VI_CHK_OVF(pcr, i*2); 8665a1b32ccSsubhan if (overflow || (diff < 0)) { 8675a1b32ccSsubhan SPARC64_VI_CLR_OVF(pcr, i*2); 8685a1b32ccSsubhan ultra_setpcr(pcr); 86925cf1a30Sjl139090 diff += (1ll << 32); 8705a1b32ccSsubhan } 87125cf1a30Sjl139090 *pic_data[i*2] += diff; 87225cf1a30Sjl139090 8735a1b32ccSsubhan diff = (curpic >> 32) - (uint64_t)pic[i*2 + 1]->opl_pic; 8745a1b32ccSsubhan overflow = SPARC64_VI_CHK_OVF(pcr, i*2 + 1); 8755a1b32ccSsubhan if (overflow || (diff < 0)) { 8765a1b32ccSsubhan SPARC64_VI_CLR_OVF(pcr, i*2 + 1); 8775a1b32ccSsubhan ultra_setpcr(pcr); 87825cf1a30Sjl139090 diff += (1ll << 32); 8795a1b32ccSsubhan } 88025cf1a30Sjl139090 *pic_data[i*2 + 1] += diff; 88125cf1a30Sjl139090 88225cf1a30Sjl139090 pic[i*2]->opl_pic = (uint32_t)(curpic & PIC_MASK); 88325cf1a30Sjl139090 pic[i*2 + 1]->opl_pic = (uint32_t)(curpic >> 32); 88425cf1a30Sjl139090 } 8855a1b32ccSsubhan pcr = ultra_getpcr(); 8865a1b32ccSsubhan pcr |= SPARC64_VI_PCR_OVRO; 8875a1b32ccSsubhan ultra_setpcr(pcr); 88825cf1a30Sjl139090 } 88925cf1a30Sjl139090 89025cf1a30Sjl139090 static void 89125cf1a30Sjl139090 opl_pcbe_free(void *config) 89225cf1a30Sjl139090 { 89325cf1a30Sjl139090 kmem_free(config, sizeof (opl_pcbe_config_t)); 89425cf1a30Sjl139090 } 89525cf1a30Sjl139090 89625cf1a30Sjl139090 89725cf1a30Sjl139090 static struct modlpcbe modlpcbe = { 89825cf1a30Sjl139090 &mod_pcbeops, 899820c9f58Skk208521 "SPARC64 VI&VII Perf Cntrs", 90025cf1a30Sjl139090 &opl_pcbe_ops 90125cf1a30Sjl139090 }; 90225cf1a30Sjl139090 90325cf1a30Sjl139090 static struct modlinkage modl = { 90425cf1a30Sjl139090 MODREV_1, 90525cf1a30Sjl139090 &modlpcbe, 90625cf1a30Sjl139090 }; 90725cf1a30Sjl139090 90825cf1a30Sjl139090 int 90925cf1a30Sjl139090 _init(void) 91025cf1a30Sjl139090 { 91125cf1a30Sjl139090 if (opl_pcbe_init() != 0) 91225cf1a30Sjl139090 return (ENOTSUP); 91325cf1a30Sjl139090 return (mod_install(&modl)); 91425cf1a30Sjl139090 } 91525cf1a30Sjl139090 91625cf1a30Sjl139090 int 91725cf1a30Sjl139090 _fini(void) 91825cf1a30Sjl139090 { 91925cf1a30Sjl139090 return (mod_remove(&modl)); 92025cf1a30Sjl139090 } 92125cf1a30Sjl139090 92225cf1a30Sjl139090 int 92325cf1a30Sjl139090 _info(struct modinfo *mi) 92425cf1a30Sjl139090 { 92525cf1a30Sjl139090 return (mod_info(&modl, mi)); 92625cf1a30Sjl139090 } 927