1*29949e86Sstevel /* 2*29949e86Sstevel * CDDL HEADER START 3*29949e86Sstevel * 4*29949e86Sstevel * The contents of this file are subject to the terms of the 5*29949e86Sstevel * Common Development and Distribution License (the "License"). 6*29949e86Sstevel * You may not use this file except in compliance with the License. 7*29949e86Sstevel * 8*29949e86Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*29949e86Sstevel * or http://www.opensolaris.org/os/licensing. 10*29949e86Sstevel * See the License for the specific language governing permissions 11*29949e86Sstevel * and limitations under the License. 12*29949e86Sstevel * 13*29949e86Sstevel * When distributing Covered Code, include this CDDL HEADER in each 14*29949e86Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*29949e86Sstevel * If applicable, add the following below this CDDL HEADER, with the 16*29949e86Sstevel * fields enclosed by brackets "[]" replaced with your own identifying 17*29949e86Sstevel * information: Portions Copyright [yyyy] [name of copyright owner] 18*29949e86Sstevel * 19*29949e86Sstevel * CDDL HEADER END 20*29949e86Sstevel */ 21*29949e86Sstevel 22*29949e86Sstevel /* 23*29949e86Sstevel * Copyright 1998 Sun Microsystems, Inc. All rights reserved. 24*29949e86Sstevel * Use is subject to license terms. 25*29949e86Sstevel */ 26*29949e86Sstevel 27*29949e86Sstevel #pragma ident "%Z%%M% %I% %E% SMI" 28*29949e86Sstevel 29*29949e86Sstevel #include <sys/types.h> 30*29949e86Sstevel #include <sys/systm.h> 31*29949e86Sstevel #include <sys/ddi.h> 32*29949e86Sstevel #include <sys/sunddi.h> 33*29949e86Sstevel #include <sys/ddi_impldefs.h> 34*29949e86Sstevel #include <sys/obpdefs.h> 35*29949e86Sstevel #include <sys/cmn_err.h> 36*29949e86Sstevel #include <sys/errno.h> 37*29949e86Sstevel #include <sys/kmem.h> 38*29949e86Sstevel #include <sys/debug.h> 39*29949e86Sstevel #include <sys/sysmacros.h> 40*29949e86Sstevel #include <sys/machsystm.h> 41*29949e86Sstevel #include <sys/machparam.h> 42*29949e86Sstevel #include <sys/modctl.h> 43*29949e86Sstevel #include <sys/fhc.h> 44*29949e86Sstevel #include <sys/ac.h> 45*29949e86Sstevel #include <sys/vm.h> 46*29949e86Sstevel #include <sys/cpu_module.h> 47*29949e86Sstevel #include <vm/hat_sfmmu.h> 48*29949e86Sstevel #include <sys/mem_config.h> 49*29949e86Sstevel #include <sys/mem_cage.h> 50*29949e86Sstevel 51*29949e86Sstevel extern ac_err_t ac_kpm_err_cvt(int); 52*29949e86Sstevel 53*29949e86Sstevel #ifdef DEBUG 54*29949e86Sstevel static void query_checker(pfn_t, pgcnt_t, memquery_t *); 55*29949e86Sstevel static int ac_do_query_check = 0; 56*29949e86Sstevel #endif /* DEBUG */ 57*29949e86Sstevel 58*29949e86Sstevel int 59*29949e86Sstevel ac_mem_stat(ac_cfga_pkt_t *pkt, int flag) 60*29949e86Sstevel { 61*29949e86Sstevel ac_stat_t *statp; 62*29949e86Sstevel memquery_t memq; 63*29949e86Sstevel struct ac_mem_info *mem_info; 64*29949e86Sstevel struct bd_list *board; 65*29949e86Sstevel struct ac_soft_state *ac; 66*29949e86Sstevel uint64_t decode; 67*29949e86Sstevel uint64_t base_pa; 68*29949e86Sstevel uint64_t bank_size; 69*29949e86Sstevel pfn_t base; 70*29949e86Sstevel pgcnt_t npgs; 71*29949e86Sstevel int ret; 72*29949e86Sstevel int retval; 73*29949e86Sstevel 74*29949e86Sstevel /* 75*29949e86Sstevel * Is the specified bank present? 76*29949e86Sstevel */ 77*29949e86Sstevel 78*29949e86Sstevel board = fhc_bdlist_lock(pkt->softsp->board); 79*29949e86Sstevel if (board == NULL || board->ac_softsp == NULL) { 80*29949e86Sstevel fhc_bdlist_unlock(); 81*29949e86Sstevel AC_ERR_SET(pkt, AC_ERR_BD); 82*29949e86Sstevel return (EINVAL); 83*29949e86Sstevel } 84*29949e86Sstevel 85*29949e86Sstevel /* verify the board is of the correct type */ 86*29949e86Sstevel switch (board->sc.type) { 87*29949e86Sstevel case CPU_BOARD: 88*29949e86Sstevel case MEM_BOARD: 89*29949e86Sstevel break; 90*29949e86Sstevel default: 91*29949e86Sstevel fhc_bdlist_unlock(); 92*29949e86Sstevel AC_ERR_SET(pkt, AC_ERR_BD_TYPE); 93*29949e86Sstevel return (EINVAL); 94*29949e86Sstevel } 95*29949e86Sstevel ASSERT(pkt->softsp == board->ac_softsp); 96*29949e86Sstevel 97*29949e86Sstevel ac = pkt->softsp; 98*29949e86Sstevel mem_info = &ac->bank[pkt->bank]; 99*29949e86Sstevel 100*29949e86Sstevel statp = kmem_zalloc(sizeof (ac_stat_t), KM_SLEEP); 101*29949e86Sstevel 102*29949e86Sstevel statp->rstate = mem_info->rstate; 103*29949e86Sstevel statp->ostate = mem_info->ostate; 104*29949e86Sstevel statp->condition = mem_info->condition; 105*29949e86Sstevel statp->status_time = mem_info->status_change; 106*29949e86Sstevel statp->board = ac->board; 107*29949e86Sstevel statp->real_size = mem_info->real_size; 108*29949e86Sstevel statp->use_size = mem_info->use_size; 109*29949e86Sstevel statp->ac_memctl = *(ac->ac_memctl); 110*29949e86Sstevel statp->ac_decode0 = *(ac->ac_memdecode0); 111*29949e86Sstevel statp->ac_decode1 = *(ac->ac_memdecode1); 112*29949e86Sstevel 113*29949e86Sstevel statp->page_size = PAGESIZE; 114*29949e86Sstevel 115*29949e86Sstevel /* 116*29949e86Sstevel * Busy could also be set for fhc_bd_busy(ac->board) 117*29949e86Sstevel * however, this is just advisory information so limit it 118*29949e86Sstevel * to memory operation in progress. 119*29949e86Sstevel */ 120*29949e86Sstevel statp->busy = (mem_info->busy != FALSE); 121*29949e86Sstevel 122*29949e86Sstevel /* 123*29949e86Sstevel * Determine the physical location of the selected bank 124*29949e86Sstevel */ 125*29949e86Sstevel decode = (pkt->bank == Bank0) ? 126*29949e86Sstevel *(ac->ac_memdecode0) : *(ac->ac_memdecode1); 127*29949e86Sstevel base_pa = GRP_REALBASE(decode); 128*29949e86Sstevel bank_size = GRP_UK2SPAN(decode); 129*29949e86Sstevel 130*29949e86Sstevel base = base_pa >> PAGESHIFT; 131*29949e86Sstevel npgs = bank_size >> PAGESHIFT; 132*29949e86Sstevel 133*29949e86Sstevel if (mem_info->ostate == SYSC_CFGA_OSTATE_CONFIGURED) { 134*29949e86Sstevel bzero(&memq, sizeof (memq)); 135*29949e86Sstevel 136*29949e86Sstevel ret = kphysm_del_span_query(base, npgs, &memq); 137*29949e86Sstevel 138*29949e86Sstevel if (ret != KPHYSM_OK) { 139*29949e86Sstevel fhc_bdlist_unlock(); 140*29949e86Sstevel AC_ERR_SET(pkt, ac_kpm_err_cvt(ret)); 141*29949e86Sstevel retval = EINVAL; 142*29949e86Sstevel goto out; 143*29949e86Sstevel } 144*29949e86Sstevel #ifdef DEBUG 145*29949e86Sstevel if (ac_do_query_check) { 146*29949e86Sstevel query_checker(base, npgs, &memq); 147*29949e86Sstevel if (memq.phys_pages != npgs) { 148*29949e86Sstevel /* 149*29949e86Sstevel * This can happen in normal concurrent 150*29949e86Sstevel * operation. 151*29949e86Sstevel */ 152*29949e86Sstevel cmn_err(CE_WARN, "ac_mem_stat(): " 153*29949e86Sstevel "memq.phys_pages != npgs (%ld != %ld)", 154*29949e86Sstevel (u_long)memq.phys_pages, (u_long)npgs); 155*29949e86Sstevel } 156*29949e86Sstevel } 157*29949e86Sstevel #endif /* DEBUG */ 158*29949e86Sstevel 159*29949e86Sstevel statp->phys_pages = memq.phys_pages; 160*29949e86Sstevel statp->managed = memq.managed; 161*29949e86Sstevel if (!kcage_on) 162*29949e86Sstevel statp->nonrelocatable = memq.phys_pages; 163*29949e86Sstevel else 164*29949e86Sstevel statp->nonrelocatable = memq.nonrelocatable; 165*29949e86Sstevel } else 166*29949e86Sstevel if (mem_info->rstate == SYSC_CFGA_RSTATE_CONNECTED) { 167*29949e86Sstevel /* Bank is in state Spare */ 168*29949e86Sstevel statp->phys_pages = npgs; 169*29949e86Sstevel } 170*29949e86Sstevel 171*29949e86Sstevel fhc_bdlist_unlock(); 172*29949e86Sstevel 173*29949e86Sstevel retval = DDI_SUCCESS; 174*29949e86Sstevel /* return the information to the user */ 175*29949e86Sstevel #ifdef _MULTI_DATAMODEL 176*29949e86Sstevel switch (ddi_model_convert_from(flag & FMODELS)) { 177*29949e86Sstevel case DDI_MODEL_ILP32: { 178*29949e86Sstevel ac_stat32_t *stat32p; 179*29949e86Sstevel 180*29949e86Sstevel stat32p = kmem_zalloc(sizeof (ac_stat32_t), KM_SLEEP); 181*29949e86Sstevel 182*29949e86Sstevel stat32p->rstate = statp->rstate; 183*29949e86Sstevel stat32p->ostate = statp->ostate; 184*29949e86Sstevel stat32p->condition = statp->condition; 185*29949e86Sstevel stat32p->status_time = (time32_t)statp->status_time; 186*29949e86Sstevel stat32p->board = statp->board; 187*29949e86Sstevel stat32p->real_size = statp->real_size; 188*29949e86Sstevel stat32p->use_size = statp->use_size; 189*29949e86Sstevel stat32p->busy = statp->busy; 190*29949e86Sstevel stat32p->page_size = statp->page_size; 191*29949e86Sstevel stat32p->phys_pages = statp->phys_pages; 192*29949e86Sstevel stat32p->managed = statp->managed; 193*29949e86Sstevel stat32p->nonrelocatable = statp->nonrelocatable; 194*29949e86Sstevel stat32p->ac_memctl = statp->ac_memctl; 195*29949e86Sstevel stat32p->ac_decode0 = statp->ac_decode0; 196*29949e86Sstevel stat32p->ac_decode1 = statp->ac_decode1; 197*29949e86Sstevel 198*29949e86Sstevel if (ddi_copyout(stat32p, pkt->cmd_cfga.private, 199*29949e86Sstevel sizeof (ac_stat32_t), flag) != 0) { 200*29949e86Sstevel retval = EFAULT; 201*29949e86Sstevel } 202*29949e86Sstevel kmem_free(stat32p, sizeof (ac_stat32_t)); 203*29949e86Sstevel break; 204*29949e86Sstevel } 205*29949e86Sstevel case DDI_MODEL_NONE: 206*29949e86Sstevel if (ddi_copyout(statp, pkt->cmd_cfga.private, 207*29949e86Sstevel sizeof (ac_stat_t), flag) != 0) { 208*29949e86Sstevel retval = EFAULT; 209*29949e86Sstevel } 210*29949e86Sstevel break; 211*29949e86Sstevel } 212*29949e86Sstevel #else /* _MULTI_DATAMODEL */ 213*29949e86Sstevel if (ddi_copyout(statp, pkt->cmd_cfga.private, 214*29949e86Sstevel sizeof (ac_stat_t), flag) != 0) { 215*29949e86Sstevel retval = EFAULT; 216*29949e86Sstevel } 217*29949e86Sstevel #endif /* _MULTI_DATAMODEL */ 218*29949e86Sstevel 219*29949e86Sstevel out: 220*29949e86Sstevel kmem_free(statp, sizeof (ac_stat_t)); 221*29949e86Sstevel 222*29949e86Sstevel return (retval); 223*29949e86Sstevel } 224*29949e86Sstevel 225*29949e86Sstevel #ifdef DEBUG 226*29949e86Sstevel 227*29949e86Sstevel static void 228*29949e86Sstevel query_checker( 229*29949e86Sstevel pfn_t base, 230*29949e86Sstevel pgcnt_t npgs, 231*29949e86Sstevel memquery_t *mqp) 232*29949e86Sstevel { 233*29949e86Sstevel memquery_t memq; 234*29949e86Sstevel memquery_t amemq; 235*29949e86Sstevel int done_first_nonreloc; 236*29949e86Sstevel int all_pop; 237*29949e86Sstevel pfn_t abase; 238*29949e86Sstevel pgcnt_t n; 239*29949e86Sstevel int ret; 240*29949e86Sstevel 241*29949e86Sstevel all_pop = (mqp->phys_pages == npgs); 242*29949e86Sstevel memq.phys_pages = 0; 243*29949e86Sstevel memq.managed = 0; 244*29949e86Sstevel memq.nonrelocatable = 0; 245*29949e86Sstevel memq.first_nonrelocatable = 0; 246*29949e86Sstevel memq.last_nonrelocatable = 0; 247*29949e86Sstevel done_first_nonreloc = 0; 248*29949e86Sstevel for (abase = base, n = npgs; n != 0; abase++, n--) { 249*29949e86Sstevel ret = kphysm_del_span_query(abase, 1, &amemq); 250*29949e86Sstevel if (ret != KPHYSM_OK) { 251*29949e86Sstevel printf("%ld: ret = %d\n", abase, ret); 252*29949e86Sstevel continue; 253*29949e86Sstevel } 254*29949e86Sstevel if (all_pop && amemq.phys_pages != 1) { 255*29949e86Sstevel printf("%ld: phys_pages = %ld, expected 1\n", 256*29949e86Sstevel abase, amemq.phys_pages); 257*29949e86Sstevel } else 258*29949e86Sstevel if (amemq.phys_pages != 0 && amemq.phys_pages != 1) { 259*29949e86Sstevel printf("%ld: phys_pages = %ld, expected 0 or 1\n", 260*29949e86Sstevel abase, amemq.phys_pages); 261*29949e86Sstevel } 262*29949e86Sstevel memq.phys_pages += amemq.phys_pages; 263*29949e86Sstevel if (amemq.managed != 0 && amemq.managed != 1) { 264*29949e86Sstevel printf("%ld: managed = %ld, expected 0 or 1\n", 265*29949e86Sstevel abase, amemq.managed); 266*29949e86Sstevel } 267*29949e86Sstevel memq.managed += amemq.managed; 268*29949e86Sstevel if (amemq.nonrelocatable != 0 && amemq.nonrelocatable != 1) { 269*29949e86Sstevel printf("%ld: nonrelocatable = %ld, expected 0 or 1\n", 270*29949e86Sstevel abase, amemq.nonrelocatable); 271*29949e86Sstevel } 272*29949e86Sstevel memq.nonrelocatable += amemq.nonrelocatable; 273*29949e86Sstevel if (amemq.nonrelocatable != 0) { 274*29949e86Sstevel if (amemq.first_nonrelocatable != abase) { 275*29949e86Sstevel printf("%ld: first_nonrelocatable = %ld\n", 276*29949e86Sstevel abase, amemq.first_nonrelocatable); 277*29949e86Sstevel } 278*29949e86Sstevel if (amemq.last_nonrelocatable != abase) { 279*29949e86Sstevel printf("%ld: last_nonrelocatable = %ld\n", 280*29949e86Sstevel abase, amemq.last_nonrelocatable); 281*29949e86Sstevel } 282*29949e86Sstevel if (!done_first_nonreloc) { 283*29949e86Sstevel memq.first_nonrelocatable = abase; 284*29949e86Sstevel done_first_nonreloc = 1; 285*29949e86Sstevel } 286*29949e86Sstevel memq.last_nonrelocatable = abase; 287*29949e86Sstevel } 288*29949e86Sstevel } 289*29949e86Sstevel if (mqp->phys_pages != memq.phys_pages) { 290*29949e86Sstevel printf("query phys_pages: %ld != %ld\n", 291*29949e86Sstevel mqp->phys_pages, memq.phys_pages); 292*29949e86Sstevel } 293*29949e86Sstevel if (mqp->managed != memq.managed) { 294*29949e86Sstevel printf("query managed: %ld != %ld\n", 295*29949e86Sstevel mqp->managed, memq.managed); 296*29949e86Sstevel } 297*29949e86Sstevel if (mqp->nonrelocatable != memq.nonrelocatable) { 298*29949e86Sstevel printf("query nonrelocatable: %ld != %ld\n", 299*29949e86Sstevel mqp->nonrelocatable, memq.nonrelocatable); 300*29949e86Sstevel } 301*29949e86Sstevel if (mqp->first_nonrelocatable != memq.first_nonrelocatable) { 302*29949e86Sstevel printf("query first_nonrelocatable: %ld != %ld\n", 303*29949e86Sstevel mqp->first_nonrelocatable, memq.first_nonrelocatable); 304*29949e86Sstevel } 305*29949e86Sstevel if (mqp->last_nonrelocatable != memq.last_nonrelocatable) { 306*29949e86Sstevel printf("query last_nonrelocatable: %ld != %ld\n", 307*29949e86Sstevel mqp->last_nonrelocatable, memq.last_nonrelocatable); 308*29949e86Sstevel } 309*29949e86Sstevel } 310*29949e86Sstevel #endif /* DEBUG */ 311