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 51592Sgirish * Common Development and Distribution License (the "License"). 61592Sgirish * 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 /* 224732Sdavemq * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <sys/types.h> 290Sstevel@tonic-gate #include <sys/async.h> 300Sstevel@tonic-gate #include <sys/sunddi.h> 310Sstevel@tonic-gate #include <sys/sunndi.h> 320Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 330Sstevel@tonic-gate #include <sys/machsystm.h> 340Sstevel@tonic-gate #include <sys/hypervisor_api.h> 350Sstevel@tonic-gate #include <sys/kstat.h> 363156Sgirish #if defined(NIAGARA_IMPL) 373156Sgirish #include <sys/niagararegs.h> 384732Sdavemq #elif defined(NIAGARA2_IMPL) || defined(VFALLS_IMPL) 393156Sgirish #include <sys/niagara2regs.h> 403156Sgirish #endif 410Sstevel@tonic-gate 421592Sgirish extern char cpu_module_name[]; 430Sstevel@tonic-gate 440Sstevel@tonic-gate /* 450Sstevel@tonic-gate * Data structure used to build array of event-names and pcr-mask values 460Sstevel@tonic-gate */ 470Sstevel@tonic-gate typedef struct ni_kev_mask { 480Sstevel@tonic-gate char *event_name; 490Sstevel@tonic-gate uint64_t pcr_mask; 500Sstevel@tonic-gate } ni_kev_mask_t; 510Sstevel@tonic-gate 520Sstevel@tonic-gate /* 530Sstevel@tonic-gate * Kstat data structure for DRAM and JBUS performance counters 540Sstevel@tonic-gate * 550Sstevel@tonic-gate * Note that these performance counters are only 31 bits wide. Since 560Sstevel@tonic-gate * the "busstat" command assumes a 32-bit counter, we emulate a 32-bit 570Sstevel@tonic-gate * counter by detecting overflow on read of these performance counters 580Sstevel@tonic-gate * and using the least significant bit of the overflow count as the 590Sstevel@tonic-gate * most significant bit (i.e. bit# 31) of the DRAM and JBUS performance 600Sstevel@tonic-gate * counters. 610Sstevel@tonic-gate */ 621592Sgirish #define NUM_OF_PICS 2 631592Sgirish 640Sstevel@tonic-gate typedef struct ni_ksinfo { 650Sstevel@tonic-gate uint8_t pic_no_evs; /* number of events */ 660Sstevel@tonic-gate uint8_t pic_sel_shift[NUM_OF_PICS]; 670Sstevel@tonic-gate uint8_t pic_shift[NUM_OF_PICS]; 680Sstevel@tonic-gate uint64_t pic_mask[NUM_OF_PICS]; 690Sstevel@tonic-gate kstat_t *pic_name_ksp[NUM_OF_PICS]; 700Sstevel@tonic-gate kstat_t *cntr_ksp; 71*5146Ssvemuri uint32_t pic_reg[NUM_OF_PICS]; 720Sstevel@tonic-gate uint32_t pcr_reg; 730Sstevel@tonic-gate uint32_t pic_overflow[NUM_OF_PICS]; /* overflow count */ 740Sstevel@tonic-gate uint32_t pic_last_val[NUM_OF_PICS]; /* last PIC value */ 750Sstevel@tonic-gate } ni_ksinfo_t; 760Sstevel@tonic-gate 770Sstevel@tonic-gate static ni_ksinfo_t *ni_dram_kstats[NIAGARA_DRAM_BANKS]; 783156Sgirish 793156Sgirish #if defined(NIAGARA_IMPL) 800Sstevel@tonic-gate static ni_ksinfo_t *ni_jbus_kstat; 813156Sgirish #endif 820Sstevel@tonic-gate 830Sstevel@tonic-gate typedef struct ni_perf_regs { 840Sstevel@tonic-gate uint32_t pcr_reg; 850Sstevel@tonic-gate uint32_t pic_reg; 860Sstevel@tonic-gate } ni_perf_regs_t; 870Sstevel@tonic-gate 880Sstevel@tonic-gate static ni_perf_regs_t dram_perf_regs[] = { 890Sstevel@tonic-gate {HV_NIAGARA_DRAM_CTL0, HV_NIAGARA_DRAM_COUNT0}, 900Sstevel@tonic-gate {HV_NIAGARA_DRAM_CTL1, HV_NIAGARA_DRAM_COUNT1}, 910Sstevel@tonic-gate {HV_NIAGARA_DRAM_CTL2, HV_NIAGARA_DRAM_COUNT2}, 920Sstevel@tonic-gate {HV_NIAGARA_DRAM_CTL3, HV_NIAGARA_DRAM_COUNT3}, 93*5146Ssvemuri #ifdef VFALLS_IMPL 94*5146Ssvemuri {HV_NIAGARA_DRAM_CTL4, HV_NIAGARA_DRAM_COUNT4}, 95*5146Ssvemuri {HV_NIAGARA_DRAM_CTL5, HV_NIAGARA_DRAM_COUNT5}, 96*5146Ssvemuri {HV_NIAGARA_DRAM_CTL6, HV_NIAGARA_DRAM_COUNT6}, 97*5146Ssvemuri {HV_NIAGARA_DRAM_CTL7, HV_NIAGARA_DRAM_COUNT7} 98*5146Ssvemuri #endif 990Sstevel@tonic-gate }; 1000Sstevel@tonic-gate 101*5146Ssvemuri #ifdef VFALLS_IMPL 102*5146Ssvemuri /* 103*5146Ssvemuri * Kstat data structure for Zambezi performance counters 104*5146Ssvemuri * These performance counters are 64 bits wide. 105*5146Ssvemuri */ 106*5146Ssvemuri static ni_ksinfo_t *zam_lpu_kstats[ZAMBEZI_LPU_COUNTERS]; 107*5146Ssvemuri static ni_ksinfo_t *zam_gpd_kstats[ZAMBEZI_GPD_COUNTERS]; 108*5146Ssvemuri static ni_ksinfo_t *zam_asu_kstats[ZAMBEZI_ASU_COUNTERS]; 109*5146Ssvemuri 110*5146Ssvemuri typedef struct zam_perf_regs { 111*5146Ssvemuri uint32_t pcr_reg; 112*5146Ssvemuri uint32_t pic_reg[NUM_OF_PICS]; 113*5146Ssvemuri } zam_perf_regs_t; 114*5146Ssvemuri 115*5146Ssvemuri static zam_perf_regs_t lpu_perf_regs[] = { 116*5146Ssvemuri {HV_ZAM0_LPU_A_PCR, HV_ZAM0_LPU_A_PIC0, HV_ZAM0_LPU_A_PIC1}, 117*5146Ssvemuri {HV_ZAM0_LPU_B_PCR, HV_ZAM0_LPU_B_PIC0, HV_ZAM0_LPU_B_PIC1}, 118*5146Ssvemuri {HV_ZAM0_LPU_C_PCR, HV_ZAM0_LPU_C_PIC0, HV_ZAM0_LPU_C_PIC1}, 119*5146Ssvemuri {HV_ZAM0_LPU_D_PCR, HV_ZAM0_LPU_D_PIC0, HV_ZAM0_LPU_D_PIC1}, 120*5146Ssvemuri 121*5146Ssvemuri {HV_ZAM1_LPU_A_PCR, HV_ZAM1_LPU_A_PIC0, HV_ZAM1_LPU_A_PIC1}, 122*5146Ssvemuri {HV_ZAM1_LPU_B_PCR, HV_ZAM1_LPU_B_PIC0, HV_ZAM1_LPU_B_PIC1}, 123*5146Ssvemuri {HV_ZAM1_LPU_C_PCR, HV_ZAM1_LPU_C_PIC0, HV_ZAM1_LPU_C_PIC1}, 124*5146Ssvemuri {HV_ZAM1_LPU_D_PCR, HV_ZAM1_LPU_D_PIC0, HV_ZAM1_LPU_D_PIC1}, 125*5146Ssvemuri 126*5146Ssvemuri {HV_ZAM2_LPU_A_PCR, HV_ZAM2_LPU_A_PIC0, HV_ZAM2_LPU_A_PIC1}, 127*5146Ssvemuri {HV_ZAM2_LPU_B_PCR, HV_ZAM2_LPU_B_PIC0, HV_ZAM2_LPU_B_PIC1}, 128*5146Ssvemuri {HV_ZAM2_LPU_C_PCR, HV_ZAM2_LPU_C_PIC0, HV_ZAM2_LPU_C_PIC1}, 129*5146Ssvemuri {HV_ZAM2_LPU_D_PCR, HV_ZAM2_LPU_D_PIC0, HV_ZAM2_LPU_D_PIC1}, 130*5146Ssvemuri 131*5146Ssvemuri {HV_ZAM3_LPU_A_PCR, HV_ZAM3_LPU_A_PIC0, HV_ZAM3_LPU_A_PIC1}, 132*5146Ssvemuri {HV_ZAM3_LPU_B_PCR, HV_ZAM3_LPU_B_PIC0, HV_ZAM3_LPU_B_PIC1}, 133*5146Ssvemuri {HV_ZAM3_LPU_C_PCR, HV_ZAM3_LPU_C_PIC0, HV_ZAM3_LPU_C_PIC1}, 134*5146Ssvemuri {HV_ZAM3_LPU_D_PCR, HV_ZAM3_LPU_D_PIC0, HV_ZAM3_LPU_D_PIC1} 135*5146Ssvemuri }; 136*5146Ssvemuri 137*5146Ssvemuri static zam_perf_regs_t gpd_perf_regs[] = { 138*5146Ssvemuri {HV_ZAM0_GPD_PCR, HV_ZAM0_GPD_PIC0, HV_ZAM0_GPD_PIC1}, 139*5146Ssvemuri {HV_ZAM1_GPD_PCR, HV_ZAM1_GPD_PIC0, HV_ZAM1_GPD_PIC1}, 140*5146Ssvemuri {HV_ZAM2_GPD_PCR, HV_ZAM2_GPD_PIC0, HV_ZAM2_GPD_PIC1}, 141*5146Ssvemuri {HV_ZAM3_GPD_PCR, HV_ZAM3_GPD_PIC0, HV_ZAM3_GPD_PIC1} 142*5146Ssvemuri }; 143*5146Ssvemuri 144*5146Ssvemuri static zam_perf_regs_t asu_perf_regs[] = { 145*5146Ssvemuri {HV_ZAM0_ASU_PCR, HV_ZAM0_ASU_PIC0, HV_ZAM0_ASU_PIC1}, 146*5146Ssvemuri {HV_ZAM1_ASU_PCR, HV_ZAM1_ASU_PIC0, HV_ZAM1_ASU_PIC1}, 147*5146Ssvemuri {HV_ZAM2_ASU_PCR, HV_ZAM2_ASU_PIC0, HV_ZAM2_ASU_PIC1}, 148*5146Ssvemuri {HV_ZAM3_ASU_PCR, HV_ZAM3_ASU_PIC0, HV_ZAM3_ASU_PIC1} 149*5146Ssvemuri }; 150*5146Ssvemuri 151*5146Ssvemuri static int zam_cntr_kstat_update(kstat_t *, int); 152*5146Ssvemuri #endif 153*5146Ssvemuri 1540Sstevel@tonic-gate static void ni_create_name_kstat(char *, ni_ksinfo_t *, ni_kev_mask_t *); 1550Sstevel@tonic-gate static void ni_delete_name_kstat(ni_ksinfo_t *); 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate static kstat_t *ni_create_cntr_kstat(char *, int, 1580Sstevel@tonic-gate int (*update)(kstat_t *, int), void *); 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate static int ni_cntr_kstat_update(kstat_t *, int); 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate static kstat_t *ni_create_picN_kstat(char *, int, int, int, 1630Sstevel@tonic-gate ni_kev_mask_t *); 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate #ifdef DEBUG 1660Sstevel@tonic-gate static int ni_perf_debug; 1670Sstevel@tonic-gate #endif 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate /* 1704732Sdavemq * Niagara, Niagara2 and VFalls DRAM Performance Events 1710Sstevel@tonic-gate */ 1720Sstevel@tonic-gate static ni_kev_mask_t 1730Sstevel@tonic-gate niagara_dram_events[] = { 1740Sstevel@tonic-gate {"mem_reads", 0x0}, 1750Sstevel@tonic-gate {"mem_writes", 0x1}, 1760Sstevel@tonic-gate {"mem_read_write", 0x2}, 1770Sstevel@tonic-gate {"bank_busy_stalls", 0x3}, 1780Sstevel@tonic-gate {"rd_queue_latency", 0x4}, 1790Sstevel@tonic-gate {"wr_queue_latency", 0x5}, 1800Sstevel@tonic-gate {"rw_queue_latency", 0x6}, 1810Sstevel@tonic-gate {"wb_buf_hits", 0x7}, 182*5146Ssvemuri {"clear_pic", 0xf} 1830Sstevel@tonic-gate }; 1840Sstevel@tonic-gate 185*5146Ssvemuri #if defined(VFALLS_IMPL) 186*5146Ssvemuri /* 187*5146Ssvemuri * Zambezi Performance Events 188*5146Ssvemuri */ 189*5146Ssvemuri static ni_kev_mask_t 190*5146Ssvemuri zam_lpu_perf_events[] = { 191*5146Ssvemuri {"none", 0x0}, 192*5146Ssvemuri {"clock_cycles", 0x1}, 193*5146Ssvemuri {"cycles_c2c_portX", 0x2}, 194*5146Ssvemuri {"cycles_mem_portX", 0x3}, 195*5146Ssvemuri {"cycles_WB_portX", 0x4}, 196*5146Ssvemuri {"cycles_NC_portX", 0x5}, 197*5146Ssvemuri {"cycles_c2c_portY", 0x6}, 198*5146Ssvemuri {"cycles_mem_portY", 0x7}, 199*5146Ssvemuri {"cycles_WB_portY", 0x8}, 200*5146Ssvemuri {"cycles_NC_portY", 0x9}, 201*5146Ssvemuri {"cycles_c2c_portZ", 0xa}, 202*5146Ssvemuri {"cycles_mem_portZ", 0xb}, 203*5146Ssvemuri {"cycles_WB_portZ", 0xc}, 204*5146Ssvemuri {"cycles_NC_portZ", 0xd}, 205*5146Ssvemuri {"cycles_TID_WB", 0xe}, 206*5146Ssvemuri {"cycles_TID_INV", 0xf}, 207*5146Ssvemuri {"cycles_TID_RTD", 0x10}, 208*5146Ssvemuri {"cycles_TID_RTO", 0x11}, 209*5146Ssvemuri {"cycles_TID_RTS", 0x12}, 210*5146Ssvemuri {"cycles_IO_WRM", 0x13}, 211*5146Ssvemuri {"cycles_IO_RD", 0x14}, 212*5146Ssvemuri {"cycles_WB_egress", 0x15}, 213*5146Ssvemuri {"cycles_INV_egress", 0x16}, 214*5146Ssvemuri {"cycles_RTO_egress", 0x17}, 215*5146Ssvemuri {"cycles_RTD_egress", 0x18}, 216*5146Ssvemuri {"cycles_RTS_egress", 0x19}, 217*5146Ssvemuri {"cycles_no_WB", 0x1a}, 218*5146Ssvemuri {"cycles_no_read/inv", 0x1b}, 219*5146Ssvemuri {"cycles_HIT_M", 0x1c}, 220*5146Ssvemuri {"cycles_HIT_O", 0x1d}, 221*5146Ssvemuri {"cycles_HIT_S", 0x1e}, 222*5146Ssvemuri {"cycles_WB_HIT", 0x1f}, 223*5146Ssvemuri {"cycles_MISS", 0x20}, 224*5146Ssvemuri {"cycles_READ_or_INV", 0x21}, 225*5146Ssvemuri {"cycles_WB", 0x22}, 226*5146Ssvemuri {"cycles_NDR", 0x23}, 227*5146Ssvemuri {"cycles_cache_miss", 0x24}, 228*5146Ssvemuri {"cycles_cache_hit", 0x25}, 229*5146Ssvemuri {"cycles_CRC_errors", 0x26}, 230*5146Ssvemuri {"cycles_replys_sent", 0x27}, 231*5146Ssvemuri {"cycles_replys_recev", 0x28}, 232*5146Ssvemuri {"cycles_link_retrain", 0x29}, 233*5146Ssvemuri {"clear_pic", 0xff} 234*5146Ssvemuri }; 235*5146Ssvemuri 236*5146Ssvemuri static ni_kev_mask_t 237*5146Ssvemuri zam_gpd_perf_events[] = { 238*5146Ssvemuri {"none", 0x0}, 239*5146Ssvemuri {"clock_cycles", 0x1}, 240*5146Ssvemuri {"clear_pic", 0xf} 241*5146Ssvemuri }; 242*5146Ssvemuri 243*5146Ssvemuri static ni_kev_mask_t 244*5146Ssvemuri zam_asu_perf_events[] = { 245*5146Ssvemuri {"none", 0x0}, 246*5146Ssvemuri {"clock_cycles", 0x1}, 247*5146Ssvemuri {"asu_in_pck", 0x2}, 248*5146Ssvemuri {"asu_out_pck", 0x3}, 249*5146Ssvemuri {"asu_CAM_hit", 0x4}, 250*5146Ssvemuri {"asu_wakeup", 0x5}, 251*5146Ssvemuri {"clear_pic", 0xf} 252*5146Ssvemuri }; 253*5146Ssvemuri #endif 2540Sstevel@tonic-gate 2553156Sgirish #if defined(NIAGARA_IMPL) 2560Sstevel@tonic-gate /* 2570Sstevel@tonic-gate * Niagara JBUS Performance Events 2580Sstevel@tonic-gate */ 2590Sstevel@tonic-gate static ni_kev_mask_t 2600Sstevel@tonic-gate niagara_jbus_events[] = { 2610Sstevel@tonic-gate {"jbus_cycles", 0x1}, 2620Sstevel@tonic-gate {"dma_reads", 0x2}, 2630Sstevel@tonic-gate {"dma_read_latency", 0x3}, 2640Sstevel@tonic-gate {"dma_writes", 0x4}, 2650Sstevel@tonic-gate {"dma_write8", 0x5}, 2660Sstevel@tonic-gate {"ordering_waits", 0x6}, 2670Sstevel@tonic-gate {"pio_reads", 0x8}, 2680Sstevel@tonic-gate {"pio_read_latency", 0x9}, 2690Sstevel@tonic-gate {"aok_dok_off_cycles", 0xc}, 2700Sstevel@tonic-gate {"aok_off_cycles", 0xd}, 2710Sstevel@tonic-gate {"dok_off_cycles", 0xe}, 2720Sstevel@tonic-gate {"clear_pic", 0xf} 2730Sstevel@tonic-gate }; 2743156Sgirish #endif 2750Sstevel@tonic-gate 2760Sstevel@tonic-gate /* 277*5146Ssvemuri * Create the picN kstats for DRAM, JBUS and Zambezi events 2780Sstevel@tonic-gate */ 2790Sstevel@tonic-gate void 2800Sstevel@tonic-gate niagara_kstat_init() 2810Sstevel@tonic-gate { 2820Sstevel@tonic-gate int i; 2830Sstevel@tonic-gate ni_ksinfo_t *ksinfop; 284*5146Ssvemuri uint64_t pcr; 285*5146Ssvemuri uint64_t stat; 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate #ifdef DEBUG 2880Sstevel@tonic-gate if (ni_perf_debug) 2890Sstevel@tonic-gate printf("ni_kstat_init called\n"); 2900Sstevel@tonic-gate #endif 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate /* 2930Sstevel@tonic-gate * Create DRAM perf events kstat 2940Sstevel@tonic-gate */ 2950Sstevel@tonic-gate for (i = 0; i < NIAGARA_DRAM_BANKS; i++) { 2964732Sdavemq #ifdef VFALLS_IMPL 2974732Sdavemq /* check if this dram instance is enabled in the HW */ 298*5146Ssvemuri stat = hv_niagara_getperf(dram_perf_regs[i].pcr_reg, &pcr); 299*5146Ssvemuri if ((stat != H_EINVAL) && (stat != H_ENOTSUPPORTED)) { 3004732Sdavemq #endif 3014732Sdavemq ksinfop = (ni_ksinfo_t *)kmem_zalloc( 3024732Sdavemq sizeof (ni_ksinfo_t), KM_NOSLEEP); 3030Sstevel@tonic-gate 3044732Sdavemq if (ksinfop == NULL) { 3054732Sdavemq cmn_err(CE_WARN, 3064732Sdavemq "%s: no space for dram kstat\n", 3074732Sdavemq cpu_module_name); 3084732Sdavemq break; 3094732Sdavemq } 3104732Sdavemq ksinfop->pic_no_evs = 3114732Sdavemq sizeof (niagara_dram_events) / 3124732Sdavemq sizeof (ni_kev_mask_t); 3134732Sdavemq ksinfop->pic_sel_shift[0] = NIAGARA_DRAM_PIC0_SEL_SHIFT; 3144732Sdavemq ksinfop->pic_shift[0] = NIAGARA_DRAM_PIC0_SHIFT; 3154732Sdavemq ksinfop->pic_mask[0] = NIAGARA_DRAM_PIC0_MASK; 3164732Sdavemq ksinfop->pic_sel_shift[1] = NIAGARA_DRAM_PIC1_SEL_SHIFT; 3174732Sdavemq ksinfop->pic_shift[1] = NIAGARA_DRAM_PIC1_SHIFT; 3184732Sdavemq ksinfop->pic_mask[1] = NIAGARA_DRAM_PIC1_MASK; 319*5146Ssvemuri ksinfop->pic_reg[0] = dram_perf_regs[i].pic_reg; 3204732Sdavemq ksinfop->pcr_reg = dram_perf_regs[i].pcr_reg; 3214732Sdavemq ni_dram_kstats[i] = ksinfop; 3220Sstevel@tonic-gate 3234732Sdavemq /* create basic pic event/mask pair (only once) */ 3244732Sdavemq if (i == 0) 3254732Sdavemq ni_create_name_kstat("dram", ksinfop, 3260Sstevel@tonic-gate niagara_dram_events); 3270Sstevel@tonic-gate 3284732Sdavemq /* create counter kstats */ 3294732Sdavemq ni_dram_kstats[i]->cntr_ksp = ni_create_cntr_kstat( 3304732Sdavemq "dram", i, ni_cntr_kstat_update, ksinfop); 3314732Sdavemq #ifdef VFALLS_IMPL 3324732Sdavemq } 3334732Sdavemq #endif 3340Sstevel@tonic-gate } 3350Sstevel@tonic-gate 336*5146Ssvemuri #ifdef VFALLS_IMPL 337*5146Ssvemuri /* 338*5146Ssvemuri * Create Zambezi LPU perf events kstat 339*5146Ssvemuri */ 340*5146Ssvemuri for (i = 0; i < ZAMBEZI_LPU_COUNTERS; i++) { 341*5146Ssvemuri /* check if this Zambezi LPU instance is enabled in the HW */ 342*5146Ssvemuri stat = hv_niagara_getperf(lpu_perf_regs[i].pcr_reg, &pcr); 343*5146Ssvemuri if ((stat != H_EINVAL) && (stat != H_ENOTSUPPORTED)) { 344*5146Ssvemuri ksinfop = (ni_ksinfo_t *)kmem_zalloc( 345*5146Ssvemuri sizeof (ni_ksinfo_t), KM_NOSLEEP); 346*5146Ssvemuri 347*5146Ssvemuri if (ksinfop == NULL) { 348*5146Ssvemuri cmn_err(CE_WARN, 349*5146Ssvemuri "%s: no space for zambezi lpu kstat\n", 350*5146Ssvemuri cpu_module_name); 351*5146Ssvemuri break; 352*5146Ssvemuri } 353*5146Ssvemuri ksinfop->pic_no_evs = 354*5146Ssvemuri sizeof (zam_lpu_perf_events) / 355*5146Ssvemuri sizeof (ni_kev_mask_t); 356*5146Ssvemuri ksinfop->pic_sel_shift[0] = ZAMBEZI_PIC0_SEL_SHIFT; 357*5146Ssvemuri ksinfop->pic_reg[0] = lpu_perf_regs[i].pic_reg[0]; 358*5146Ssvemuri ksinfop->pic_sel_shift[1] = ZAMBEZI_PIC1_SEL_SHIFT; 359*5146Ssvemuri ksinfop->pic_reg[1] = lpu_perf_regs[i].pic_reg[1]; 360*5146Ssvemuri ksinfop->pcr_reg = lpu_perf_regs[i].pcr_reg; 361*5146Ssvemuri zam_lpu_kstats[i] = ksinfop; 362*5146Ssvemuri 363*5146Ssvemuri /* create basic pic event/mask pair (only once) */ 364*5146Ssvemuri if (i == 0) 365*5146Ssvemuri ni_create_name_kstat("lpu", ksinfop, 366*5146Ssvemuri zam_lpu_perf_events); 367*5146Ssvemuri 368*5146Ssvemuri /* create counter kstats */ 369*5146Ssvemuri zam_lpu_kstats[i]->cntr_ksp = ni_create_cntr_kstat( 370*5146Ssvemuri "lpu", i, zam_cntr_kstat_update, ksinfop); 371*5146Ssvemuri } 372*5146Ssvemuri } 373*5146Ssvemuri /* 374*5146Ssvemuri * Create Zambezi GPD perf events kstat 375*5146Ssvemuri */ 376*5146Ssvemuri for (i = 0; i < ZAMBEZI_GPD_COUNTERS; i++) { 377*5146Ssvemuri /* check if this Zambezi GPD instance is enabled in the HW */ 378*5146Ssvemuri stat = hv_niagara_getperf(gpd_perf_regs[i].pcr_reg, &pcr); 379*5146Ssvemuri if ((stat != H_EINVAL) && (stat != H_ENOTSUPPORTED)) { 380*5146Ssvemuri ksinfop = (ni_ksinfo_t *)kmem_zalloc( 381*5146Ssvemuri sizeof (ni_ksinfo_t), KM_NOSLEEP); 382*5146Ssvemuri 383*5146Ssvemuri if (ksinfop == NULL) { 384*5146Ssvemuri cmn_err(CE_WARN, 385*5146Ssvemuri "%s: no space for zambezi gpd kstat\n", 386*5146Ssvemuri cpu_module_name); 387*5146Ssvemuri break; 388*5146Ssvemuri } 389*5146Ssvemuri ksinfop->pic_no_evs = 390*5146Ssvemuri sizeof (zam_gpd_perf_events) / 391*5146Ssvemuri sizeof (ni_kev_mask_t); 392*5146Ssvemuri ksinfop->pic_sel_shift[0] = ZAMBEZI_PIC0_SEL_SHIFT; 393*5146Ssvemuri ksinfop->pic_reg[0] = gpd_perf_regs[i].pic_reg[0]; 394*5146Ssvemuri ksinfop->pic_sel_shift[1] = ZAMBEZI_PIC1_SEL_SHIFT; 395*5146Ssvemuri ksinfop->pic_reg[1] = gpd_perf_regs[i].pic_reg[1]; 396*5146Ssvemuri ksinfop->pcr_reg = gpd_perf_regs[i].pcr_reg; 397*5146Ssvemuri zam_gpd_kstats[i] = ksinfop; 398*5146Ssvemuri 399*5146Ssvemuri /* create basic pic event/mask pair (only once) */ 400*5146Ssvemuri if (i == 0) 401*5146Ssvemuri ni_create_name_kstat("gpd", ksinfop, 402*5146Ssvemuri zam_gpd_perf_events); 403*5146Ssvemuri 404*5146Ssvemuri /* create counter kstats */ 405*5146Ssvemuri zam_lpu_kstats[i]->cntr_ksp = ni_create_cntr_kstat( 406*5146Ssvemuri "gpd", i, zam_cntr_kstat_update, ksinfop); 407*5146Ssvemuri } 408*5146Ssvemuri } 409*5146Ssvemuri /* 410*5146Ssvemuri * Create Zambezi ASU perf events kstat 411*5146Ssvemuri */ 412*5146Ssvemuri for (i = 0; i < ZAMBEZI_ASU_COUNTERS; i++) { 413*5146Ssvemuri /* check if this Zambezi ASU instance is enabled in the HW */ 414*5146Ssvemuri stat = hv_niagara_getperf(asu_perf_regs[i].pcr_reg, &pcr); 415*5146Ssvemuri if ((stat != H_EINVAL) && (stat != H_ENOTSUPPORTED)) { 416*5146Ssvemuri ksinfop = (ni_ksinfo_t *)kmem_zalloc( 417*5146Ssvemuri sizeof (ni_ksinfo_t), KM_NOSLEEP); 418*5146Ssvemuri 419*5146Ssvemuri if (ksinfop == NULL) { 420*5146Ssvemuri cmn_err(CE_WARN, 421*5146Ssvemuri "%s: no space for zambezi asu kstat\n", 422*5146Ssvemuri cpu_module_name); 423*5146Ssvemuri break; 424*5146Ssvemuri } 425*5146Ssvemuri ksinfop->pic_no_evs = 426*5146Ssvemuri sizeof (zam_asu_perf_events) / 427*5146Ssvemuri sizeof (ni_kev_mask_t); 428*5146Ssvemuri ksinfop->pic_sel_shift[0] = ZAMBEZI_PIC0_SEL_SHIFT; 429*5146Ssvemuri ksinfop->pic_reg[0] = asu_perf_regs[i].pic_reg[0]; 430*5146Ssvemuri ksinfop->pic_sel_shift[1] = ZAMBEZI_PIC1_SEL_SHIFT; 431*5146Ssvemuri ksinfop->pic_reg[1] = asu_perf_regs[i].pic_reg[1]; 432*5146Ssvemuri ksinfop->pcr_reg = asu_perf_regs[i].pcr_reg; 433*5146Ssvemuri zam_asu_kstats[i] = ksinfop; 434*5146Ssvemuri 435*5146Ssvemuri /* create basic pic event/mask pair (only once) */ 436*5146Ssvemuri if (i == 0) 437*5146Ssvemuri ni_create_name_kstat("asu", ksinfop, 438*5146Ssvemuri zam_asu_perf_events); 439*5146Ssvemuri 440*5146Ssvemuri /* create counter kstats */ 441*5146Ssvemuri zam_lpu_kstats[i]->cntr_ksp = ni_create_cntr_kstat( 442*5146Ssvemuri "asu", i, zam_cntr_kstat_update, ksinfop); 443*5146Ssvemuri } 444*5146Ssvemuri } 445*5146Ssvemuri #endif 446*5146Ssvemuri 4473156Sgirish #if defined(NIAGARA_IMPL) 4480Sstevel@tonic-gate /* 4490Sstevel@tonic-gate * Create JBUS perf events kstat 4500Sstevel@tonic-gate */ 4510Sstevel@tonic-gate ni_jbus_kstat = (ni_ksinfo_t *)kmem_alloc(sizeof (ni_ksinfo_t), 4524732Sdavemq KM_NOSLEEP); 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate if (ni_jbus_kstat == NULL) { 4550Sstevel@tonic-gate cmn_err(CE_WARN, "%s: no space for niagara jbus kstat\n", 4561592Sgirish cpu_module_name); 4570Sstevel@tonic-gate } else { 4580Sstevel@tonic-gate ni_jbus_kstat->pic_no_evs = 4594732Sdavemq sizeof (niagara_jbus_events) / sizeof (ni_kev_mask_t); 4600Sstevel@tonic-gate ni_jbus_kstat->pic_sel_shift[0] = NIAGARA_JBUS_PIC0_SEL_SHIFT; 4610Sstevel@tonic-gate ni_jbus_kstat->pic_shift[0] = NIAGARA_JBUS_PIC0_SHIFT; 4620Sstevel@tonic-gate ni_jbus_kstat->pic_mask[0] = NIAGARA_JBUS_PIC0_MASK; 4630Sstevel@tonic-gate ni_jbus_kstat->pic_sel_shift[1] = NIAGARA_JBUS_PIC1_SEL_SHIFT; 4640Sstevel@tonic-gate ni_jbus_kstat->pic_shift[1] = NIAGARA_JBUS_PIC1_SHIFT; 4650Sstevel@tonic-gate ni_jbus_kstat->pic_mask[1] = NIAGARA_JBUS_PIC1_MASK; 466*5146Ssvemuri ni_jbus_kstat->pic_reg[0] = HV_NIAGARA_JBUS_COUNT; 4670Sstevel@tonic-gate ni_jbus_kstat->pcr_reg = HV_NIAGARA_JBUS_CTL; 4680Sstevel@tonic-gate ni_create_name_kstat("jbus", ni_jbus_kstat, 4690Sstevel@tonic-gate niagara_jbus_events); 4700Sstevel@tonic-gate ni_jbus_kstat->cntr_ksp = ni_create_cntr_kstat("jbus", 0, 4710Sstevel@tonic-gate ni_cntr_kstat_update, ni_jbus_kstat); 4720Sstevel@tonic-gate } 4733156Sgirish #endif 4740Sstevel@tonic-gate } 4750Sstevel@tonic-gate 4760Sstevel@tonic-gate void 4770Sstevel@tonic-gate niagara_kstat_fini() 4780Sstevel@tonic-gate { 4790Sstevel@tonic-gate int i; 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate #ifdef DEBUG 4820Sstevel@tonic-gate if (ni_perf_debug) 4830Sstevel@tonic-gate printf("ni_kstat_fini called\n"); 4840Sstevel@tonic-gate #endif 485*5146Ssvemuri 4860Sstevel@tonic-gate for (i = 0; i < NIAGARA_DRAM_BANKS; i++) { 4870Sstevel@tonic-gate if (ni_dram_kstats[i] != NULL) { 4880Sstevel@tonic-gate ni_delete_name_kstat(ni_dram_kstats[i]); 4890Sstevel@tonic-gate if (ni_dram_kstats[i]->cntr_ksp != NULL) 4900Sstevel@tonic-gate kstat_delete(ni_dram_kstats[i]->cntr_ksp); 4910Sstevel@tonic-gate kmem_free(ni_dram_kstats[i], sizeof (ni_ksinfo_t)); 4920Sstevel@tonic-gate ni_dram_kstats[i] = NULL; 4930Sstevel@tonic-gate } 4940Sstevel@tonic-gate } 4950Sstevel@tonic-gate 496*5146Ssvemuri #if defined(VFALLS_IMPL) 497*5146Ssvemuri for (i = 0; i < ZAMBEZI_LPU_COUNTERS; i++) { 498*5146Ssvemuri if (zam_lpu_kstats[i] != NULL) { 499*5146Ssvemuri ni_delete_name_kstat(zam_lpu_kstats[i]); 500*5146Ssvemuri if (zam_lpu_kstats[i]->cntr_ksp != NULL) 501*5146Ssvemuri kstat_delete(zam_lpu_kstats[i]->cntr_ksp); 502*5146Ssvemuri kmem_free(zam_lpu_kstats[i], sizeof (ni_ksinfo_t)); 503*5146Ssvemuri zam_lpu_kstats[i] = NULL; 504*5146Ssvemuri } 505*5146Ssvemuri } 506*5146Ssvemuri 507*5146Ssvemuri for (i = 0; i < ZAMBEZI_GPD_COUNTERS; i++) { 508*5146Ssvemuri if (zam_gpd_kstats[i] != NULL) { 509*5146Ssvemuri ni_delete_name_kstat(zam_gpd_kstats[i]); 510*5146Ssvemuri if (zam_gpd_kstats[i]->cntr_ksp != NULL) 511*5146Ssvemuri kstat_delete(zam_gpd_kstats[i]->cntr_ksp); 512*5146Ssvemuri kmem_free(zam_gpd_kstats[i], sizeof (ni_ksinfo_t)); 513*5146Ssvemuri zam_gpd_kstats[i] = NULL; 514*5146Ssvemuri } 515*5146Ssvemuri } 516*5146Ssvemuri 517*5146Ssvemuri for (i = 0; i < ZAMBEZI_ASU_COUNTERS; i++) { 518*5146Ssvemuri if (zam_asu_kstats[i] != NULL) { 519*5146Ssvemuri ni_delete_name_kstat(zam_asu_kstats[i]); 520*5146Ssvemuri if (zam_asu_kstats[i]->cntr_ksp != NULL) 521*5146Ssvemuri kstat_delete(zam_asu_kstats[i]->cntr_ksp); 522*5146Ssvemuri kmem_free(zam_asu_kstats[i], sizeof (ni_ksinfo_t)); 523*5146Ssvemuri zam_asu_kstats[i] = NULL; 524*5146Ssvemuri } 525*5146Ssvemuri } 526*5146Ssvemuri #endif 527*5146Ssvemuri 5283156Sgirish #if defined(NIAGARA_IMPL) 5290Sstevel@tonic-gate if (ni_jbus_kstat != NULL) { 5300Sstevel@tonic-gate ni_delete_name_kstat(ni_jbus_kstat); 5310Sstevel@tonic-gate if (ni_jbus_kstat->cntr_ksp != NULL) 5320Sstevel@tonic-gate kstat_delete(ni_jbus_kstat->cntr_ksp); 5330Sstevel@tonic-gate kmem_free(ni_jbus_kstat, sizeof (ni_ksinfo_t)); 5340Sstevel@tonic-gate ni_jbus_kstat = NULL; 5350Sstevel@tonic-gate } 5363156Sgirish #endif 5370Sstevel@tonic-gate } 5380Sstevel@tonic-gate 5390Sstevel@tonic-gate static void 5400Sstevel@tonic-gate ni_create_name_kstat(char *name, ni_ksinfo_t *pp, ni_kev_mask_t *ev) 5410Sstevel@tonic-gate { 5420Sstevel@tonic-gate int i; 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate #ifdef DEBUG 5450Sstevel@tonic-gate if (ni_perf_debug > 1) 5460Sstevel@tonic-gate printf("ni_create_name_kstat: name: %s\n", name); 5470Sstevel@tonic-gate #endif 5480Sstevel@tonic-gate for (i = 0; i < NUM_OF_PICS; i++) { 5490Sstevel@tonic-gate pp->pic_name_ksp[i] = ni_create_picN_kstat(name, 5504732Sdavemq i, pp->pic_sel_shift[i], pp->pic_no_evs, ev); 5510Sstevel@tonic-gate 5520Sstevel@tonic-gate if (pp->pic_name_ksp[i] == NULL) { 5530Sstevel@tonic-gate cmn_err(CE_WARN, "%s: unable to create name kstat", 5541592Sgirish cpu_module_name); 5550Sstevel@tonic-gate } 5560Sstevel@tonic-gate } 5570Sstevel@tonic-gate } 5580Sstevel@tonic-gate 5590Sstevel@tonic-gate static void 5600Sstevel@tonic-gate ni_delete_name_kstat(ni_ksinfo_t *pp) 5610Sstevel@tonic-gate { 5620Sstevel@tonic-gate int i; 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate if (pp != NULL) { 5650Sstevel@tonic-gate for (i = 0; i < NUM_OF_PICS; i++) { 5660Sstevel@tonic-gate if (pp->pic_name_ksp[i] != NULL) 5670Sstevel@tonic-gate kstat_delete(pp->pic_name_ksp[i]); 5680Sstevel@tonic-gate } 5690Sstevel@tonic-gate } 5700Sstevel@tonic-gate } 5710Sstevel@tonic-gate 5720Sstevel@tonic-gate /* 5730Sstevel@tonic-gate * Create the picN kstat. Returns a pointer to the 5740Sstevel@tonic-gate * kstat which the driver must store to allow it 5750Sstevel@tonic-gate * to be deleted when necessary. 5760Sstevel@tonic-gate */ 5770Sstevel@tonic-gate static kstat_t * 5780Sstevel@tonic-gate ni_create_picN_kstat(char *mod_name, int pic, int pic_sel_shift, 5790Sstevel@tonic-gate int num_ev, ni_kev_mask_t *ev_array) 5800Sstevel@tonic-gate { 5810Sstevel@tonic-gate struct kstat_named *pic_named_data; 5820Sstevel@tonic-gate int inst = 0; 5830Sstevel@tonic-gate int event; 5840Sstevel@tonic-gate char pic_name[30]; 5850Sstevel@tonic-gate kstat_t *picN_ksp = NULL; 5860Sstevel@tonic-gate 5870Sstevel@tonic-gate (void) sprintf(pic_name, "pic%d", pic); 5880Sstevel@tonic-gate if ((picN_ksp = kstat_create(mod_name, inst, pic_name, 5890Sstevel@tonic-gate "bus", KSTAT_TYPE_NAMED, num_ev, NULL)) == NULL) { 5900Sstevel@tonic-gate cmn_err(CE_WARN, "%s %s : kstat create failed", 5914732Sdavemq mod_name, pic_name); 5920Sstevel@tonic-gate 5930Sstevel@tonic-gate /* 5940Sstevel@tonic-gate * It is up to the calling function to delete any kstats 5950Sstevel@tonic-gate * that may have been created already. We just 5960Sstevel@tonic-gate * return NULL to indicate an error has occured. 5970Sstevel@tonic-gate */ 5980Sstevel@tonic-gate return (NULL); 5990Sstevel@tonic-gate } 6000Sstevel@tonic-gate 6010Sstevel@tonic-gate pic_named_data = (struct kstat_named *) 6020Sstevel@tonic-gate picN_ksp->ks_data; 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate /* 6050Sstevel@tonic-gate * Write event names and their associated pcr masks. The 6060Sstevel@tonic-gate * last entry in the array (clear_pic) is added seperately 6070Sstevel@tonic-gate * below as the pic value must be inverted. 6080Sstevel@tonic-gate */ 6090Sstevel@tonic-gate for (event = 0; event < num_ev - 1; event++) { 6100Sstevel@tonic-gate pic_named_data[event].value.ui64 = 6114732Sdavemq (ev_array[event].pcr_mask << pic_sel_shift); 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate kstat_named_init(&pic_named_data[event], 6144732Sdavemq ev_array[event].event_name, 6154732Sdavemq KSTAT_DATA_UINT64); 6160Sstevel@tonic-gate } 6170Sstevel@tonic-gate 6180Sstevel@tonic-gate /* 6190Sstevel@tonic-gate * add the clear_pic entry. 6200Sstevel@tonic-gate */ 6210Sstevel@tonic-gate pic_named_data[event].value.ui64 = 6224732Sdavemq (uint64_t)~(ev_array[event].pcr_mask << pic_sel_shift); 6230Sstevel@tonic-gate 6240Sstevel@tonic-gate kstat_named_init(&pic_named_data[event], ev_array[event].event_name, 6250Sstevel@tonic-gate KSTAT_DATA_UINT64); 6260Sstevel@tonic-gate 6270Sstevel@tonic-gate kstat_install(picN_ksp); 6280Sstevel@tonic-gate 6290Sstevel@tonic-gate return (picN_ksp); 6300Sstevel@tonic-gate } 6310Sstevel@tonic-gate 6320Sstevel@tonic-gate /* 6330Sstevel@tonic-gate * Create the "counters" kstat. 6340Sstevel@tonic-gate */ 6350Sstevel@tonic-gate static kstat_t * 6360Sstevel@tonic-gate ni_create_cntr_kstat(char *name, int instance, int (*update)(kstat_t *, int), 6370Sstevel@tonic-gate void *ksinfop) 6380Sstevel@tonic-gate { 6390Sstevel@tonic-gate struct kstat *counters_ksp; 6400Sstevel@tonic-gate struct kstat_named *counters_named_data; 6410Sstevel@tonic-gate char pic_str[10]; 6420Sstevel@tonic-gate int i; 6430Sstevel@tonic-gate int num_pics = NUM_OF_PICS; 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate #ifdef DEBUG 6460Sstevel@tonic-gate if (ni_perf_debug > 1) 6470Sstevel@tonic-gate printf("ni_create_cntr_kstat: name: %s instance: %d\n", 6480Sstevel@tonic-gate name, instance); 6490Sstevel@tonic-gate #endif 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate /* 6520Sstevel@tonic-gate * Size of kstat is num_pics + 1 as it 6530Sstevel@tonic-gate * also contains the %pcr 6540Sstevel@tonic-gate */ 6550Sstevel@tonic-gate if ((counters_ksp = kstat_create(name, instance, "counters", "bus", 6560Sstevel@tonic-gate KSTAT_TYPE_NAMED, num_pics + 1, KSTAT_FLAG_WRITABLE)) == NULL) { 6570Sstevel@tonic-gate cmn_err(CE_WARN, 6581592Sgirish "%s: kstat_create for %s%d failed", cpu_module_name, 6590Sstevel@tonic-gate name, instance); 6600Sstevel@tonic-gate return (NULL); 6610Sstevel@tonic-gate } 6620Sstevel@tonic-gate 6630Sstevel@tonic-gate counters_named_data = (struct kstat_named *)(counters_ksp->ks_data); 6640Sstevel@tonic-gate 6650Sstevel@tonic-gate /* 6660Sstevel@tonic-gate * Iinitialize the named kstats 6670Sstevel@tonic-gate */ 6680Sstevel@tonic-gate kstat_named_init(&counters_named_data[0], "pcr", KSTAT_DATA_UINT64); 6690Sstevel@tonic-gate 6700Sstevel@tonic-gate for (i = 0; i < num_pics; i++) { 6710Sstevel@tonic-gate (void) sprintf(pic_str, "pic%d", i); 6720Sstevel@tonic-gate 6730Sstevel@tonic-gate kstat_named_init(&counters_named_data[i+1], pic_str, 6740Sstevel@tonic-gate KSTAT_DATA_UINT64); 6750Sstevel@tonic-gate } 6760Sstevel@tonic-gate 6770Sstevel@tonic-gate /* 6780Sstevel@tonic-gate * Store the register offset's in the kstat's 6790Sstevel@tonic-gate * private field so that they are available 6800Sstevel@tonic-gate * to the update function. 6810Sstevel@tonic-gate */ 6820Sstevel@tonic-gate counters_ksp->ks_private = (void *)ksinfop; 6830Sstevel@tonic-gate counters_ksp->ks_update = update; 6840Sstevel@tonic-gate 6850Sstevel@tonic-gate kstat_install(counters_ksp); 6860Sstevel@tonic-gate 6870Sstevel@tonic-gate return (counters_ksp); 6880Sstevel@tonic-gate } 6890Sstevel@tonic-gate 690*5146Ssvemuri #if defined(VFALLS_IMPL) 691*5146Ssvemuri /* 692*5146Ssvemuri * zambezi kstat update function. Handles reads/writes 693*5146Ssvemuri * from/to kstat. 694*5146Ssvemuri */ 695*5146Ssvemuri static int 696*5146Ssvemuri zam_cntr_kstat_update(kstat_t *ksp, int rw) 697*5146Ssvemuri { 698*5146Ssvemuri struct kstat_named *data_p; 699*5146Ssvemuri ni_ksinfo_t *ksinfop = ksp->ks_private; 700*5146Ssvemuri uint64_t pic0, pic1, pcr; 701*5146Ssvemuri int stat = 0; 702*5146Ssvemuri uint64_t pic0_stat = 0, pic1_stat = 0, pcr_stat = 0; 703*5146Ssvemuri 704*5146Ssvemuri data_p = (struct kstat_named *)ksp->ks_data; 705*5146Ssvemuri 706*5146Ssvemuri if (rw == KSTAT_WRITE) { 707*5146Ssvemuri #ifdef DEBUG 708*5146Ssvemuri if (ni_perf_debug) 709*5146Ssvemuri printf("zam_cntr_kstat_update: wr pcr-%d: %lx\n", 710*5146Ssvemuri ksinfop->pcr_reg, data_p[0].value.ui64); 711*5146Ssvemuri #endif 712*5146Ssvemuri if (hv_niagara_setperf(ksinfop->pcr_reg, data_p[0].value.ui64)) 713*5146Ssvemuri stat = EACCES; 714*5146Ssvemuri } else { 715*5146Ssvemuri do { 716*5146Ssvemuri pic0_stat = hv_niagara_getperf(ksinfop->pic_reg[0], 717*5146Ssvemuri &pic0); 718*5146Ssvemuri } while (pic0_stat == H_EWOULDBLOCK); 719*5146Ssvemuri do { 720*5146Ssvemuri pic1_stat = hv_niagara_getperf(ksinfop->pic_reg[1], 721*5146Ssvemuri &pic1); 722*5146Ssvemuri } while (pic1_stat == H_EWOULDBLOCK); 723*5146Ssvemuri do { 724*5146Ssvemuri pcr_stat = hv_niagara_getperf(ksinfop->pcr_reg, 725*5146Ssvemuri &pcr); 726*5146Ssvemuri } while (pcr_stat == H_EWOULDBLOCK); 727*5146Ssvemuri if (pic0_stat != 0 || pic1_stat != 0 || pcr_stat != 0) 728*5146Ssvemuri stat = EACCES; 729*5146Ssvemuri else { 730*5146Ssvemuri data_p[0].value.ui64 = pcr; 731*5146Ssvemuri data_p[1].value.ui64 = pic0; 732*5146Ssvemuri data_p[2].value.ui64 = pic1; 733*5146Ssvemuri } 734*5146Ssvemuri #ifdef DEBUG 735*5146Ssvemuri if (ni_perf_debug) 736*5146Ssvemuri printf("zam_cntr_kstat_update: rd pcr%d: %lx " 737*5146Ssvemuri "pic0: %16lx pic1: %16lx\n", 738*5146Ssvemuri ksinfop->pcr_reg, pcr, 739*5146Ssvemuri data_p[1].value.ui64, data_p[2].value.ui64); 740*5146Ssvemuri #endif 741*5146Ssvemuri } 742*5146Ssvemuri 743*5146Ssvemuri return (stat); 744*5146Ssvemuri } 745*5146Ssvemuri #endif 746*5146Ssvemuri 7470Sstevel@tonic-gate /* 7480Sstevel@tonic-gate * kstat update function. Handles reads/writes 7490Sstevel@tonic-gate * from/to kstat. 7500Sstevel@tonic-gate */ 7510Sstevel@tonic-gate static int 7520Sstevel@tonic-gate ni_cntr_kstat_update(kstat_t *ksp, int rw) 7530Sstevel@tonic-gate { 7540Sstevel@tonic-gate struct kstat_named *data_p; 7550Sstevel@tonic-gate ni_ksinfo_t *ksinfop = ksp->ks_private; 7560Sstevel@tonic-gate uint64_t pic, pcr; 7570Sstevel@tonic-gate int stat = 0; 7580Sstevel@tonic-gate uint32_t pic0, pic1; 7590Sstevel@tonic-gate 7600Sstevel@tonic-gate data_p = (struct kstat_named *)ksp->ks_data; 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate if (rw == KSTAT_WRITE) { 7630Sstevel@tonic-gate #ifdef DEBUG 7640Sstevel@tonic-gate if (ni_perf_debug) 765911Siskreen printf("ni_cntr_kstat_update: wr pcr-%d: %lx\n", 7660Sstevel@tonic-gate ksinfop->pcr_reg, data_p[0].value.ui64); 7670Sstevel@tonic-gate #endif 7680Sstevel@tonic-gate if (hv_niagara_setperf(ksinfop->pcr_reg, data_p[0].value.ui64)) 7690Sstevel@tonic-gate stat = EACCES; 7700Sstevel@tonic-gate } else { 771*5146Ssvemuri if (hv_niagara_getperf(ksinfop->pic_reg[0], &pic) != 0 || 7720Sstevel@tonic-gate hv_niagara_getperf(ksinfop->pcr_reg, &pcr) != 0) 7730Sstevel@tonic-gate stat = EACCES; 7740Sstevel@tonic-gate else { 7750Sstevel@tonic-gate 7760Sstevel@tonic-gate data_p[0].value.ui64 = pcr; 7770Sstevel@tonic-gate 7780Sstevel@tonic-gate /* 7790Sstevel@tonic-gate * Generate a 32-bit PIC0 value by detecting overflow 7800Sstevel@tonic-gate */ 7810Sstevel@tonic-gate pic0 = (uint32_t)((pic >> ksinfop->pic_shift[0]) & 7820Sstevel@tonic-gate ksinfop->pic_mask[0]); 7830Sstevel@tonic-gate if (pic0 < ksinfop->pic_last_val[0]) 7840Sstevel@tonic-gate ksinfop->pic_overflow[0]++; 7850Sstevel@tonic-gate ksinfop->pic_last_val[0] = pic0; 7860Sstevel@tonic-gate pic0 += (ksinfop->pic_overflow[0] & 1) << 31; 7870Sstevel@tonic-gate data_p[1].value.ui64 = (uint64_t)pic0; 7880Sstevel@tonic-gate 7890Sstevel@tonic-gate /* 7900Sstevel@tonic-gate * Generate a 32-bit PIC1 value by detecting overflow 7910Sstevel@tonic-gate */ 7920Sstevel@tonic-gate pic1 = (uint32_t)((pic >> ksinfop->pic_shift[1]) & 7930Sstevel@tonic-gate ksinfop->pic_mask[1]); 7940Sstevel@tonic-gate if (pic1 < ksinfop->pic_last_val[1]) 7950Sstevel@tonic-gate ksinfop->pic_overflow[1]++; 7960Sstevel@tonic-gate ksinfop->pic_last_val[1] = pic1; 7970Sstevel@tonic-gate pic1 += (ksinfop->pic_overflow[1] & 1) << 31; 7980Sstevel@tonic-gate data_p[2].value.ui64 = (uint64_t)pic1; 7990Sstevel@tonic-gate } 8000Sstevel@tonic-gate #ifdef DEBUG 8010Sstevel@tonic-gate if (ni_perf_debug) 8020Sstevel@tonic-gate printf("ni_cntr_kstat_update: rd pcr%d: %lx " 8030Sstevel@tonic-gate "pic%d: %16lx pic0: %8lx pic1: %8lx\n", 804*5146Ssvemuri ksinfop->pcr_reg, pcr, ksinfop->pic_reg[0], pic, 8050Sstevel@tonic-gate data_p[1].value.ui64, data_p[2].value.ui64); 8060Sstevel@tonic-gate #endif 8070Sstevel@tonic-gate } 8080Sstevel@tonic-gate return (stat); 8090Sstevel@tonic-gate } 810