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; 715146Ssvemuri 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}, 935146Ssvemuri #ifdef VFALLS_IMPL 945146Ssvemuri {HV_NIAGARA_DRAM_CTL4, HV_NIAGARA_DRAM_COUNT4}, 955146Ssvemuri {HV_NIAGARA_DRAM_CTL5, HV_NIAGARA_DRAM_COUNT5}, 965146Ssvemuri {HV_NIAGARA_DRAM_CTL6, HV_NIAGARA_DRAM_COUNT6}, 975146Ssvemuri {HV_NIAGARA_DRAM_CTL7, HV_NIAGARA_DRAM_COUNT7} 985146Ssvemuri #endif 990Sstevel@tonic-gate }; 1000Sstevel@tonic-gate 1015146Ssvemuri #ifdef VFALLS_IMPL 1025146Ssvemuri /* 1035146Ssvemuri * Kstat data structure for Zambezi performance counters 1045146Ssvemuri * These performance counters are 64 bits wide. 1055146Ssvemuri */ 1065146Ssvemuri static ni_ksinfo_t *zam_lpu_kstats[ZAMBEZI_LPU_COUNTERS]; 1075146Ssvemuri static ni_ksinfo_t *zam_gpd_kstats[ZAMBEZI_GPD_COUNTERS]; 1085146Ssvemuri static ni_ksinfo_t *zam_asu_kstats[ZAMBEZI_ASU_COUNTERS]; 1095146Ssvemuri 1105146Ssvemuri typedef struct zam_perf_regs { 1115146Ssvemuri uint32_t pcr_reg; 1125146Ssvemuri uint32_t pic_reg[NUM_OF_PICS]; 1135146Ssvemuri } zam_perf_regs_t; 1145146Ssvemuri 1155146Ssvemuri static zam_perf_regs_t lpu_perf_regs[] = { 1165146Ssvemuri {HV_ZAM0_LPU_A_PCR, HV_ZAM0_LPU_A_PIC0, HV_ZAM0_LPU_A_PIC1}, 1175146Ssvemuri {HV_ZAM0_LPU_B_PCR, HV_ZAM0_LPU_B_PIC0, HV_ZAM0_LPU_B_PIC1}, 1185146Ssvemuri {HV_ZAM0_LPU_C_PCR, HV_ZAM0_LPU_C_PIC0, HV_ZAM0_LPU_C_PIC1}, 1195146Ssvemuri {HV_ZAM0_LPU_D_PCR, HV_ZAM0_LPU_D_PIC0, HV_ZAM0_LPU_D_PIC1}, 1205146Ssvemuri 1215146Ssvemuri {HV_ZAM1_LPU_A_PCR, HV_ZAM1_LPU_A_PIC0, HV_ZAM1_LPU_A_PIC1}, 1225146Ssvemuri {HV_ZAM1_LPU_B_PCR, HV_ZAM1_LPU_B_PIC0, HV_ZAM1_LPU_B_PIC1}, 1235146Ssvemuri {HV_ZAM1_LPU_C_PCR, HV_ZAM1_LPU_C_PIC0, HV_ZAM1_LPU_C_PIC1}, 1245146Ssvemuri {HV_ZAM1_LPU_D_PCR, HV_ZAM1_LPU_D_PIC0, HV_ZAM1_LPU_D_PIC1}, 1255146Ssvemuri 1265146Ssvemuri {HV_ZAM2_LPU_A_PCR, HV_ZAM2_LPU_A_PIC0, HV_ZAM2_LPU_A_PIC1}, 1275146Ssvemuri {HV_ZAM2_LPU_B_PCR, HV_ZAM2_LPU_B_PIC0, HV_ZAM2_LPU_B_PIC1}, 1285146Ssvemuri {HV_ZAM2_LPU_C_PCR, HV_ZAM2_LPU_C_PIC0, HV_ZAM2_LPU_C_PIC1}, 1295146Ssvemuri {HV_ZAM2_LPU_D_PCR, HV_ZAM2_LPU_D_PIC0, HV_ZAM2_LPU_D_PIC1}, 1305146Ssvemuri 1315146Ssvemuri {HV_ZAM3_LPU_A_PCR, HV_ZAM3_LPU_A_PIC0, HV_ZAM3_LPU_A_PIC1}, 1325146Ssvemuri {HV_ZAM3_LPU_B_PCR, HV_ZAM3_LPU_B_PIC0, HV_ZAM3_LPU_B_PIC1}, 1335146Ssvemuri {HV_ZAM3_LPU_C_PCR, HV_ZAM3_LPU_C_PIC0, HV_ZAM3_LPU_C_PIC1}, 1345146Ssvemuri {HV_ZAM3_LPU_D_PCR, HV_ZAM3_LPU_D_PIC0, HV_ZAM3_LPU_D_PIC1} 1355146Ssvemuri }; 1365146Ssvemuri 1375146Ssvemuri static zam_perf_regs_t gpd_perf_regs[] = { 1385146Ssvemuri {HV_ZAM0_GPD_PCR, HV_ZAM0_GPD_PIC0, HV_ZAM0_GPD_PIC1}, 1395146Ssvemuri {HV_ZAM1_GPD_PCR, HV_ZAM1_GPD_PIC0, HV_ZAM1_GPD_PIC1}, 1405146Ssvemuri {HV_ZAM2_GPD_PCR, HV_ZAM2_GPD_PIC0, HV_ZAM2_GPD_PIC1}, 1415146Ssvemuri {HV_ZAM3_GPD_PCR, HV_ZAM3_GPD_PIC0, HV_ZAM3_GPD_PIC1} 1425146Ssvemuri }; 1435146Ssvemuri 1445146Ssvemuri static zam_perf_regs_t asu_perf_regs[] = { 1455146Ssvemuri {HV_ZAM0_ASU_PCR, HV_ZAM0_ASU_PIC0, HV_ZAM0_ASU_PIC1}, 1465146Ssvemuri {HV_ZAM1_ASU_PCR, HV_ZAM1_ASU_PIC0, HV_ZAM1_ASU_PIC1}, 1475146Ssvemuri {HV_ZAM2_ASU_PCR, HV_ZAM2_ASU_PIC0, HV_ZAM2_ASU_PIC1}, 1485146Ssvemuri {HV_ZAM3_ASU_PCR, HV_ZAM3_ASU_PIC0, HV_ZAM3_ASU_PIC1} 1495146Ssvemuri }; 1505146Ssvemuri 1515146Ssvemuri static int zam_cntr_kstat_update(kstat_t *, int); 1525146Ssvemuri #endif 1535146Ssvemuri 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}, 1825146Ssvemuri {"clear_pic", 0xf} 1830Sstevel@tonic-gate }; 1840Sstevel@tonic-gate 1855146Ssvemuri #if defined(VFALLS_IMPL) 1865146Ssvemuri /* 1875146Ssvemuri * Zambezi Performance Events 1885146Ssvemuri */ 1895146Ssvemuri static ni_kev_mask_t 1905146Ssvemuri zam_lpu_perf_events[] = { 1915146Ssvemuri {"none", 0x0}, 1925146Ssvemuri {"clock_cycles", 0x1}, 1935146Ssvemuri {"cycles_c2c_portX", 0x2}, 1945146Ssvemuri {"cycles_mem_portX", 0x3}, 1955146Ssvemuri {"cycles_WB_portX", 0x4}, 1965146Ssvemuri {"cycles_NC_portX", 0x5}, 1975146Ssvemuri {"cycles_c2c_portY", 0x6}, 1985146Ssvemuri {"cycles_mem_portY", 0x7}, 1995146Ssvemuri {"cycles_WB_portY", 0x8}, 2005146Ssvemuri {"cycles_NC_portY", 0x9}, 2015146Ssvemuri {"cycles_c2c_portZ", 0xa}, 2025146Ssvemuri {"cycles_mem_portZ", 0xb}, 2035146Ssvemuri {"cycles_WB_portZ", 0xc}, 2045146Ssvemuri {"cycles_NC_portZ", 0xd}, 2055146Ssvemuri {"cycles_TID_WB", 0xe}, 2065146Ssvemuri {"cycles_TID_INV", 0xf}, 2075146Ssvemuri {"cycles_TID_RTD", 0x10}, 2085146Ssvemuri {"cycles_TID_RTO", 0x11}, 2095146Ssvemuri {"cycles_TID_RTS", 0x12}, 2105146Ssvemuri {"cycles_IO_WRM", 0x13}, 2115146Ssvemuri {"cycles_IO_RD", 0x14}, 2125146Ssvemuri {"cycles_WB_egress", 0x15}, 2135146Ssvemuri {"cycles_INV_egress", 0x16}, 2145146Ssvemuri {"cycles_RTO_egress", 0x17}, 2155146Ssvemuri {"cycles_RTD_egress", 0x18}, 2165146Ssvemuri {"cycles_RTS_egress", 0x19}, 2175146Ssvemuri {"cycles_no_WB", 0x1a}, 2185146Ssvemuri {"cycles_no_read/inv", 0x1b}, 2195146Ssvemuri {"cycles_HIT_M", 0x1c}, 2205146Ssvemuri {"cycles_HIT_O", 0x1d}, 2215146Ssvemuri {"cycles_HIT_S", 0x1e}, 2225146Ssvemuri {"cycles_WB_HIT", 0x1f}, 2235146Ssvemuri {"cycles_MISS", 0x20}, 2245146Ssvemuri {"cycles_READ_or_INV", 0x21}, 2255146Ssvemuri {"cycles_WB", 0x22}, 2265146Ssvemuri {"cycles_NDR", 0x23}, 2275146Ssvemuri {"cycles_cache_miss", 0x24}, 2285146Ssvemuri {"cycles_cache_hit", 0x25}, 2295146Ssvemuri {"cycles_CRC_errors", 0x26}, 2305146Ssvemuri {"cycles_replys_sent", 0x27}, 2315146Ssvemuri {"cycles_replys_recev", 0x28}, 2325146Ssvemuri {"cycles_link_retrain", 0x29}, 2335146Ssvemuri {"clear_pic", 0xff} 2345146Ssvemuri }; 2355146Ssvemuri 2365146Ssvemuri static ni_kev_mask_t 2375146Ssvemuri zam_gpd_perf_events[] = { 2385146Ssvemuri {"none", 0x0}, 2395146Ssvemuri {"clock_cycles", 0x1}, 2405146Ssvemuri {"clear_pic", 0xf} 2415146Ssvemuri }; 2425146Ssvemuri 2435146Ssvemuri static ni_kev_mask_t 2445146Ssvemuri zam_asu_perf_events[] = { 2455146Ssvemuri {"none", 0x0}, 2465146Ssvemuri {"clock_cycles", 0x1}, 2475146Ssvemuri {"asu_in_pck", 0x2}, 2485146Ssvemuri {"asu_out_pck", 0x3}, 2495146Ssvemuri {"asu_CAM_hit", 0x4}, 2505146Ssvemuri {"asu_wakeup", 0x5}, 2515146Ssvemuri {"clear_pic", 0xf} 2525146Ssvemuri }; 2535146Ssvemuri #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 /* 2775146Ssvemuri * 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*5352Ssvemuri #ifdef VFALLS_IMPL 285*5352Ssvemuri uint64_t stat, pcr; 286*5352Ssvemuri #endif 2870Sstevel@tonic-gate 2880Sstevel@tonic-gate #ifdef DEBUG 2890Sstevel@tonic-gate if (ni_perf_debug) 2900Sstevel@tonic-gate printf("ni_kstat_init called\n"); 2910Sstevel@tonic-gate #endif 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate /* 2940Sstevel@tonic-gate * Create DRAM perf events kstat 2950Sstevel@tonic-gate */ 2960Sstevel@tonic-gate for (i = 0; i < NIAGARA_DRAM_BANKS; i++) { 2974732Sdavemq #ifdef VFALLS_IMPL 2984732Sdavemq /* check if this dram instance is enabled in the HW */ 2995146Ssvemuri stat = hv_niagara_getperf(dram_perf_regs[i].pcr_reg, &pcr); 3005146Ssvemuri if ((stat != H_EINVAL) && (stat != H_ENOTSUPPORTED)) { 3014732Sdavemq #endif 3024732Sdavemq ksinfop = (ni_ksinfo_t *)kmem_zalloc( 3034732Sdavemq sizeof (ni_ksinfo_t), KM_NOSLEEP); 3040Sstevel@tonic-gate 3054732Sdavemq if (ksinfop == NULL) { 3064732Sdavemq cmn_err(CE_WARN, 3074732Sdavemq "%s: no space for dram kstat\n", 3084732Sdavemq cpu_module_name); 3094732Sdavemq break; 3104732Sdavemq } 3114732Sdavemq ksinfop->pic_no_evs = 3124732Sdavemq sizeof (niagara_dram_events) / 3134732Sdavemq sizeof (ni_kev_mask_t); 3144732Sdavemq ksinfop->pic_sel_shift[0] = NIAGARA_DRAM_PIC0_SEL_SHIFT; 3154732Sdavemq ksinfop->pic_shift[0] = NIAGARA_DRAM_PIC0_SHIFT; 3164732Sdavemq ksinfop->pic_mask[0] = NIAGARA_DRAM_PIC0_MASK; 3174732Sdavemq ksinfop->pic_sel_shift[1] = NIAGARA_DRAM_PIC1_SEL_SHIFT; 3184732Sdavemq ksinfop->pic_shift[1] = NIAGARA_DRAM_PIC1_SHIFT; 3194732Sdavemq ksinfop->pic_mask[1] = NIAGARA_DRAM_PIC1_MASK; 3205146Ssvemuri ksinfop->pic_reg[0] = dram_perf_regs[i].pic_reg; 3214732Sdavemq ksinfop->pcr_reg = dram_perf_regs[i].pcr_reg; 3224732Sdavemq ni_dram_kstats[i] = ksinfop; 3230Sstevel@tonic-gate 3244732Sdavemq /* create basic pic event/mask pair (only once) */ 3254732Sdavemq if (i == 0) 3264732Sdavemq ni_create_name_kstat("dram", ksinfop, 3270Sstevel@tonic-gate niagara_dram_events); 3280Sstevel@tonic-gate 3294732Sdavemq /* create counter kstats */ 3304732Sdavemq ni_dram_kstats[i]->cntr_ksp = ni_create_cntr_kstat( 3314732Sdavemq "dram", i, ni_cntr_kstat_update, ksinfop); 3324732Sdavemq #ifdef VFALLS_IMPL 3334732Sdavemq } 3344732Sdavemq #endif 3350Sstevel@tonic-gate } 3360Sstevel@tonic-gate 3375146Ssvemuri #ifdef VFALLS_IMPL 3385146Ssvemuri /* 3395146Ssvemuri * Create Zambezi LPU perf events kstat 3405146Ssvemuri */ 3415146Ssvemuri for (i = 0; i < ZAMBEZI_LPU_COUNTERS; i++) { 3425146Ssvemuri /* check if this Zambezi LPU instance is enabled in the HW */ 3435146Ssvemuri stat = hv_niagara_getperf(lpu_perf_regs[i].pcr_reg, &pcr); 3445146Ssvemuri if ((stat != H_EINVAL) && (stat != H_ENOTSUPPORTED)) { 3455146Ssvemuri ksinfop = (ni_ksinfo_t *)kmem_zalloc( 3465146Ssvemuri sizeof (ni_ksinfo_t), KM_NOSLEEP); 3475146Ssvemuri 3485146Ssvemuri if (ksinfop == NULL) { 3495146Ssvemuri cmn_err(CE_WARN, 3505146Ssvemuri "%s: no space for zambezi lpu kstat\n", 3515146Ssvemuri cpu_module_name); 3525146Ssvemuri break; 3535146Ssvemuri } 3545146Ssvemuri ksinfop->pic_no_evs = 3555146Ssvemuri sizeof (zam_lpu_perf_events) / 3565146Ssvemuri sizeof (ni_kev_mask_t); 3575146Ssvemuri ksinfop->pic_sel_shift[0] = ZAMBEZI_PIC0_SEL_SHIFT; 3585146Ssvemuri ksinfop->pic_reg[0] = lpu_perf_regs[i].pic_reg[0]; 3595146Ssvemuri ksinfop->pic_sel_shift[1] = ZAMBEZI_PIC1_SEL_SHIFT; 3605146Ssvemuri ksinfop->pic_reg[1] = lpu_perf_regs[i].pic_reg[1]; 3615146Ssvemuri ksinfop->pcr_reg = lpu_perf_regs[i].pcr_reg; 3625146Ssvemuri zam_lpu_kstats[i] = ksinfop; 3635146Ssvemuri 3645146Ssvemuri /* create basic pic event/mask pair (only once) */ 3655146Ssvemuri if (i == 0) 3665146Ssvemuri ni_create_name_kstat("lpu", ksinfop, 3675146Ssvemuri zam_lpu_perf_events); 3685146Ssvemuri 3695146Ssvemuri /* create counter kstats */ 3705146Ssvemuri zam_lpu_kstats[i]->cntr_ksp = ni_create_cntr_kstat( 3715146Ssvemuri "lpu", i, zam_cntr_kstat_update, ksinfop); 3725146Ssvemuri } 3735146Ssvemuri } 3745146Ssvemuri /* 3755146Ssvemuri * Create Zambezi GPD perf events kstat 3765146Ssvemuri */ 3775146Ssvemuri for (i = 0; i < ZAMBEZI_GPD_COUNTERS; i++) { 3785146Ssvemuri /* check if this Zambezi GPD instance is enabled in the HW */ 3795146Ssvemuri stat = hv_niagara_getperf(gpd_perf_regs[i].pcr_reg, &pcr); 3805146Ssvemuri if ((stat != H_EINVAL) && (stat != H_ENOTSUPPORTED)) { 3815146Ssvemuri ksinfop = (ni_ksinfo_t *)kmem_zalloc( 3825146Ssvemuri sizeof (ni_ksinfo_t), KM_NOSLEEP); 3835146Ssvemuri 3845146Ssvemuri if (ksinfop == NULL) { 3855146Ssvemuri cmn_err(CE_WARN, 3865146Ssvemuri "%s: no space for zambezi gpd kstat\n", 3875146Ssvemuri cpu_module_name); 3885146Ssvemuri break; 3895146Ssvemuri } 3905146Ssvemuri ksinfop->pic_no_evs = 3915146Ssvemuri sizeof (zam_gpd_perf_events) / 3925146Ssvemuri sizeof (ni_kev_mask_t); 3935146Ssvemuri ksinfop->pic_sel_shift[0] = ZAMBEZI_PIC0_SEL_SHIFT; 3945146Ssvemuri ksinfop->pic_reg[0] = gpd_perf_regs[i].pic_reg[0]; 3955146Ssvemuri ksinfop->pic_sel_shift[1] = ZAMBEZI_PIC1_SEL_SHIFT; 3965146Ssvemuri ksinfop->pic_reg[1] = gpd_perf_regs[i].pic_reg[1]; 3975146Ssvemuri ksinfop->pcr_reg = gpd_perf_regs[i].pcr_reg; 3985146Ssvemuri zam_gpd_kstats[i] = ksinfop; 3995146Ssvemuri 4005146Ssvemuri /* create basic pic event/mask pair (only once) */ 4015146Ssvemuri if (i == 0) 4025146Ssvemuri ni_create_name_kstat("gpd", ksinfop, 4035146Ssvemuri zam_gpd_perf_events); 4045146Ssvemuri 4055146Ssvemuri /* create counter kstats */ 4065146Ssvemuri zam_lpu_kstats[i]->cntr_ksp = ni_create_cntr_kstat( 4075146Ssvemuri "gpd", i, zam_cntr_kstat_update, ksinfop); 4085146Ssvemuri } 4095146Ssvemuri } 4105146Ssvemuri /* 4115146Ssvemuri * Create Zambezi ASU perf events kstat 4125146Ssvemuri */ 4135146Ssvemuri for (i = 0; i < ZAMBEZI_ASU_COUNTERS; i++) { 4145146Ssvemuri /* check if this Zambezi ASU instance is enabled in the HW */ 4155146Ssvemuri stat = hv_niagara_getperf(asu_perf_regs[i].pcr_reg, &pcr); 4165146Ssvemuri if ((stat != H_EINVAL) && (stat != H_ENOTSUPPORTED)) { 4175146Ssvemuri ksinfop = (ni_ksinfo_t *)kmem_zalloc( 4185146Ssvemuri sizeof (ni_ksinfo_t), KM_NOSLEEP); 4195146Ssvemuri 4205146Ssvemuri if (ksinfop == NULL) { 4215146Ssvemuri cmn_err(CE_WARN, 4225146Ssvemuri "%s: no space for zambezi asu kstat\n", 4235146Ssvemuri cpu_module_name); 4245146Ssvemuri break; 4255146Ssvemuri } 4265146Ssvemuri ksinfop->pic_no_evs = 4275146Ssvemuri sizeof (zam_asu_perf_events) / 4285146Ssvemuri sizeof (ni_kev_mask_t); 4295146Ssvemuri ksinfop->pic_sel_shift[0] = ZAMBEZI_PIC0_SEL_SHIFT; 4305146Ssvemuri ksinfop->pic_reg[0] = asu_perf_regs[i].pic_reg[0]; 4315146Ssvemuri ksinfop->pic_sel_shift[1] = ZAMBEZI_PIC1_SEL_SHIFT; 4325146Ssvemuri ksinfop->pic_reg[1] = asu_perf_regs[i].pic_reg[1]; 4335146Ssvemuri ksinfop->pcr_reg = asu_perf_regs[i].pcr_reg; 4345146Ssvemuri zam_asu_kstats[i] = ksinfop; 4355146Ssvemuri 4365146Ssvemuri /* create basic pic event/mask pair (only once) */ 4375146Ssvemuri if (i == 0) 4385146Ssvemuri ni_create_name_kstat("asu", ksinfop, 4395146Ssvemuri zam_asu_perf_events); 4405146Ssvemuri 4415146Ssvemuri /* create counter kstats */ 4425146Ssvemuri zam_lpu_kstats[i]->cntr_ksp = ni_create_cntr_kstat( 4435146Ssvemuri "asu", i, zam_cntr_kstat_update, ksinfop); 4445146Ssvemuri } 4455146Ssvemuri } 4465146Ssvemuri #endif 4475146Ssvemuri 4483156Sgirish #if defined(NIAGARA_IMPL) 4490Sstevel@tonic-gate /* 4500Sstevel@tonic-gate * Create JBUS perf events kstat 4510Sstevel@tonic-gate */ 4520Sstevel@tonic-gate ni_jbus_kstat = (ni_ksinfo_t *)kmem_alloc(sizeof (ni_ksinfo_t), 4534732Sdavemq KM_NOSLEEP); 4540Sstevel@tonic-gate 4550Sstevel@tonic-gate if (ni_jbus_kstat == NULL) { 4560Sstevel@tonic-gate cmn_err(CE_WARN, "%s: no space for niagara jbus kstat\n", 4571592Sgirish cpu_module_name); 4580Sstevel@tonic-gate } else { 4590Sstevel@tonic-gate ni_jbus_kstat->pic_no_evs = 4604732Sdavemq sizeof (niagara_jbus_events) / sizeof (ni_kev_mask_t); 4610Sstevel@tonic-gate ni_jbus_kstat->pic_sel_shift[0] = NIAGARA_JBUS_PIC0_SEL_SHIFT; 4620Sstevel@tonic-gate ni_jbus_kstat->pic_shift[0] = NIAGARA_JBUS_PIC0_SHIFT; 4630Sstevel@tonic-gate ni_jbus_kstat->pic_mask[0] = NIAGARA_JBUS_PIC0_MASK; 4640Sstevel@tonic-gate ni_jbus_kstat->pic_sel_shift[1] = NIAGARA_JBUS_PIC1_SEL_SHIFT; 4650Sstevel@tonic-gate ni_jbus_kstat->pic_shift[1] = NIAGARA_JBUS_PIC1_SHIFT; 4660Sstevel@tonic-gate ni_jbus_kstat->pic_mask[1] = NIAGARA_JBUS_PIC1_MASK; 4675146Ssvemuri ni_jbus_kstat->pic_reg[0] = HV_NIAGARA_JBUS_COUNT; 4680Sstevel@tonic-gate ni_jbus_kstat->pcr_reg = HV_NIAGARA_JBUS_CTL; 4690Sstevel@tonic-gate ni_create_name_kstat("jbus", ni_jbus_kstat, 4700Sstevel@tonic-gate niagara_jbus_events); 4710Sstevel@tonic-gate ni_jbus_kstat->cntr_ksp = ni_create_cntr_kstat("jbus", 0, 4720Sstevel@tonic-gate ni_cntr_kstat_update, ni_jbus_kstat); 4730Sstevel@tonic-gate } 4743156Sgirish #endif 4750Sstevel@tonic-gate } 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate void 4780Sstevel@tonic-gate niagara_kstat_fini() 4790Sstevel@tonic-gate { 4800Sstevel@tonic-gate int i; 4810Sstevel@tonic-gate 4820Sstevel@tonic-gate #ifdef DEBUG 4830Sstevel@tonic-gate if (ni_perf_debug) 4840Sstevel@tonic-gate printf("ni_kstat_fini called\n"); 4850Sstevel@tonic-gate #endif 4865146Ssvemuri 4870Sstevel@tonic-gate for (i = 0; i < NIAGARA_DRAM_BANKS; i++) { 4880Sstevel@tonic-gate if (ni_dram_kstats[i] != NULL) { 4890Sstevel@tonic-gate ni_delete_name_kstat(ni_dram_kstats[i]); 4900Sstevel@tonic-gate if (ni_dram_kstats[i]->cntr_ksp != NULL) 4910Sstevel@tonic-gate kstat_delete(ni_dram_kstats[i]->cntr_ksp); 4920Sstevel@tonic-gate kmem_free(ni_dram_kstats[i], sizeof (ni_ksinfo_t)); 4930Sstevel@tonic-gate ni_dram_kstats[i] = NULL; 4940Sstevel@tonic-gate } 4950Sstevel@tonic-gate } 4960Sstevel@tonic-gate 4975146Ssvemuri #if defined(VFALLS_IMPL) 4985146Ssvemuri for (i = 0; i < ZAMBEZI_LPU_COUNTERS; i++) { 4995146Ssvemuri if (zam_lpu_kstats[i] != NULL) { 5005146Ssvemuri ni_delete_name_kstat(zam_lpu_kstats[i]); 5015146Ssvemuri if (zam_lpu_kstats[i]->cntr_ksp != NULL) 5025146Ssvemuri kstat_delete(zam_lpu_kstats[i]->cntr_ksp); 5035146Ssvemuri kmem_free(zam_lpu_kstats[i], sizeof (ni_ksinfo_t)); 5045146Ssvemuri zam_lpu_kstats[i] = NULL; 5055146Ssvemuri } 5065146Ssvemuri } 5075146Ssvemuri 5085146Ssvemuri for (i = 0; i < ZAMBEZI_GPD_COUNTERS; i++) { 5095146Ssvemuri if (zam_gpd_kstats[i] != NULL) { 5105146Ssvemuri ni_delete_name_kstat(zam_gpd_kstats[i]); 5115146Ssvemuri if (zam_gpd_kstats[i]->cntr_ksp != NULL) 5125146Ssvemuri kstat_delete(zam_gpd_kstats[i]->cntr_ksp); 5135146Ssvemuri kmem_free(zam_gpd_kstats[i], sizeof (ni_ksinfo_t)); 5145146Ssvemuri zam_gpd_kstats[i] = NULL; 5155146Ssvemuri } 5165146Ssvemuri } 5175146Ssvemuri 5185146Ssvemuri for (i = 0; i < ZAMBEZI_ASU_COUNTERS; i++) { 5195146Ssvemuri if (zam_asu_kstats[i] != NULL) { 5205146Ssvemuri ni_delete_name_kstat(zam_asu_kstats[i]); 5215146Ssvemuri if (zam_asu_kstats[i]->cntr_ksp != NULL) 5225146Ssvemuri kstat_delete(zam_asu_kstats[i]->cntr_ksp); 5235146Ssvemuri kmem_free(zam_asu_kstats[i], sizeof (ni_ksinfo_t)); 5245146Ssvemuri zam_asu_kstats[i] = NULL; 5255146Ssvemuri } 5265146Ssvemuri } 5275146Ssvemuri #endif 5285146Ssvemuri 5293156Sgirish #if defined(NIAGARA_IMPL) 5300Sstevel@tonic-gate if (ni_jbus_kstat != NULL) { 5310Sstevel@tonic-gate ni_delete_name_kstat(ni_jbus_kstat); 5320Sstevel@tonic-gate if (ni_jbus_kstat->cntr_ksp != NULL) 5330Sstevel@tonic-gate kstat_delete(ni_jbus_kstat->cntr_ksp); 5340Sstevel@tonic-gate kmem_free(ni_jbus_kstat, sizeof (ni_ksinfo_t)); 5350Sstevel@tonic-gate ni_jbus_kstat = NULL; 5360Sstevel@tonic-gate } 5373156Sgirish #endif 5380Sstevel@tonic-gate } 5390Sstevel@tonic-gate 5400Sstevel@tonic-gate static void 5410Sstevel@tonic-gate ni_create_name_kstat(char *name, ni_ksinfo_t *pp, ni_kev_mask_t *ev) 5420Sstevel@tonic-gate { 5430Sstevel@tonic-gate int i; 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate #ifdef DEBUG 5460Sstevel@tonic-gate if (ni_perf_debug > 1) 5470Sstevel@tonic-gate printf("ni_create_name_kstat: name: %s\n", name); 5480Sstevel@tonic-gate #endif 5490Sstevel@tonic-gate for (i = 0; i < NUM_OF_PICS; i++) { 5500Sstevel@tonic-gate pp->pic_name_ksp[i] = ni_create_picN_kstat(name, 5514732Sdavemq i, pp->pic_sel_shift[i], pp->pic_no_evs, ev); 5520Sstevel@tonic-gate 5530Sstevel@tonic-gate if (pp->pic_name_ksp[i] == NULL) { 5540Sstevel@tonic-gate cmn_err(CE_WARN, "%s: unable to create name kstat", 5551592Sgirish cpu_module_name); 5560Sstevel@tonic-gate } 5570Sstevel@tonic-gate } 5580Sstevel@tonic-gate } 5590Sstevel@tonic-gate 5600Sstevel@tonic-gate static void 5610Sstevel@tonic-gate ni_delete_name_kstat(ni_ksinfo_t *pp) 5620Sstevel@tonic-gate { 5630Sstevel@tonic-gate int i; 5640Sstevel@tonic-gate 5650Sstevel@tonic-gate if (pp != NULL) { 5660Sstevel@tonic-gate for (i = 0; i < NUM_OF_PICS; i++) { 5670Sstevel@tonic-gate if (pp->pic_name_ksp[i] != NULL) 5680Sstevel@tonic-gate kstat_delete(pp->pic_name_ksp[i]); 5690Sstevel@tonic-gate } 5700Sstevel@tonic-gate } 5710Sstevel@tonic-gate } 5720Sstevel@tonic-gate 5730Sstevel@tonic-gate /* 5740Sstevel@tonic-gate * Create the picN kstat. Returns a pointer to the 5750Sstevel@tonic-gate * kstat which the driver must store to allow it 5760Sstevel@tonic-gate * to be deleted when necessary. 5770Sstevel@tonic-gate */ 5780Sstevel@tonic-gate static kstat_t * 5790Sstevel@tonic-gate ni_create_picN_kstat(char *mod_name, int pic, int pic_sel_shift, 5800Sstevel@tonic-gate int num_ev, ni_kev_mask_t *ev_array) 5810Sstevel@tonic-gate { 5820Sstevel@tonic-gate struct kstat_named *pic_named_data; 5830Sstevel@tonic-gate int inst = 0; 5840Sstevel@tonic-gate int event; 5850Sstevel@tonic-gate char pic_name[30]; 5860Sstevel@tonic-gate kstat_t *picN_ksp = NULL; 5870Sstevel@tonic-gate 5880Sstevel@tonic-gate (void) sprintf(pic_name, "pic%d", pic); 5890Sstevel@tonic-gate if ((picN_ksp = kstat_create(mod_name, inst, pic_name, 5900Sstevel@tonic-gate "bus", KSTAT_TYPE_NAMED, num_ev, NULL)) == NULL) { 5910Sstevel@tonic-gate cmn_err(CE_WARN, "%s %s : kstat create failed", 5924732Sdavemq mod_name, pic_name); 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate /* 5950Sstevel@tonic-gate * It is up to the calling function to delete any kstats 5960Sstevel@tonic-gate * that may have been created already. We just 5970Sstevel@tonic-gate * return NULL to indicate an error has occured. 5980Sstevel@tonic-gate */ 5990Sstevel@tonic-gate return (NULL); 6000Sstevel@tonic-gate } 6010Sstevel@tonic-gate 6020Sstevel@tonic-gate pic_named_data = (struct kstat_named *) 6030Sstevel@tonic-gate picN_ksp->ks_data; 6040Sstevel@tonic-gate 6050Sstevel@tonic-gate /* 6060Sstevel@tonic-gate * Write event names and their associated pcr masks. The 6070Sstevel@tonic-gate * last entry in the array (clear_pic) is added seperately 6080Sstevel@tonic-gate * below as the pic value must be inverted. 6090Sstevel@tonic-gate */ 6100Sstevel@tonic-gate for (event = 0; event < num_ev - 1; event++) { 6110Sstevel@tonic-gate pic_named_data[event].value.ui64 = 6124732Sdavemq (ev_array[event].pcr_mask << pic_sel_shift); 6130Sstevel@tonic-gate 6140Sstevel@tonic-gate kstat_named_init(&pic_named_data[event], 6154732Sdavemq ev_array[event].event_name, 6164732Sdavemq KSTAT_DATA_UINT64); 6170Sstevel@tonic-gate } 6180Sstevel@tonic-gate 6190Sstevel@tonic-gate /* 6200Sstevel@tonic-gate * add the clear_pic entry. 6210Sstevel@tonic-gate */ 6220Sstevel@tonic-gate pic_named_data[event].value.ui64 = 6234732Sdavemq (uint64_t)~(ev_array[event].pcr_mask << pic_sel_shift); 6240Sstevel@tonic-gate 6250Sstevel@tonic-gate kstat_named_init(&pic_named_data[event], ev_array[event].event_name, 6260Sstevel@tonic-gate KSTAT_DATA_UINT64); 6270Sstevel@tonic-gate 6280Sstevel@tonic-gate kstat_install(picN_ksp); 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate return (picN_ksp); 6310Sstevel@tonic-gate } 6320Sstevel@tonic-gate 6330Sstevel@tonic-gate /* 6340Sstevel@tonic-gate * Create the "counters" kstat. 6350Sstevel@tonic-gate */ 6360Sstevel@tonic-gate static kstat_t * 6370Sstevel@tonic-gate ni_create_cntr_kstat(char *name, int instance, int (*update)(kstat_t *, int), 6380Sstevel@tonic-gate void *ksinfop) 6390Sstevel@tonic-gate { 6400Sstevel@tonic-gate struct kstat *counters_ksp; 6410Sstevel@tonic-gate struct kstat_named *counters_named_data; 6420Sstevel@tonic-gate char pic_str[10]; 6430Sstevel@tonic-gate int i; 6440Sstevel@tonic-gate int num_pics = NUM_OF_PICS; 6450Sstevel@tonic-gate 6460Sstevel@tonic-gate #ifdef DEBUG 6470Sstevel@tonic-gate if (ni_perf_debug > 1) 6480Sstevel@tonic-gate printf("ni_create_cntr_kstat: name: %s instance: %d\n", 6490Sstevel@tonic-gate name, instance); 6500Sstevel@tonic-gate #endif 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate /* 6530Sstevel@tonic-gate * Size of kstat is num_pics + 1 as it 6540Sstevel@tonic-gate * also contains the %pcr 6550Sstevel@tonic-gate */ 6560Sstevel@tonic-gate if ((counters_ksp = kstat_create(name, instance, "counters", "bus", 6570Sstevel@tonic-gate KSTAT_TYPE_NAMED, num_pics + 1, KSTAT_FLAG_WRITABLE)) == NULL) { 6580Sstevel@tonic-gate cmn_err(CE_WARN, 6591592Sgirish "%s: kstat_create for %s%d failed", cpu_module_name, 6600Sstevel@tonic-gate name, instance); 6610Sstevel@tonic-gate return (NULL); 6620Sstevel@tonic-gate } 6630Sstevel@tonic-gate 6640Sstevel@tonic-gate counters_named_data = (struct kstat_named *)(counters_ksp->ks_data); 6650Sstevel@tonic-gate 6660Sstevel@tonic-gate /* 6670Sstevel@tonic-gate * Iinitialize the named kstats 6680Sstevel@tonic-gate */ 6690Sstevel@tonic-gate kstat_named_init(&counters_named_data[0], "pcr", KSTAT_DATA_UINT64); 6700Sstevel@tonic-gate 6710Sstevel@tonic-gate for (i = 0; i < num_pics; i++) { 6720Sstevel@tonic-gate (void) sprintf(pic_str, "pic%d", i); 6730Sstevel@tonic-gate 6740Sstevel@tonic-gate kstat_named_init(&counters_named_data[i+1], pic_str, 6750Sstevel@tonic-gate KSTAT_DATA_UINT64); 6760Sstevel@tonic-gate } 6770Sstevel@tonic-gate 6780Sstevel@tonic-gate /* 6790Sstevel@tonic-gate * Store the register offset's in the kstat's 6800Sstevel@tonic-gate * private field so that they are available 6810Sstevel@tonic-gate * to the update function. 6820Sstevel@tonic-gate */ 6830Sstevel@tonic-gate counters_ksp->ks_private = (void *)ksinfop; 6840Sstevel@tonic-gate counters_ksp->ks_update = update; 6850Sstevel@tonic-gate 6860Sstevel@tonic-gate kstat_install(counters_ksp); 6870Sstevel@tonic-gate 6880Sstevel@tonic-gate return (counters_ksp); 6890Sstevel@tonic-gate } 6900Sstevel@tonic-gate 6915146Ssvemuri #if defined(VFALLS_IMPL) 6925146Ssvemuri /* 6935146Ssvemuri * zambezi kstat update function. Handles reads/writes 6945146Ssvemuri * from/to kstat. 6955146Ssvemuri */ 6965146Ssvemuri static int 6975146Ssvemuri zam_cntr_kstat_update(kstat_t *ksp, int rw) 6985146Ssvemuri { 6995146Ssvemuri struct kstat_named *data_p; 7005146Ssvemuri ni_ksinfo_t *ksinfop = ksp->ks_private; 7015146Ssvemuri uint64_t pic0, pic1, pcr; 7025146Ssvemuri int stat = 0; 7035146Ssvemuri uint64_t pic0_stat = 0, pic1_stat = 0, pcr_stat = 0; 7045146Ssvemuri 7055146Ssvemuri data_p = (struct kstat_named *)ksp->ks_data; 7065146Ssvemuri 7075146Ssvemuri if (rw == KSTAT_WRITE) { 7085146Ssvemuri #ifdef DEBUG 7095146Ssvemuri if (ni_perf_debug) 7105146Ssvemuri printf("zam_cntr_kstat_update: wr pcr-%d: %lx\n", 7115146Ssvemuri ksinfop->pcr_reg, data_p[0].value.ui64); 7125146Ssvemuri #endif 7135146Ssvemuri if (hv_niagara_setperf(ksinfop->pcr_reg, data_p[0].value.ui64)) 7145146Ssvemuri stat = EACCES; 7155146Ssvemuri } else { 7165146Ssvemuri do { 7175146Ssvemuri pic0_stat = hv_niagara_getperf(ksinfop->pic_reg[0], 7185146Ssvemuri &pic0); 7195146Ssvemuri } while (pic0_stat == H_EWOULDBLOCK); 7205146Ssvemuri do { 7215146Ssvemuri pic1_stat = hv_niagara_getperf(ksinfop->pic_reg[1], 7225146Ssvemuri &pic1); 7235146Ssvemuri } while (pic1_stat == H_EWOULDBLOCK); 7245146Ssvemuri do { 7255146Ssvemuri pcr_stat = hv_niagara_getperf(ksinfop->pcr_reg, 7265146Ssvemuri &pcr); 7275146Ssvemuri } while (pcr_stat == H_EWOULDBLOCK); 7285146Ssvemuri if (pic0_stat != 0 || pic1_stat != 0 || pcr_stat != 0) 7295146Ssvemuri stat = EACCES; 7305146Ssvemuri else { 7315146Ssvemuri data_p[0].value.ui64 = pcr; 7325146Ssvemuri data_p[1].value.ui64 = pic0; 7335146Ssvemuri data_p[2].value.ui64 = pic1; 7345146Ssvemuri } 7355146Ssvemuri #ifdef DEBUG 7365146Ssvemuri if (ni_perf_debug) 7375146Ssvemuri printf("zam_cntr_kstat_update: rd pcr%d: %lx " 7385146Ssvemuri "pic0: %16lx pic1: %16lx\n", 7395146Ssvemuri ksinfop->pcr_reg, pcr, 7405146Ssvemuri data_p[1].value.ui64, data_p[2].value.ui64); 7415146Ssvemuri #endif 7425146Ssvemuri } 7435146Ssvemuri 7445146Ssvemuri return (stat); 7455146Ssvemuri } 7465146Ssvemuri #endif 7475146Ssvemuri 7480Sstevel@tonic-gate /* 7490Sstevel@tonic-gate * kstat update function. Handles reads/writes 7500Sstevel@tonic-gate * from/to kstat. 7510Sstevel@tonic-gate */ 7520Sstevel@tonic-gate static int 7530Sstevel@tonic-gate ni_cntr_kstat_update(kstat_t *ksp, int rw) 7540Sstevel@tonic-gate { 7550Sstevel@tonic-gate struct kstat_named *data_p; 7560Sstevel@tonic-gate ni_ksinfo_t *ksinfop = ksp->ks_private; 7570Sstevel@tonic-gate uint64_t pic, pcr; 7580Sstevel@tonic-gate int stat = 0; 7590Sstevel@tonic-gate uint32_t pic0, pic1; 7600Sstevel@tonic-gate 7610Sstevel@tonic-gate data_p = (struct kstat_named *)ksp->ks_data; 7620Sstevel@tonic-gate 7630Sstevel@tonic-gate if (rw == KSTAT_WRITE) { 7640Sstevel@tonic-gate #ifdef DEBUG 7650Sstevel@tonic-gate if (ni_perf_debug) 766911Siskreen printf("ni_cntr_kstat_update: wr pcr-%d: %lx\n", 7670Sstevel@tonic-gate ksinfop->pcr_reg, data_p[0].value.ui64); 7680Sstevel@tonic-gate #endif 7690Sstevel@tonic-gate if (hv_niagara_setperf(ksinfop->pcr_reg, data_p[0].value.ui64)) 7700Sstevel@tonic-gate stat = EACCES; 7710Sstevel@tonic-gate } else { 7725146Ssvemuri if (hv_niagara_getperf(ksinfop->pic_reg[0], &pic) != 0 || 7730Sstevel@tonic-gate hv_niagara_getperf(ksinfop->pcr_reg, &pcr) != 0) 7740Sstevel@tonic-gate stat = EACCES; 7750Sstevel@tonic-gate else { 7760Sstevel@tonic-gate 7770Sstevel@tonic-gate data_p[0].value.ui64 = pcr; 7780Sstevel@tonic-gate 7790Sstevel@tonic-gate /* 7800Sstevel@tonic-gate * Generate a 32-bit PIC0 value by detecting overflow 7810Sstevel@tonic-gate */ 7820Sstevel@tonic-gate pic0 = (uint32_t)((pic >> ksinfop->pic_shift[0]) & 7830Sstevel@tonic-gate ksinfop->pic_mask[0]); 7840Sstevel@tonic-gate if (pic0 < ksinfop->pic_last_val[0]) 7850Sstevel@tonic-gate ksinfop->pic_overflow[0]++; 7860Sstevel@tonic-gate ksinfop->pic_last_val[0] = pic0; 7870Sstevel@tonic-gate pic0 += (ksinfop->pic_overflow[0] & 1) << 31; 7880Sstevel@tonic-gate data_p[1].value.ui64 = (uint64_t)pic0; 7890Sstevel@tonic-gate 7900Sstevel@tonic-gate /* 7910Sstevel@tonic-gate * Generate a 32-bit PIC1 value by detecting overflow 7920Sstevel@tonic-gate */ 7930Sstevel@tonic-gate pic1 = (uint32_t)((pic >> ksinfop->pic_shift[1]) & 7940Sstevel@tonic-gate ksinfop->pic_mask[1]); 7950Sstevel@tonic-gate if (pic1 < ksinfop->pic_last_val[1]) 7960Sstevel@tonic-gate ksinfop->pic_overflow[1]++; 7970Sstevel@tonic-gate ksinfop->pic_last_val[1] = pic1; 7980Sstevel@tonic-gate pic1 += (ksinfop->pic_overflow[1] & 1) << 31; 7990Sstevel@tonic-gate data_p[2].value.ui64 = (uint64_t)pic1; 8000Sstevel@tonic-gate } 8010Sstevel@tonic-gate #ifdef DEBUG 8020Sstevel@tonic-gate if (ni_perf_debug) 8030Sstevel@tonic-gate printf("ni_cntr_kstat_update: rd pcr%d: %lx " 8040Sstevel@tonic-gate "pic%d: %16lx pic0: %8lx pic1: %8lx\n", 8055146Ssvemuri ksinfop->pcr_reg, pcr, ksinfop->pic_reg[0], pic, 8060Sstevel@tonic-gate data_p[1].value.ui64, data_p[2].value.ui64); 8070Sstevel@tonic-gate #endif 8080Sstevel@tonic-gate } 8090Sstevel@tonic-gate return (stat); 8100Sstevel@tonic-gate } 811