xref: /titanic_51/usr/src/uts/sun4u/sunfire/io/ac_stat.c (revision 29949e866e40b95795203f3ee46f44a197c946e4)
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