17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5c56c1e58Sgirish * Common Development and Distribution License (the "License"). 6c56c1e58Sgirish * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*4df55fdeSJanie Lu * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <sys/types.h> 277c478bd9Sstevel@tonic-gate #include <sys/async.h> 287c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 297c478bd9Sstevel@tonic-gate #include <sys/sunndi.h> 307c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 317c478bd9Sstevel@tonic-gate #include <sys/machsystm.h> 327c478bd9Sstevel@tonic-gate #include <sys/hypervisor_api.h> 337c478bd9Sstevel@tonic-gate #include <sys/kstat.h> 3444961713Sgirish #if defined(NIAGARA_IMPL) 3544961713Sgirish #include <sys/niagararegs.h> 36*4df55fdeSJanie Lu #elif defined(NIAGARA2_IMPL) || defined(VFALLS_IMPL) || defined(KT_IMPL) 3744961713Sgirish #include <sys/niagara2regs.h> 3844961713Sgirish #endif 397c478bd9Sstevel@tonic-gate 40c56c1e58Sgirish extern char cpu_module_name[]; 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate /* 437c478bd9Sstevel@tonic-gate * Data structure used to build array of event-names and pcr-mask values 447c478bd9Sstevel@tonic-gate */ 457c478bd9Sstevel@tonic-gate typedef struct ni_kev_mask { 467c478bd9Sstevel@tonic-gate char *event_name; 477c478bd9Sstevel@tonic-gate uint64_t pcr_mask; 487c478bd9Sstevel@tonic-gate } ni_kev_mask_t; 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate /* 517c478bd9Sstevel@tonic-gate * Kstat data structure for DRAM and JBUS performance counters 527c478bd9Sstevel@tonic-gate * 537c478bd9Sstevel@tonic-gate * Note that these performance counters are only 31 bits wide. Since 547c478bd9Sstevel@tonic-gate * the "busstat" command assumes a 32-bit counter, we emulate a 32-bit 557c478bd9Sstevel@tonic-gate * counter by detecting overflow on read of these performance counters 567c478bd9Sstevel@tonic-gate * and using the least significant bit of the overflow count as the 577c478bd9Sstevel@tonic-gate * most significant bit (i.e. bit# 31) of the DRAM and JBUS performance 587c478bd9Sstevel@tonic-gate * counters. 597c478bd9Sstevel@tonic-gate */ 60c56c1e58Sgirish #define NUM_OF_PICS 2 61*4df55fdeSJanie Lu #define NUM_OF_PIC_REGS 1 62c56c1e58Sgirish 637c478bd9Sstevel@tonic-gate typedef struct ni_ksinfo { 647c478bd9Sstevel@tonic-gate uint8_t pic_no_evs; /* number of events */ 657c478bd9Sstevel@tonic-gate uint8_t pic_sel_shift[NUM_OF_PICS]; 667c478bd9Sstevel@tonic-gate uint8_t pic_shift[NUM_OF_PICS]; 677c478bd9Sstevel@tonic-gate uint64_t pic_mask[NUM_OF_PICS]; 687c478bd9Sstevel@tonic-gate kstat_t *pic_name_ksp[NUM_OF_PICS]; 697c478bd9Sstevel@tonic-gate kstat_t *cntr_ksp; 70*4df55fdeSJanie Lu uint32_t pic_reg[NUM_OF_PIC_REGS]; 717c478bd9Sstevel@tonic-gate uint32_t pcr_reg; 727c478bd9Sstevel@tonic-gate uint32_t pic_overflow[NUM_OF_PICS]; /* overflow count */ 737c478bd9Sstevel@tonic-gate uint32_t pic_last_val[NUM_OF_PICS]; /* last PIC value */ 747c478bd9Sstevel@tonic-gate } ni_ksinfo_t; 757c478bd9Sstevel@tonic-gate 76*4df55fdeSJanie Lu static ni_ksinfo_t *ni_dram_kstats[DRAM_BANKS]; 7744961713Sgirish 7844961713Sgirish #if defined(NIAGARA_IMPL) 797c478bd9Sstevel@tonic-gate static ni_ksinfo_t *ni_jbus_kstat; 8044961713Sgirish #endif 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate typedef struct ni_perf_regs { 837c478bd9Sstevel@tonic-gate uint32_t pcr_reg; 84*4df55fdeSJanie Lu uint32_t pic_reg[NUM_OF_PIC_REGS]; 857c478bd9Sstevel@tonic-gate } ni_perf_regs_t; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate static ni_perf_regs_t dram_perf_regs[] = { 88*4df55fdeSJanie Lu #if defined(NIAGARA_IMPL) || defined(NIAGARA2_IMPL) 89*4df55fdeSJanie Lu {HV_DRAM_CTL0, HV_DRAM_COUNT0}, 90*4df55fdeSJanie Lu {HV_DRAM_CTL1, HV_DRAM_COUNT1}, 91*4df55fdeSJanie Lu {HV_DRAM_CTL2, HV_DRAM_COUNT2}, 92*4df55fdeSJanie Lu {HV_DRAM_CTL3, HV_DRAM_COUNT3}, 93*4df55fdeSJanie Lu #elif defined(VFALLS_IMPL) || defined(KT_IMPL) 94*4df55fdeSJanie Lu {HV_DRAM_CTL0, HV_DRAM_COUNT0}, 95*4df55fdeSJanie Lu {HV_DRAM_CTL1, HV_DRAM_COUNT1}, 96*4df55fdeSJanie Lu {HV_DRAM_CTL2, HV_DRAM_COUNT2}, 97*4df55fdeSJanie Lu {HV_DRAM_CTL3, HV_DRAM_COUNT3}, 98*4df55fdeSJanie Lu {HV_DRAM_CTL4, HV_DRAM_COUNT4}, 99*4df55fdeSJanie Lu {HV_DRAM_CTL5, HV_DRAM_COUNT5}, 100*4df55fdeSJanie Lu {HV_DRAM_CTL6, HV_DRAM_COUNT6}, 101*4df55fdeSJanie Lu {HV_DRAM_CTL7, HV_DRAM_COUNT7} 10264cfc8edSsvemuri #endif 1037c478bd9Sstevel@tonic-gate }; 1047c478bd9Sstevel@tonic-gate 10564cfc8edSsvemuri #ifdef VFALLS_IMPL 10664cfc8edSsvemuri /* 10764cfc8edSsvemuri * Kstat data structure for Zambezi performance counters 10864cfc8edSsvemuri * These performance counters are 64 bits wide. 10964cfc8edSsvemuri */ 11064cfc8edSsvemuri static ni_ksinfo_t *zam_lpu_kstats[ZAMBEZI_LPU_COUNTERS]; 11164cfc8edSsvemuri static ni_ksinfo_t *zam_gpd_kstats[ZAMBEZI_GPD_COUNTERS]; 11264cfc8edSsvemuri static ni_ksinfo_t *zam_asu_kstats[ZAMBEZI_ASU_COUNTERS]; 11364cfc8edSsvemuri 11464cfc8edSsvemuri typedef struct zam_perf_regs { 11564cfc8edSsvemuri uint32_t pcr_reg; 11664cfc8edSsvemuri uint32_t pic_reg[NUM_OF_PICS]; 11764cfc8edSsvemuri } zam_perf_regs_t; 11864cfc8edSsvemuri 11964cfc8edSsvemuri static zam_perf_regs_t lpu_perf_regs[] = { 12064cfc8edSsvemuri {HV_ZAM0_LPU_A_PCR, HV_ZAM0_LPU_A_PIC0, HV_ZAM0_LPU_A_PIC1}, 12164cfc8edSsvemuri {HV_ZAM0_LPU_B_PCR, HV_ZAM0_LPU_B_PIC0, HV_ZAM0_LPU_B_PIC1}, 12264cfc8edSsvemuri {HV_ZAM0_LPU_C_PCR, HV_ZAM0_LPU_C_PIC0, HV_ZAM0_LPU_C_PIC1}, 12364cfc8edSsvemuri {HV_ZAM0_LPU_D_PCR, HV_ZAM0_LPU_D_PIC0, HV_ZAM0_LPU_D_PIC1}, 12464cfc8edSsvemuri 12564cfc8edSsvemuri {HV_ZAM1_LPU_A_PCR, HV_ZAM1_LPU_A_PIC0, HV_ZAM1_LPU_A_PIC1}, 12664cfc8edSsvemuri {HV_ZAM1_LPU_B_PCR, HV_ZAM1_LPU_B_PIC0, HV_ZAM1_LPU_B_PIC1}, 12764cfc8edSsvemuri {HV_ZAM1_LPU_C_PCR, HV_ZAM1_LPU_C_PIC0, HV_ZAM1_LPU_C_PIC1}, 12864cfc8edSsvemuri {HV_ZAM1_LPU_D_PCR, HV_ZAM1_LPU_D_PIC0, HV_ZAM1_LPU_D_PIC1}, 12964cfc8edSsvemuri 13064cfc8edSsvemuri {HV_ZAM2_LPU_A_PCR, HV_ZAM2_LPU_A_PIC0, HV_ZAM2_LPU_A_PIC1}, 13164cfc8edSsvemuri {HV_ZAM2_LPU_B_PCR, HV_ZAM2_LPU_B_PIC0, HV_ZAM2_LPU_B_PIC1}, 13264cfc8edSsvemuri {HV_ZAM2_LPU_C_PCR, HV_ZAM2_LPU_C_PIC0, HV_ZAM2_LPU_C_PIC1}, 13364cfc8edSsvemuri {HV_ZAM2_LPU_D_PCR, HV_ZAM2_LPU_D_PIC0, HV_ZAM2_LPU_D_PIC1}, 13464cfc8edSsvemuri 13564cfc8edSsvemuri {HV_ZAM3_LPU_A_PCR, HV_ZAM3_LPU_A_PIC0, HV_ZAM3_LPU_A_PIC1}, 13664cfc8edSsvemuri {HV_ZAM3_LPU_B_PCR, HV_ZAM3_LPU_B_PIC0, HV_ZAM3_LPU_B_PIC1}, 13764cfc8edSsvemuri {HV_ZAM3_LPU_C_PCR, HV_ZAM3_LPU_C_PIC0, HV_ZAM3_LPU_C_PIC1}, 13864cfc8edSsvemuri {HV_ZAM3_LPU_D_PCR, HV_ZAM3_LPU_D_PIC0, HV_ZAM3_LPU_D_PIC1} 13964cfc8edSsvemuri }; 14064cfc8edSsvemuri 14164cfc8edSsvemuri static zam_perf_regs_t gpd_perf_regs[] = { 14264cfc8edSsvemuri {HV_ZAM0_GPD_PCR, HV_ZAM0_GPD_PIC0, HV_ZAM0_GPD_PIC1}, 14364cfc8edSsvemuri {HV_ZAM1_GPD_PCR, HV_ZAM1_GPD_PIC0, HV_ZAM1_GPD_PIC1}, 14464cfc8edSsvemuri {HV_ZAM2_GPD_PCR, HV_ZAM2_GPD_PIC0, HV_ZAM2_GPD_PIC1}, 14564cfc8edSsvemuri {HV_ZAM3_GPD_PCR, HV_ZAM3_GPD_PIC0, HV_ZAM3_GPD_PIC1} 14664cfc8edSsvemuri }; 14764cfc8edSsvemuri 14864cfc8edSsvemuri static zam_perf_regs_t asu_perf_regs[] = { 14964cfc8edSsvemuri {HV_ZAM0_ASU_PCR, HV_ZAM0_ASU_PIC0, HV_ZAM0_ASU_PIC1}, 15064cfc8edSsvemuri {HV_ZAM1_ASU_PCR, HV_ZAM1_ASU_PIC0, HV_ZAM1_ASU_PIC1}, 15164cfc8edSsvemuri {HV_ZAM2_ASU_PCR, HV_ZAM2_ASU_PIC0, HV_ZAM2_ASU_PIC1}, 15264cfc8edSsvemuri {HV_ZAM3_ASU_PCR, HV_ZAM3_ASU_PIC0, HV_ZAM3_ASU_PIC1} 15364cfc8edSsvemuri }; 15464cfc8edSsvemuri 15564cfc8edSsvemuri static int zam_cntr_kstat_update(kstat_t *, int); 15664cfc8edSsvemuri #endif 15764cfc8edSsvemuri 1587c478bd9Sstevel@tonic-gate static void ni_create_name_kstat(char *, ni_ksinfo_t *, ni_kev_mask_t *); 1597c478bd9Sstevel@tonic-gate static void ni_delete_name_kstat(ni_ksinfo_t *); 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate static kstat_t *ni_create_cntr_kstat(char *, int, 1627c478bd9Sstevel@tonic-gate int (*update)(kstat_t *, int), void *); 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate static int ni_cntr_kstat_update(kstat_t *, int); 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate static kstat_t *ni_create_picN_kstat(char *, int, int, int, 1677c478bd9Sstevel@tonic-gate ni_kev_mask_t *); 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate #ifdef DEBUG 1707c478bd9Sstevel@tonic-gate static int ni_perf_debug; 1717c478bd9Sstevel@tonic-gate #endif 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate /* 17459ac0c16Sdavemq * Niagara, Niagara2 and VFalls DRAM Performance Events 1757c478bd9Sstevel@tonic-gate */ 1767c478bd9Sstevel@tonic-gate static ni_kev_mask_t 1777c478bd9Sstevel@tonic-gate niagara_dram_events[] = { 178*4df55fdeSJanie Lu #if defined(NIAGARA_IMPL) || defined(NIAGARA2_IMPL) || defined(VFALLS_IMPL) 1797c478bd9Sstevel@tonic-gate {"mem_reads", 0x0}, 1807c478bd9Sstevel@tonic-gate {"mem_writes", 0x1}, 1817c478bd9Sstevel@tonic-gate {"mem_read_write", 0x2}, 182*4df55fdeSJanie Lu #elif defined(KT_IMPL) 183*4df55fdeSJanie Lu {"remote_reads", 0x0}, 184*4df55fdeSJanie Lu {"remote_writes", 0x1}, 185*4df55fdeSJanie Lu {"remote_read_write", 0x2}, 186*4df55fdeSJanie Lu #endif 187*4df55fdeSJanie Lu #if defined(NIAGARA_IMPL) || defined(KT_IMPL) 1887c478bd9Sstevel@tonic-gate {"bank_busy_stalls", 0x3}, 189a588362cSSree Vemuri #endif 1907c478bd9Sstevel@tonic-gate {"rd_queue_latency", 0x4}, 1917c478bd9Sstevel@tonic-gate {"wr_queue_latency", 0x5}, 1927c478bd9Sstevel@tonic-gate {"rw_queue_latency", 0x6}, 193*4df55fdeSJanie Lu #if defined(NIAGARA_IMPL) || defined(NIAGARA2_IMPL) || defined(VFALLS_IMPL) 1947c478bd9Sstevel@tonic-gate {"wb_buf_hits", 0x7}, 195*4df55fdeSJanie Lu #elif defined(KT_IMPL) 196*4df55fdeSJanie Lu {"write_queue_drain", 0x7}, 197*4df55fdeSJanie Lu {"read_all_channels", 0x8}, 198*4df55fdeSJanie Lu {"write_starved", 0x9}, 199*4df55fdeSJanie Lu {"write_all_channels", 0xa}, 200*4df55fdeSJanie Lu {"read_write_channel0", 0xb}, 201*4df55fdeSJanie Lu {"read_write_channel1", 0xc}, 202*4df55fdeSJanie Lu #endif 2037c478bd9Sstevel@tonic-gate {"clear_pic", 0xf} 2047c478bd9Sstevel@tonic-gate }; 2057c478bd9Sstevel@tonic-gate 20664cfc8edSsvemuri #if defined(VFALLS_IMPL) 20764cfc8edSsvemuri /* 20864cfc8edSsvemuri * Zambezi Performance Events 20964cfc8edSsvemuri */ 21064cfc8edSsvemuri static ni_kev_mask_t 21164cfc8edSsvemuri zam_lpu_perf_events[] = { 21264cfc8edSsvemuri {"none", 0x0}, 21364cfc8edSsvemuri {"clock_cycles", 0x1}, 21464cfc8edSsvemuri {"cycles_c2c_portX", 0x2}, 21564cfc8edSsvemuri {"cycles_mem_portX", 0x3}, 21664cfc8edSsvemuri {"cycles_WB_portX", 0x4}, 21764cfc8edSsvemuri {"cycles_NC_portX", 0x5}, 21864cfc8edSsvemuri {"cycles_c2c_portY", 0x6}, 21964cfc8edSsvemuri {"cycles_mem_portY", 0x7}, 22064cfc8edSsvemuri {"cycles_WB_portY", 0x8}, 22164cfc8edSsvemuri {"cycles_NC_portY", 0x9}, 22264cfc8edSsvemuri {"cycles_c2c_portZ", 0xa}, 22364cfc8edSsvemuri {"cycles_mem_portZ", 0xb}, 22464cfc8edSsvemuri {"cycles_WB_portZ", 0xc}, 22564cfc8edSsvemuri {"cycles_NC_portZ", 0xd}, 22664cfc8edSsvemuri {"cycles_TID_WB", 0xe}, 22764cfc8edSsvemuri {"cycles_TID_INV", 0xf}, 22864cfc8edSsvemuri {"cycles_TID_RTD", 0x10}, 22964cfc8edSsvemuri {"cycles_TID_RTO", 0x11}, 23064cfc8edSsvemuri {"cycles_TID_RTS", 0x12}, 23164cfc8edSsvemuri {"cycles_IO_WRM", 0x13}, 23264cfc8edSsvemuri {"cycles_IO_RD", 0x14}, 23364cfc8edSsvemuri {"cycles_WB_egress", 0x15}, 23464cfc8edSsvemuri {"cycles_INV_egress", 0x16}, 23564cfc8edSsvemuri {"cycles_RTO_egress", 0x17}, 23664cfc8edSsvemuri {"cycles_RTD_egress", 0x18}, 23764cfc8edSsvemuri {"cycles_RTS_egress", 0x19}, 23864cfc8edSsvemuri {"cycles_no_WB", 0x1a}, 23964cfc8edSsvemuri {"cycles_no_read/inv", 0x1b}, 24064cfc8edSsvemuri {"cycles_HIT_M", 0x1c}, 24164cfc8edSsvemuri {"cycles_HIT_O", 0x1d}, 24264cfc8edSsvemuri {"cycles_HIT_S", 0x1e}, 24364cfc8edSsvemuri {"cycles_WB_HIT", 0x1f}, 24464cfc8edSsvemuri {"cycles_MISS", 0x20}, 24564cfc8edSsvemuri {"cycles_READ_or_INV", 0x21}, 24664cfc8edSsvemuri {"cycles_WB", 0x22}, 24764cfc8edSsvemuri {"cycles_NDR", 0x23}, 24864cfc8edSsvemuri {"cycles_cache_miss", 0x24}, 24964cfc8edSsvemuri {"cycles_cache_hit", 0x25}, 25064cfc8edSsvemuri {"cycles_CRC_errors", 0x26}, 25164cfc8edSsvemuri {"cycles_replys_sent", 0x27}, 25264cfc8edSsvemuri {"cycles_replys_recev", 0x28}, 25364cfc8edSsvemuri {"cycles_link_retrain", 0x29}, 25464cfc8edSsvemuri {"clear_pic", 0xff} 25564cfc8edSsvemuri }; 25664cfc8edSsvemuri 25764cfc8edSsvemuri static ni_kev_mask_t 25864cfc8edSsvemuri zam_gpd_perf_events[] = { 25964cfc8edSsvemuri {"none", 0x0}, 26064cfc8edSsvemuri {"clock_cycles", 0x1}, 26164cfc8edSsvemuri {"clear_pic", 0xf} 26264cfc8edSsvemuri }; 26364cfc8edSsvemuri 26464cfc8edSsvemuri static ni_kev_mask_t 26564cfc8edSsvemuri zam_asu_perf_events[] = { 26664cfc8edSsvemuri {"none", 0x0}, 26764cfc8edSsvemuri {"clock_cycles", 0x1}, 26864cfc8edSsvemuri {"asu_in_pck", 0x2}, 26964cfc8edSsvemuri {"asu_out_pck", 0x3}, 27064cfc8edSsvemuri {"asu_CAM_hit", 0x4}, 27164cfc8edSsvemuri {"asu_wakeup", 0x5}, 27264cfc8edSsvemuri {"clear_pic", 0xf} 27364cfc8edSsvemuri }; 27464cfc8edSsvemuri #endif 2757c478bd9Sstevel@tonic-gate 27644961713Sgirish #if defined(NIAGARA_IMPL) 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * Niagara JBUS Performance Events 2797c478bd9Sstevel@tonic-gate */ 2807c478bd9Sstevel@tonic-gate static ni_kev_mask_t 2817c478bd9Sstevel@tonic-gate niagara_jbus_events[] = { 2827c478bd9Sstevel@tonic-gate {"jbus_cycles", 0x1}, 2837c478bd9Sstevel@tonic-gate {"dma_reads", 0x2}, 2847c478bd9Sstevel@tonic-gate {"dma_read_latency", 0x3}, 2857c478bd9Sstevel@tonic-gate {"dma_writes", 0x4}, 2867c478bd9Sstevel@tonic-gate {"dma_write8", 0x5}, 2877c478bd9Sstevel@tonic-gate {"ordering_waits", 0x6}, 2887c478bd9Sstevel@tonic-gate {"pio_reads", 0x8}, 2897c478bd9Sstevel@tonic-gate {"pio_read_latency", 0x9}, 2907c478bd9Sstevel@tonic-gate {"aok_dok_off_cycles", 0xc}, 2917c478bd9Sstevel@tonic-gate {"aok_off_cycles", 0xd}, 2927c478bd9Sstevel@tonic-gate {"dok_off_cycles", 0xe}, 2937c478bd9Sstevel@tonic-gate {"clear_pic", 0xf} 2947c478bd9Sstevel@tonic-gate }; 29544961713Sgirish #endif 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate /* 29864cfc8edSsvemuri * Create the picN kstats for DRAM, JBUS and Zambezi events 2997c478bd9Sstevel@tonic-gate */ 3007c478bd9Sstevel@tonic-gate void 3017c478bd9Sstevel@tonic-gate niagara_kstat_init() 3027c478bd9Sstevel@tonic-gate { 3037c478bd9Sstevel@tonic-gate int i; 3047c478bd9Sstevel@tonic-gate ni_ksinfo_t *ksinfop; 305*4df55fdeSJanie Lu #if defined(VFALLS_IMPL) || defined(KT_IMPL) 306b02e9a2dSsvemuri uint64_t stat, pcr; 307b02e9a2dSsvemuri #endif 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate #ifdef DEBUG 3107c478bd9Sstevel@tonic-gate if (ni_perf_debug) 3117c478bd9Sstevel@tonic-gate printf("ni_kstat_init called\n"); 3127c478bd9Sstevel@tonic-gate #endif 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate /* 3157c478bd9Sstevel@tonic-gate * Create DRAM perf events kstat 3167c478bd9Sstevel@tonic-gate */ 317*4df55fdeSJanie Lu for (i = 0; i < DRAM_BANKS; i++) { 318*4df55fdeSJanie Lu #if defined(VFALLS_IMPL) || defined(KT_IMPL) 31959ac0c16Sdavemq /* check if this dram instance is enabled in the HW */ 32064cfc8edSsvemuri stat = hv_niagara_getperf(dram_perf_regs[i].pcr_reg, &pcr); 32164cfc8edSsvemuri if ((stat != H_EINVAL) && (stat != H_ENOTSUPPORTED)) { 32259ac0c16Sdavemq #endif 32359ac0c16Sdavemq ksinfop = (ni_ksinfo_t *)kmem_zalloc( 32459ac0c16Sdavemq sizeof (ni_ksinfo_t), KM_NOSLEEP); 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate if (ksinfop == NULL) { 3277c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 32859ac0c16Sdavemq "%s: no space for dram kstat\n", 329c56c1e58Sgirish cpu_module_name); 3307c478bd9Sstevel@tonic-gate break; 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate ksinfop->pic_no_evs = 33359ac0c16Sdavemq sizeof (niagara_dram_events) / 33459ac0c16Sdavemq sizeof (ni_kev_mask_t); 335*4df55fdeSJanie Lu ksinfop->pic_sel_shift[0] = DRAM_PIC0_SEL_SHIFT; 336*4df55fdeSJanie Lu ksinfop->pic_shift[0] = DRAM_PIC0_SHIFT; 337*4df55fdeSJanie Lu ksinfop->pic_mask[0] = DRAM_PIC0_MASK; 338*4df55fdeSJanie Lu ksinfop->pic_sel_shift[1] = DRAM_PIC1_SEL_SHIFT; 339*4df55fdeSJanie Lu ksinfop->pic_shift[1] = DRAM_PIC1_SHIFT; 340*4df55fdeSJanie Lu ksinfop->pic_mask[1] = DRAM_PIC1_MASK; 341*4df55fdeSJanie Lu ksinfop->pic_reg[0] = dram_perf_regs[i].pic_reg[0]; 3427c478bd9Sstevel@tonic-gate ksinfop->pcr_reg = dram_perf_regs[i].pcr_reg; 3437c478bd9Sstevel@tonic-gate ni_dram_kstats[i] = ksinfop; 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate /* create basic pic event/mask pair (only once) */ 3467c478bd9Sstevel@tonic-gate if (i == 0) 3477c478bd9Sstevel@tonic-gate ni_create_name_kstat("dram", ksinfop, 3487c478bd9Sstevel@tonic-gate niagara_dram_events); 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate /* create counter kstats */ 35159ac0c16Sdavemq ni_dram_kstats[i]->cntr_ksp = ni_create_cntr_kstat( 35259ac0c16Sdavemq "dram", i, ni_cntr_kstat_update, ksinfop); 353*4df55fdeSJanie Lu #if defined(VFALLS_IMPL) || defined(KT_IMPL) 35459ac0c16Sdavemq } 35559ac0c16Sdavemq #endif 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate 35864cfc8edSsvemuri #ifdef VFALLS_IMPL 35964cfc8edSsvemuri /* 36064cfc8edSsvemuri * Create Zambezi LPU perf events kstat 36164cfc8edSsvemuri */ 36264cfc8edSsvemuri for (i = 0; i < ZAMBEZI_LPU_COUNTERS; i++) { 36364cfc8edSsvemuri /* check if this Zambezi LPU instance is enabled in the HW */ 36464cfc8edSsvemuri stat = hv_niagara_getperf(lpu_perf_regs[i].pcr_reg, &pcr); 36564cfc8edSsvemuri if ((stat != H_EINVAL) && (stat != H_ENOTSUPPORTED)) { 36664cfc8edSsvemuri ksinfop = (ni_ksinfo_t *)kmem_zalloc( 36764cfc8edSsvemuri sizeof (ni_ksinfo_t), KM_NOSLEEP); 36864cfc8edSsvemuri 36964cfc8edSsvemuri if (ksinfop == NULL) { 37064cfc8edSsvemuri cmn_err(CE_WARN, 37164cfc8edSsvemuri "%s: no space for zambezi lpu kstat\n", 37264cfc8edSsvemuri cpu_module_name); 37364cfc8edSsvemuri break; 37464cfc8edSsvemuri } 37564cfc8edSsvemuri ksinfop->pic_no_evs = 37664cfc8edSsvemuri sizeof (zam_lpu_perf_events) / 37764cfc8edSsvemuri sizeof (ni_kev_mask_t); 37864cfc8edSsvemuri ksinfop->pic_sel_shift[0] = ZAMBEZI_PIC0_SEL_SHIFT; 37964cfc8edSsvemuri ksinfop->pic_reg[0] = lpu_perf_regs[i].pic_reg[0]; 38064cfc8edSsvemuri ksinfop->pic_sel_shift[1] = ZAMBEZI_PIC1_SEL_SHIFT; 38164cfc8edSsvemuri ksinfop->pic_reg[1] = lpu_perf_regs[i].pic_reg[1]; 38264cfc8edSsvemuri ksinfop->pcr_reg = lpu_perf_regs[i].pcr_reg; 38364cfc8edSsvemuri zam_lpu_kstats[i] = ksinfop; 38464cfc8edSsvemuri 38564cfc8edSsvemuri /* create basic pic event/mask pair (only once) */ 38664cfc8edSsvemuri if (i == 0) 38764cfc8edSsvemuri ni_create_name_kstat("lpu", ksinfop, 38864cfc8edSsvemuri zam_lpu_perf_events); 38964cfc8edSsvemuri 39064cfc8edSsvemuri /* create counter kstats */ 39164cfc8edSsvemuri zam_lpu_kstats[i]->cntr_ksp = ni_create_cntr_kstat( 39264cfc8edSsvemuri "lpu", i, zam_cntr_kstat_update, ksinfop); 39364cfc8edSsvemuri } 39464cfc8edSsvemuri } 39564cfc8edSsvemuri /* 39664cfc8edSsvemuri * Create Zambezi GPD perf events kstat 39764cfc8edSsvemuri */ 39864cfc8edSsvemuri for (i = 0; i < ZAMBEZI_GPD_COUNTERS; i++) { 39964cfc8edSsvemuri /* check if this Zambezi GPD instance is enabled in the HW */ 40064cfc8edSsvemuri stat = hv_niagara_getperf(gpd_perf_regs[i].pcr_reg, &pcr); 40164cfc8edSsvemuri if ((stat != H_EINVAL) && (stat != H_ENOTSUPPORTED)) { 40264cfc8edSsvemuri ksinfop = (ni_ksinfo_t *)kmem_zalloc( 40364cfc8edSsvemuri sizeof (ni_ksinfo_t), KM_NOSLEEP); 40464cfc8edSsvemuri 40564cfc8edSsvemuri if (ksinfop == NULL) { 40664cfc8edSsvemuri cmn_err(CE_WARN, 40764cfc8edSsvemuri "%s: no space for zambezi gpd kstat\n", 40864cfc8edSsvemuri cpu_module_name); 40964cfc8edSsvemuri break; 41064cfc8edSsvemuri } 41164cfc8edSsvemuri ksinfop->pic_no_evs = 41264cfc8edSsvemuri sizeof (zam_gpd_perf_events) / 41364cfc8edSsvemuri sizeof (ni_kev_mask_t); 41464cfc8edSsvemuri ksinfop->pic_sel_shift[0] = ZAMBEZI_PIC0_SEL_SHIFT; 41564cfc8edSsvemuri ksinfop->pic_reg[0] = gpd_perf_regs[i].pic_reg[0]; 41664cfc8edSsvemuri ksinfop->pic_sel_shift[1] = ZAMBEZI_PIC1_SEL_SHIFT; 41764cfc8edSsvemuri ksinfop->pic_reg[1] = gpd_perf_regs[i].pic_reg[1]; 41864cfc8edSsvemuri ksinfop->pcr_reg = gpd_perf_regs[i].pcr_reg; 41964cfc8edSsvemuri zam_gpd_kstats[i] = ksinfop; 42064cfc8edSsvemuri 42164cfc8edSsvemuri /* create basic pic event/mask pair (only once) */ 42264cfc8edSsvemuri if (i == 0) 42364cfc8edSsvemuri ni_create_name_kstat("gpd", ksinfop, 42464cfc8edSsvemuri zam_gpd_perf_events); 42564cfc8edSsvemuri 42664cfc8edSsvemuri /* create counter kstats */ 42764cfc8edSsvemuri zam_lpu_kstats[i]->cntr_ksp = ni_create_cntr_kstat( 42864cfc8edSsvemuri "gpd", i, zam_cntr_kstat_update, ksinfop); 42964cfc8edSsvemuri } 43064cfc8edSsvemuri } 43164cfc8edSsvemuri /* 43264cfc8edSsvemuri * Create Zambezi ASU perf events kstat 43364cfc8edSsvemuri */ 43464cfc8edSsvemuri for (i = 0; i < ZAMBEZI_ASU_COUNTERS; i++) { 43564cfc8edSsvemuri /* check if this Zambezi ASU instance is enabled in the HW */ 43664cfc8edSsvemuri stat = hv_niagara_getperf(asu_perf_regs[i].pcr_reg, &pcr); 43764cfc8edSsvemuri if ((stat != H_EINVAL) && (stat != H_ENOTSUPPORTED)) { 43864cfc8edSsvemuri ksinfop = (ni_ksinfo_t *)kmem_zalloc( 43964cfc8edSsvemuri sizeof (ni_ksinfo_t), KM_NOSLEEP); 44064cfc8edSsvemuri 44164cfc8edSsvemuri if (ksinfop == NULL) { 44264cfc8edSsvemuri cmn_err(CE_WARN, 44364cfc8edSsvemuri "%s: no space for zambezi asu kstat\n", 44464cfc8edSsvemuri cpu_module_name); 44564cfc8edSsvemuri break; 44664cfc8edSsvemuri } 44764cfc8edSsvemuri ksinfop->pic_no_evs = 44864cfc8edSsvemuri sizeof (zam_asu_perf_events) / 44964cfc8edSsvemuri sizeof (ni_kev_mask_t); 45064cfc8edSsvemuri ksinfop->pic_sel_shift[0] = ZAMBEZI_PIC0_SEL_SHIFT; 45164cfc8edSsvemuri ksinfop->pic_reg[0] = asu_perf_regs[i].pic_reg[0]; 45264cfc8edSsvemuri ksinfop->pic_sel_shift[1] = ZAMBEZI_PIC1_SEL_SHIFT; 45364cfc8edSsvemuri ksinfop->pic_reg[1] = asu_perf_regs[i].pic_reg[1]; 45464cfc8edSsvemuri ksinfop->pcr_reg = asu_perf_regs[i].pcr_reg; 45564cfc8edSsvemuri zam_asu_kstats[i] = ksinfop; 45664cfc8edSsvemuri 45764cfc8edSsvemuri /* create basic pic event/mask pair (only once) */ 45864cfc8edSsvemuri if (i == 0) 45964cfc8edSsvemuri ni_create_name_kstat("asu", ksinfop, 46064cfc8edSsvemuri zam_asu_perf_events); 46164cfc8edSsvemuri 46264cfc8edSsvemuri /* create counter kstats */ 46364cfc8edSsvemuri zam_lpu_kstats[i]->cntr_ksp = ni_create_cntr_kstat( 46464cfc8edSsvemuri "asu", i, zam_cntr_kstat_update, ksinfop); 46564cfc8edSsvemuri } 46664cfc8edSsvemuri } 46764cfc8edSsvemuri #endif 46864cfc8edSsvemuri 46944961713Sgirish #if defined(NIAGARA_IMPL) 4707c478bd9Sstevel@tonic-gate /* 4717c478bd9Sstevel@tonic-gate * Create JBUS perf events kstat 4727c478bd9Sstevel@tonic-gate */ 4737c478bd9Sstevel@tonic-gate ni_jbus_kstat = (ni_ksinfo_t *)kmem_alloc(sizeof (ni_ksinfo_t), 4747c478bd9Sstevel@tonic-gate KM_NOSLEEP); 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate if (ni_jbus_kstat == NULL) { 4777c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s: no space for niagara jbus kstat\n", 478c56c1e58Sgirish cpu_module_name); 4797c478bd9Sstevel@tonic-gate } else { 4807c478bd9Sstevel@tonic-gate ni_jbus_kstat->pic_no_evs = 4817c478bd9Sstevel@tonic-gate sizeof (niagara_jbus_events) / sizeof (ni_kev_mask_t); 4827c478bd9Sstevel@tonic-gate ni_jbus_kstat->pic_sel_shift[0] = NIAGARA_JBUS_PIC0_SEL_SHIFT; 4837c478bd9Sstevel@tonic-gate ni_jbus_kstat->pic_shift[0] = NIAGARA_JBUS_PIC0_SHIFT; 4847c478bd9Sstevel@tonic-gate ni_jbus_kstat->pic_mask[0] = NIAGARA_JBUS_PIC0_MASK; 4857c478bd9Sstevel@tonic-gate ni_jbus_kstat->pic_sel_shift[1] = NIAGARA_JBUS_PIC1_SEL_SHIFT; 4867c478bd9Sstevel@tonic-gate ni_jbus_kstat->pic_shift[1] = NIAGARA_JBUS_PIC1_SHIFT; 4877c478bd9Sstevel@tonic-gate ni_jbus_kstat->pic_mask[1] = NIAGARA_JBUS_PIC1_MASK; 48864cfc8edSsvemuri ni_jbus_kstat->pic_reg[0] = HV_NIAGARA_JBUS_COUNT; 4897c478bd9Sstevel@tonic-gate ni_jbus_kstat->pcr_reg = HV_NIAGARA_JBUS_CTL; 4907c478bd9Sstevel@tonic-gate ni_create_name_kstat("jbus", ni_jbus_kstat, 4917c478bd9Sstevel@tonic-gate niagara_jbus_events); 4927c478bd9Sstevel@tonic-gate ni_jbus_kstat->cntr_ksp = ni_create_cntr_kstat("jbus", 0, 4937c478bd9Sstevel@tonic-gate ni_cntr_kstat_update, ni_jbus_kstat); 4947c478bd9Sstevel@tonic-gate } 49544961713Sgirish #endif 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate void 4997c478bd9Sstevel@tonic-gate niagara_kstat_fini() 5007c478bd9Sstevel@tonic-gate { 5017c478bd9Sstevel@tonic-gate int i; 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate #ifdef DEBUG 5047c478bd9Sstevel@tonic-gate if (ni_perf_debug) 5057c478bd9Sstevel@tonic-gate printf("ni_kstat_fini called\n"); 5067c478bd9Sstevel@tonic-gate #endif 50764cfc8edSsvemuri 508*4df55fdeSJanie Lu for (i = 0; i < DRAM_BANKS; i++) { 5097c478bd9Sstevel@tonic-gate if (ni_dram_kstats[i] != NULL) { 5107c478bd9Sstevel@tonic-gate ni_delete_name_kstat(ni_dram_kstats[i]); 5117c478bd9Sstevel@tonic-gate if (ni_dram_kstats[i]->cntr_ksp != NULL) 5127c478bd9Sstevel@tonic-gate kstat_delete(ni_dram_kstats[i]->cntr_ksp); 5137c478bd9Sstevel@tonic-gate kmem_free(ni_dram_kstats[i], sizeof (ni_ksinfo_t)); 5147c478bd9Sstevel@tonic-gate ni_dram_kstats[i] = NULL; 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate 51864cfc8edSsvemuri #if defined(VFALLS_IMPL) 51964cfc8edSsvemuri for (i = 0; i < ZAMBEZI_LPU_COUNTERS; i++) { 52064cfc8edSsvemuri if (zam_lpu_kstats[i] != NULL) { 52164cfc8edSsvemuri ni_delete_name_kstat(zam_lpu_kstats[i]); 52264cfc8edSsvemuri if (zam_lpu_kstats[i]->cntr_ksp != NULL) 52364cfc8edSsvemuri kstat_delete(zam_lpu_kstats[i]->cntr_ksp); 52464cfc8edSsvemuri kmem_free(zam_lpu_kstats[i], sizeof (ni_ksinfo_t)); 52564cfc8edSsvemuri zam_lpu_kstats[i] = NULL; 52664cfc8edSsvemuri } 52764cfc8edSsvemuri } 52864cfc8edSsvemuri 52964cfc8edSsvemuri for (i = 0; i < ZAMBEZI_GPD_COUNTERS; i++) { 53064cfc8edSsvemuri if (zam_gpd_kstats[i] != NULL) { 53164cfc8edSsvemuri ni_delete_name_kstat(zam_gpd_kstats[i]); 53264cfc8edSsvemuri if (zam_gpd_kstats[i]->cntr_ksp != NULL) 53364cfc8edSsvemuri kstat_delete(zam_gpd_kstats[i]->cntr_ksp); 53464cfc8edSsvemuri kmem_free(zam_gpd_kstats[i], sizeof (ni_ksinfo_t)); 53564cfc8edSsvemuri zam_gpd_kstats[i] = NULL; 53664cfc8edSsvemuri } 53764cfc8edSsvemuri } 53864cfc8edSsvemuri 53964cfc8edSsvemuri for (i = 0; i < ZAMBEZI_ASU_COUNTERS; i++) { 54064cfc8edSsvemuri if (zam_asu_kstats[i] != NULL) { 54164cfc8edSsvemuri ni_delete_name_kstat(zam_asu_kstats[i]); 54264cfc8edSsvemuri if (zam_asu_kstats[i]->cntr_ksp != NULL) 54364cfc8edSsvemuri kstat_delete(zam_asu_kstats[i]->cntr_ksp); 54464cfc8edSsvemuri kmem_free(zam_asu_kstats[i], sizeof (ni_ksinfo_t)); 54564cfc8edSsvemuri zam_asu_kstats[i] = NULL; 54664cfc8edSsvemuri } 54764cfc8edSsvemuri } 54864cfc8edSsvemuri #endif 54964cfc8edSsvemuri 55044961713Sgirish #if defined(NIAGARA_IMPL) 5517c478bd9Sstevel@tonic-gate if (ni_jbus_kstat != NULL) { 5527c478bd9Sstevel@tonic-gate ni_delete_name_kstat(ni_jbus_kstat); 5537c478bd9Sstevel@tonic-gate if (ni_jbus_kstat->cntr_ksp != NULL) 5547c478bd9Sstevel@tonic-gate kstat_delete(ni_jbus_kstat->cntr_ksp); 5557c478bd9Sstevel@tonic-gate kmem_free(ni_jbus_kstat, sizeof (ni_ksinfo_t)); 5567c478bd9Sstevel@tonic-gate ni_jbus_kstat = NULL; 5577c478bd9Sstevel@tonic-gate } 55844961713Sgirish #endif 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate static void 5627c478bd9Sstevel@tonic-gate ni_create_name_kstat(char *name, ni_ksinfo_t *pp, ni_kev_mask_t *ev) 5637c478bd9Sstevel@tonic-gate { 5647c478bd9Sstevel@tonic-gate int i; 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate #ifdef DEBUG 5677c478bd9Sstevel@tonic-gate if (ni_perf_debug > 1) 5687c478bd9Sstevel@tonic-gate printf("ni_create_name_kstat: name: %s\n", name); 5697c478bd9Sstevel@tonic-gate #endif 5707c478bd9Sstevel@tonic-gate for (i = 0; i < NUM_OF_PICS; i++) { 5717c478bd9Sstevel@tonic-gate pp->pic_name_ksp[i] = ni_create_picN_kstat(name, 5727c478bd9Sstevel@tonic-gate i, pp->pic_sel_shift[i], pp->pic_no_evs, ev); 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate if (pp->pic_name_ksp[i] == NULL) { 5757c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s: unable to create name kstat", 576c56c1e58Sgirish cpu_module_name); 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate } 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate static void 5827c478bd9Sstevel@tonic-gate ni_delete_name_kstat(ni_ksinfo_t *pp) 5837c478bd9Sstevel@tonic-gate { 5847c478bd9Sstevel@tonic-gate int i; 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate if (pp != NULL) { 5877c478bd9Sstevel@tonic-gate for (i = 0; i < NUM_OF_PICS; i++) { 5887c478bd9Sstevel@tonic-gate if (pp->pic_name_ksp[i] != NULL) 5897c478bd9Sstevel@tonic-gate kstat_delete(pp->pic_name_ksp[i]); 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate } 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate /* 5957c478bd9Sstevel@tonic-gate * Create the picN kstat. Returns a pointer to the 5967c478bd9Sstevel@tonic-gate * kstat which the driver must store to allow it 5977c478bd9Sstevel@tonic-gate * to be deleted when necessary. 5987c478bd9Sstevel@tonic-gate */ 5997c478bd9Sstevel@tonic-gate static kstat_t * 6007c478bd9Sstevel@tonic-gate ni_create_picN_kstat(char *mod_name, int pic, int pic_sel_shift, 6017c478bd9Sstevel@tonic-gate int num_ev, ni_kev_mask_t *ev_array) 6027c478bd9Sstevel@tonic-gate { 6037c478bd9Sstevel@tonic-gate struct kstat_named *pic_named_data; 6047c478bd9Sstevel@tonic-gate int inst = 0; 6057c478bd9Sstevel@tonic-gate int event; 6067c478bd9Sstevel@tonic-gate char pic_name[30]; 6077c478bd9Sstevel@tonic-gate kstat_t *picN_ksp = NULL; 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate (void) sprintf(pic_name, "pic%d", pic); 6107c478bd9Sstevel@tonic-gate if ((picN_ksp = kstat_create(mod_name, inst, pic_name, 6117c478bd9Sstevel@tonic-gate "bus", KSTAT_TYPE_NAMED, num_ev, NULL)) == NULL) { 6127c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s %s : kstat create failed", 6137c478bd9Sstevel@tonic-gate mod_name, pic_name); 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate /* 6167c478bd9Sstevel@tonic-gate * It is up to the calling function to delete any kstats 6177c478bd9Sstevel@tonic-gate * that may have been created already. We just 6187c478bd9Sstevel@tonic-gate * return NULL to indicate an error has occured. 6197c478bd9Sstevel@tonic-gate */ 6207c478bd9Sstevel@tonic-gate return (NULL); 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate pic_named_data = (struct kstat_named *) 6247c478bd9Sstevel@tonic-gate picN_ksp->ks_data; 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate /* 6277c478bd9Sstevel@tonic-gate * Write event names and their associated pcr masks. The 6287c478bd9Sstevel@tonic-gate * last entry in the array (clear_pic) is added seperately 6297c478bd9Sstevel@tonic-gate * below as the pic value must be inverted. 6307c478bd9Sstevel@tonic-gate */ 6317c478bd9Sstevel@tonic-gate for (event = 0; event < num_ev - 1; event++) { 6327c478bd9Sstevel@tonic-gate pic_named_data[event].value.ui64 = 6337c478bd9Sstevel@tonic-gate (ev_array[event].pcr_mask << pic_sel_shift); 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate kstat_named_init(&pic_named_data[event], 6367c478bd9Sstevel@tonic-gate ev_array[event].event_name, 6377c478bd9Sstevel@tonic-gate KSTAT_DATA_UINT64); 6387c478bd9Sstevel@tonic-gate } 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate /* 6417c478bd9Sstevel@tonic-gate * add the clear_pic entry. 6427c478bd9Sstevel@tonic-gate */ 6437c478bd9Sstevel@tonic-gate pic_named_data[event].value.ui64 = 6447c478bd9Sstevel@tonic-gate (uint64_t)~(ev_array[event].pcr_mask << pic_sel_shift); 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate kstat_named_init(&pic_named_data[event], ev_array[event].event_name, 6477c478bd9Sstevel@tonic-gate KSTAT_DATA_UINT64); 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate kstat_install(picN_ksp); 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate return (picN_ksp); 6527c478bd9Sstevel@tonic-gate } 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate /* 6557c478bd9Sstevel@tonic-gate * Create the "counters" kstat. 6567c478bd9Sstevel@tonic-gate */ 6577c478bd9Sstevel@tonic-gate static kstat_t * 6587c478bd9Sstevel@tonic-gate ni_create_cntr_kstat(char *name, int instance, int (*update)(kstat_t *, int), 6597c478bd9Sstevel@tonic-gate void *ksinfop) 6607c478bd9Sstevel@tonic-gate { 6617c478bd9Sstevel@tonic-gate struct kstat *counters_ksp; 6627c478bd9Sstevel@tonic-gate struct kstat_named *counters_named_data; 6637c478bd9Sstevel@tonic-gate char pic_str[10]; 6647c478bd9Sstevel@tonic-gate int i; 6657c478bd9Sstevel@tonic-gate int num_pics = NUM_OF_PICS; 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate #ifdef DEBUG 6687c478bd9Sstevel@tonic-gate if (ni_perf_debug > 1) 6697c478bd9Sstevel@tonic-gate printf("ni_create_cntr_kstat: name: %s instance: %d\n", 6707c478bd9Sstevel@tonic-gate name, instance); 6717c478bd9Sstevel@tonic-gate #endif 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate /* 6747c478bd9Sstevel@tonic-gate * Size of kstat is num_pics + 1 as it 6757c478bd9Sstevel@tonic-gate * also contains the %pcr 6767c478bd9Sstevel@tonic-gate */ 6777c478bd9Sstevel@tonic-gate if ((counters_ksp = kstat_create(name, instance, "counters", "bus", 6787c478bd9Sstevel@tonic-gate KSTAT_TYPE_NAMED, num_pics + 1, KSTAT_FLAG_WRITABLE)) == NULL) { 6797c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 680c56c1e58Sgirish "%s: kstat_create for %s%d failed", cpu_module_name, 6817c478bd9Sstevel@tonic-gate name, instance); 6827c478bd9Sstevel@tonic-gate return (NULL); 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate counters_named_data = (struct kstat_named *)(counters_ksp->ks_data); 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate /* 6887c478bd9Sstevel@tonic-gate * Iinitialize the named kstats 6897c478bd9Sstevel@tonic-gate */ 6907c478bd9Sstevel@tonic-gate kstat_named_init(&counters_named_data[0], "pcr", KSTAT_DATA_UINT64); 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate for (i = 0; i < num_pics; i++) { 6937c478bd9Sstevel@tonic-gate (void) sprintf(pic_str, "pic%d", i); 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate kstat_named_init(&counters_named_data[i+1], pic_str, 6967c478bd9Sstevel@tonic-gate KSTAT_DATA_UINT64); 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate /* 7007c478bd9Sstevel@tonic-gate * Store the register offset's in the kstat's 7017c478bd9Sstevel@tonic-gate * private field so that they are available 7027c478bd9Sstevel@tonic-gate * to the update function. 7037c478bd9Sstevel@tonic-gate */ 7047c478bd9Sstevel@tonic-gate counters_ksp->ks_private = (void *)ksinfop; 7057c478bd9Sstevel@tonic-gate counters_ksp->ks_update = update; 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate kstat_install(counters_ksp); 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate return (counters_ksp); 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate 71264cfc8edSsvemuri #if defined(VFALLS_IMPL) 71364cfc8edSsvemuri /* 71464cfc8edSsvemuri * zambezi kstat update function. Handles reads/writes 71564cfc8edSsvemuri * from/to kstat. 71664cfc8edSsvemuri */ 71764cfc8edSsvemuri static int 71864cfc8edSsvemuri zam_cntr_kstat_update(kstat_t *ksp, int rw) 71964cfc8edSsvemuri { 72064cfc8edSsvemuri struct kstat_named *data_p; 72164cfc8edSsvemuri ni_ksinfo_t *ksinfop = ksp->ks_private; 72264cfc8edSsvemuri uint64_t pic0, pic1, pcr; 72364cfc8edSsvemuri int stat = 0; 72464cfc8edSsvemuri uint64_t pic0_stat = 0, pic1_stat = 0, pcr_stat = 0; 72564cfc8edSsvemuri 72664cfc8edSsvemuri data_p = (struct kstat_named *)ksp->ks_data; 72764cfc8edSsvemuri 72864cfc8edSsvemuri if (rw == KSTAT_WRITE) { 72964cfc8edSsvemuri #ifdef DEBUG 73064cfc8edSsvemuri if (ni_perf_debug) 73164cfc8edSsvemuri printf("zam_cntr_kstat_update: wr pcr-%d: %lx\n", 73264cfc8edSsvemuri ksinfop->pcr_reg, data_p[0].value.ui64); 73364cfc8edSsvemuri #endif 73464cfc8edSsvemuri if (hv_niagara_setperf(ksinfop->pcr_reg, data_p[0].value.ui64)) 73564cfc8edSsvemuri stat = EACCES; 73664cfc8edSsvemuri } else { 73764cfc8edSsvemuri do { 73864cfc8edSsvemuri pic0_stat = hv_niagara_getperf(ksinfop->pic_reg[0], 73964cfc8edSsvemuri &pic0); 74064cfc8edSsvemuri } while (pic0_stat == H_EWOULDBLOCK); 74164cfc8edSsvemuri do { 74264cfc8edSsvemuri pic1_stat = hv_niagara_getperf(ksinfop->pic_reg[1], 74364cfc8edSsvemuri &pic1); 74464cfc8edSsvemuri } while (pic1_stat == H_EWOULDBLOCK); 74564cfc8edSsvemuri do { 74664cfc8edSsvemuri pcr_stat = hv_niagara_getperf(ksinfop->pcr_reg, 74764cfc8edSsvemuri &pcr); 74864cfc8edSsvemuri } while (pcr_stat == H_EWOULDBLOCK); 74964cfc8edSsvemuri if (pic0_stat != 0 || pic1_stat != 0 || pcr_stat != 0) 75064cfc8edSsvemuri stat = EACCES; 75164cfc8edSsvemuri else { 75264cfc8edSsvemuri data_p[0].value.ui64 = pcr; 75364cfc8edSsvemuri data_p[1].value.ui64 = pic0; 75464cfc8edSsvemuri data_p[2].value.ui64 = pic1; 75564cfc8edSsvemuri } 75664cfc8edSsvemuri #ifdef DEBUG 75764cfc8edSsvemuri if (ni_perf_debug) 75864cfc8edSsvemuri printf("zam_cntr_kstat_update: rd pcr%d: %lx " 75964cfc8edSsvemuri "pic0: %16lx pic1: %16lx\n", 76064cfc8edSsvemuri ksinfop->pcr_reg, pcr, 76164cfc8edSsvemuri data_p[1].value.ui64, data_p[2].value.ui64); 76264cfc8edSsvemuri #endif 76364cfc8edSsvemuri } 76464cfc8edSsvemuri 76564cfc8edSsvemuri return (stat); 76664cfc8edSsvemuri } 76764cfc8edSsvemuri #endif 76864cfc8edSsvemuri 7697c478bd9Sstevel@tonic-gate /* 7707c478bd9Sstevel@tonic-gate * kstat update function. Handles reads/writes 7717c478bd9Sstevel@tonic-gate * from/to kstat. 7727c478bd9Sstevel@tonic-gate */ 7737c478bd9Sstevel@tonic-gate static int 7747c478bd9Sstevel@tonic-gate ni_cntr_kstat_update(kstat_t *ksp, int rw) 7757c478bd9Sstevel@tonic-gate { 7767c478bd9Sstevel@tonic-gate struct kstat_named *data_p; 7777c478bd9Sstevel@tonic-gate ni_ksinfo_t *ksinfop = ksp->ks_private; 7787c478bd9Sstevel@tonic-gate uint64_t pic, pcr; 7797c478bd9Sstevel@tonic-gate int stat = 0; 7807c478bd9Sstevel@tonic-gate uint32_t pic0, pic1; 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate data_p = (struct kstat_named *)ksp->ks_data; 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate if (rw == KSTAT_WRITE) { 7857c478bd9Sstevel@tonic-gate #ifdef DEBUG 7867c478bd9Sstevel@tonic-gate if (ni_perf_debug) 7870bd5614cSiskreen printf("ni_cntr_kstat_update: wr pcr-%d: %lx\n", 7887c478bd9Sstevel@tonic-gate ksinfop->pcr_reg, data_p[0].value.ui64); 7897c478bd9Sstevel@tonic-gate #endif 7907c478bd9Sstevel@tonic-gate if (hv_niagara_setperf(ksinfop->pcr_reg, data_p[0].value.ui64)) 7917c478bd9Sstevel@tonic-gate stat = EACCES; 7927c478bd9Sstevel@tonic-gate } else { 79364cfc8edSsvemuri if (hv_niagara_getperf(ksinfop->pic_reg[0], &pic) != 0 || 7947c478bd9Sstevel@tonic-gate hv_niagara_getperf(ksinfop->pcr_reg, &pcr) != 0) 7957c478bd9Sstevel@tonic-gate stat = EACCES; 7967c478bd9Sstevel@tonic-gate else { 7977c478bd9Sstevel@tonic-gate data_p[0].value.ui64 = pcr; 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate /* 8007c478bd9Sstevel@tonic-gate * Generate a 32-bit PIC0 value by detecting overflow 8017c478bd9Sstevel@tonic-gate */ 8027c478bd9Sstevel@tonic-gate pic0 = (uint32_t)((pic >> ksinfop->pic_shift[0]) & 8037c478bd9Sstevel@tonic-gate ksinfop->pic_mask[0]); 8047c478bd9Sstevel@tonic-gate if (pic0 < ksinfop->pic_last_val[0]) 8057c478bd9Sstevel@tonic-gate ksinfop->pic_overflow[0]++; 8067c478bd9Sstevel@tonic-gate ksinfop->pic_last_val[0] = pic0; 8077c478bd9Sstevel@tonic-gate pic0 += (ksinfop->pic_overflow[0] & 1) << 31; 8087c478bd9Sstevel@tonic-gate data_p[1].value.ui64 = (uint64_t)pic0; 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate /* 8117c478bd9Sstevel@tonic-gate * Generate a 32-bit PIC1 value by detecting overflow 8127c478bd9Sstevel@tonic-gate */ 8137c478bd9Sstevel@tonic-gate pic1 = (uint32_t)((pic >> ksinfop->pic_shift[1]) & 8147c478bd9Sstevel@tonic-gate ksinfop->pic_mask[1]); 8157c478bd9Sstevel@tonic-gate if (pic1 < ksinfop->pic_last_val[1]) 8167c478bd9Sstevel@tonic-gate ksinfop->pic_overflow[1]++; 8177c478bd9Sstevel@tonic-gate ksinfop->pic_last_val[1] = pic1; 8187c478bd9Sstevel@tonic-gate pic1 += (ksinfop->pic_overflow[1] & 1) << 31; 8197c478bd9Sstevel@tonic-gate data_p[2].value.ui64 = (uint64_t)pic1; 8207c478bd9Sstevel@tonic-gate } 8217c478bd9Sstevel@tonic-gate #ifdef DEBUG 8227c478bd9Sstevel@tonic-gate if (ni_perf_debug) 8237c478bd9Sstevel@tonic-gate printf("ni_cntr_kstat_update: rd pcr%d: %lx " 8247c478bd9Sstevel@tonic-gate "pic%d: %16lx pic0: %8lx pic1: %8lx\n", 82564cfc8edSsvemuri ksinfop->pcr_reg, pcr, ksinfop->pic_reg[0], pic, 8267c478bd9Sstevel@tonic-gate data_p[1].value.ui64, data_p[2].value.ui64); 8277c478bd9Sstevel@tonic-gate #endif 8287c478bd9Sstevel@tonic-gate } 8297c478bd9Sstevel@tonic-gate return (stat); 8307c478bd9Sstevel@tonic-gate } 831