xref: /onnv-gate/usr/src/uts/sun4u/starfire/os/starfire.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/param.h>
30*0Sstevel@tonic-gate #include <sys/systm.h>
31*0Sstevel@tonic-gate #include <sys/sysmacros.h>
32*0Sstevel@tonic-gate #include <sys/sunddi.h>
33*0Sstevel@tonic-gate #include <sys/modctl.h>
34*0Sstevel@tonic-gate #include <sys/promif.h>
35*0Sstevel@tonic-gate #include <sys/machparam.h>
36*0Sstevel@tonic-gate #include <sys/kobj.h>
37*0Sstevel@tonic-gate #include <sys/mem_cage.h>
38*0Sstevel@tonic-gate #include <sys/starfire.h>
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate #include <sys/platform_module.h>
41*0Sstevel@tonic-gate #include <sys/errno.h>
42*0Sstevel@tonic-gate #include <vm/page.h>
43*0Sstevel@tonic-gate #include <vm/hat_sfmmu.h>
44*0Sstevel@tonic-gate #include <sys/memnode.h>
45*0Sstevel@tonic-gate #include <vm/vm_dep.h>
46*0Sstevel@tonic-gate #include <sys/cpu_sgnblk_defs.h>
47*0Sstevel@tonic-gate #include <sys/cpu_sgn.h>
48*0Sstevel@tonic-gate #include <sys/kdi_impl.h>
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate extern cpu_sgnblk_t *cpu_sgnblkp[];
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate /* Preallocation of spare tsb's for DR - none for now */
53*0Sstevel@tonic-gate int starfire_tsb_spares = STARFIRE_MAX_BOARDS << 1;
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate /* Set the maximum number of boards... for DR */
56*0Sstevel@tonic-gate int starfire_boards = STARFIRE_MAX_BOARDS;
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate /* Maximum number of cpus per board... for DR */
59*0Sstevel@tonic-gate int starfire_cpu_per_board = 4;
60*0Sstevel@tonic-gate 
61*0Sstevel@tonic-gate /* Maximum number of mem-units per board... for DR */
62*0Sstevel@tonic-gate int starfire_mem_per_board = 1;
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate /* Maximum number of io-units (buses) per board... for DR */
65*0Sstevel@tonic-gate int starfire_io_per_board = 2;
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate /* Preferred minimum cage size (expressed in pages)... for DR */
68*0Sstevel@tonic-gate pgcnt_t starfire_startup_cage_size = 0;
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate void sgn_update_all_cpus(ushort_t, uchar_t, uchar_t);
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate int
73*0Sstevel@tonic-gate set_platform_max_ncpus(void)
74*0Sstevel@tonic-gate {
75*0Sstevel@tonic-gate 	starfire_boards = MIN(starfire_boards, STARFIRE_MAX_BOARDS);
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate 	if (starfire_boards < 1)
78*0Sstevel@tonic-gate 		starfire_boards = 1;
79*0Sstevel@tonic-gate 
80*0Sstevel@tonic-gate 	return (starfire_boards * starfire_cpu_per_board);
81*0Sstevel@tonic-gate }
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate void
84*0Sstevel@tonic-gate startup_platform(void)
85*0Sstevel@tonic-gate {
86*0Sstevel@tonic-gate }
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate int
89*0Sstevel@tonic-gate set_platform_tsb_spares()
90*0Sstevel@tonic-gate {
91*0Sstevel@tonic-gate 	return (MIN(starfire_tsb_spares, MAX_UPA));
92*0Sstevel@tonic-gate }
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate void
95*0Sstevel@tonic-gate set_platform_defaults(void)
96*0Sstevel@tonic-gate {
97*0Sstevel@tonic-gate 	extern char *tod_module_name;
98*0Sstevel@tonic-gate 	extern int ts_dispatch_extended;
99*0Sstevel@tonic-gate 	extern void cpu_sgn_update(ushort_t, uchar_t, uchar_t, int);
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate 	uint32_t	revlevel;
102*0Sstevel@tonic-gate 	char		buf[20];
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate #ifdef DEBUG
105*0Sstevel@tonic-gate 	ce_verbose_memory = 2;
106*0Sstevel@tonic-gate 	ce_verbose_other = 2;
107*0Sstevel@tonic-gate #endif
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate 	/*
110*0Sstevel@tonic-gate 	 * Check to see if we have the right firmware
111*0Sstevel@tonic-gate 	 * We simply do a prom_test to see if
112*0Sstevel@tonic-gate 	 * "SUNW,UE10000-prom-version" interface exist.
113*0Sstevel@tonic-gate 	 */
114*0Sstevel@tonic-gate 	if (prom_test("SUNW,UE10000-prom-version") != 0) {
115*0Sstevel@tonic-gate 		halt("Firmware upgrade is required to boot this OS!");
116*0Sstevel@tonic-gate 	} else {
117*0Sstevel@tonic-gate 		/*
118*0Sstevel@tonic-gate 		 * Versions 5 to 50 and 150 or above  can support this OS
119*0Sstevel@tonic-gate 		 */
120*0Sstevel@tonic-gate 		sprintf(buf, "cpu-prom-version swap l!");
121*0Sstevel@tonic-gate 		prom_interpret(buf, (uint32_t)&revlevel, 0, 0, 0, 0);
122*0Sstevel@tonic-gate 		if ((revlevel < 5) || ((revlevel > 50) && (revlevel < 150)))
123*0Sstevel@tonic-gate 			halt("Firmware upgrade is required to boot this OS!");
124*0Sstevel@tonic-gate 	}
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate 	/* Set the CPU signature function pointer */
127*0Sstevel@tonic-gate 	cpu_sgn_func = cpu_sgn_update;
128*0Sstevel@tonic-gate 
129*0Sstevel@tonic-gate 	/* Set appropriate tod module for starfire */
130*0Sstevel@tonic-gate 	ASSERT(tod_module_name == NULL);
131*0Sstevel@tonic-gate 	tod_module_name = "todstarfire";
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate 	/*
134*0Sstevel@tonic-gate 	 * Use the alternate TS dispatch table, which is better
135*0Sstevel@tonic-gate 	 * tuned for large servers.
136*0Sstevel@tonic-gate 	 */
137*0Sstevel@tonic-gate 	if (ts_dispatch_extended == -1) /* use platform default */
138*0Sstevel@tonic-gate 		ts_dispatch_extended = 1;
139*0Sstevel@tonic-gate }
140*0Sstevel@tonic-gate 
141*0Sstevel@tonic-gate #ifdef DEBUG
142*0Sstevel@tonic-gate pgcnt_t starfire_cage_size_limit;
143*0Sstevel@tonic-gate #endif
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate void
146*0Sstevel@tonic-gate set_platform_cage_params(void)
147*0Sstevel@tonic-gate {
148*0Sstevel@tonic-gate 	extern pgcnt_t total_pages;
149*0Sstevel@tonic-gate 	extern struct memlist *phys_avail;
150*0Sstevel@tonic-gate 	int ret;
151*0Sstevel@tonic-gate 
152*0Sstevel@tonic-gate 	if (kernel_cage_enable) {
153*0Sstevel@tonic-gate 		pgcnt_t preferred_cage_size;
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate 		preferred_cage_size =
156*0Sstevel@tonic-gate 			MAX(starfire_startup_cage_size, total_pages / 256);
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate #ifdef DEBUG
159*0Sstevel@tonic-gate 		if (starfire_cage_size_limit)
160*0Sstevel@tonic-gate 			preferred_cage_size = starfire_cage_size_limit;
161*0Sstevel@tonic-gate #endif
162*0Sstevel@tonic-gate 		kcage_range_lock();
163*0Sstevel@tonic-gate 		/*
164*0Sstevel@tonic-gate 		 * Note: we are assuming that post has load the
165*0Sstevel@tonic-gate 		 * whole show in to the high end of memory. Having
166*0Sstevel@tonic-gate 		 * taken this leap, we copy the whole of phys_avail
167*0Sstevel@tonic-gate 		 * the glist and arrange for the cage to grow
168*0Sstevel@tonic-gate 		 * downward (descending pfns).
169*0Sstevel@tonic-gate 		 */
170*0Sstevel@tonic-gate 		ret = kcage_range_init(phys_avail, 1);
171*0Sstevel@tonic-gate 		if (ret == 0)
172*0Sstevel@tonic-gate 			kcage_init(preferred_cage_size);
173*0Sstevel@tonic-gate 		kcage_range_unlock();
174*0Sstevel@tonic-gate 	}
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 	if (kcage_on)
177*0Sstevel@tonic-gate 		cmn_err(CE_NOTE, "!DR Kernel Cage is ENABLED");
178*0Sstevel@tonic-gate 	else
179*0Sstevel@tonic-gate 		cmn_err(CE_NOTE, "!DR Kernel Cage is DISABLED");
180*0Sstevel@tonic-gate }
181*0Sstevel@tonic-gate 
182*0Sstevel@tonic-gate void
183*0Sstevel@tonic-gate load_platform_drivers(void)
184*0Sstevel@tonic-gate {
185*0Sstevel@tonic-gate 	/* load the NGDR driver */
186*0Sstevel@tonic-gate 	if (i_ddi_attach_pseudo_node("ngdr") == NULL) {
187*0Sstevel@tonic-gate 		cmn_err(CE_WARN, "ngdr failed to load");
188*0Sstevel@tonic-gate 	}
189*0Sstevel@tonic-gate }
190*0Sstevel@tonic-gate 
191*0Sstevel@tonic-gate /*
192*0Sstevel@tonic-gate  * Starfire does not support power control of CPUs from the OS.
193*0Sstevel@tonic-gate  */
194*0Sstevel@tonic-gate /*ARGSUSED*/
195*0Sstevel@tonic-gate int
196*0Sstevel@tonic-gate plat_cpu_poweron(struct cpu *cp)
197*0Sstevel@tonic-gate {
198*0Sstevel@tonic-gate 	int (*starfire_cpu_poweron)(struct cpu *) = NULL;
199*0Sstevel@tonic-gate 
200*0Sstevel@tonic-gate 	starfire_cpu_poweron =
201*0Sstevel@tonic-gate 	    (int (*)(struct cpu *))kobj_getsymvalue("drmach_cpu_poweron", 0);
202*0Sstevel@tonic-gate 
203*0Sstevel@tonic-gate 	if (starfire_cpu_poweron == NULL)
204*0Sstevel@tonic-gate 		return (ENOTSUP);
205*0Sstevel@tonic-gate 	else
206*0Sstevel@tonic-gate 		return ((starfire_cpu_poweron)(cp));
207*0Sstevel@tonic-gate }
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate /*ARGSUSED*/
210*0Sstevel@tonic-gate int
211*0Sstevel@tonic-gate plat_cpu_poweroff(struct cpu *cp)
212*0Sstevel@tonic-gate {
213*0Sstevel@tonic-gate 	int (*starfire_cpu_poweroff)(struct cpu *) = NULL;
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate 	starfire_cpu_poweroff =
216*0Sstevel@tonic-gate 	    (int (*)(struct cpu *))kobj_getsymvalue("drmach_cpu_poweroff", 0);
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate 	if (starfire_cpu_poweroff == NULL)
219*0Sstevel@tonic-gate 		return (ENOTSUP);
220*0Sstevel@tonic-gate 	else
221*0Sstevel@tonic-gate 		return ((starfire_cpu_poweroff)(cp));
222*0Sstevel@tonic-gate }
223*0Sstevel@tonic-gate 
224*0Sstevel@tonic-gate void
225*0Sstevel@tonic-gate plat_dmv_params(uint_t *hwint, uint_t *swint)
226*0Sstevel@tonic-gate {
227*0Sstevel@tonic-gate 	*hwint = STARFIRE_DMV_HWINT;
228*0Sstevel@tonic-gate 	*swint = 0;
229*0Sstevel@tonic-gate }
230*0Sstevel@tonic-gate 
231*0Sstevel@tonic-gate /*
232*0Sstevel@tonic-gate  * The following our currently private to Starfire DR
233*0Sstevel@tonic-gate  */
234*0Sstevel@tonic-gate int
235*0Sstevel@tonic-gate plat_max_boards()
236*0Sstevel@tonic-gate {
237*0Sstevel@tonic-gate 	return (starfire_boards);
238*0Sstevel@tonic-gate }
239*0Sstevel@tonic-gate 
240*0Sstevel@tonic-gate int
241*0Sstevel@tonic-gate plat_max_cpu_units_per_board()
242*0Sstevel@tonic-gate {
243*0Sstevel@tonic-gate 	return (starfire_cpu_per_board);
244*0Sstevel@tonic-gate }
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate int
247*0Sstevel@tonic-gate plat_max_mem_units_per_board()
248*0Sstevel@tonic-gate {
249*0Sstevel@tonic-gate 	return (starfire_mem_per_board);
250*0Sstevel@tonic-gate }
251*0Sstevel@tonic-gate 
252*0Sstevel@tonic-gate int
253*0Sstevel@tonic-gate plat_max_io_units_per_board()
254*0Sstevel@tonic-gate {
255*0Sstevel@tonic-gate 	return (starfire_io_per_board);
256*0Sstevel@tonic-gate }
257*0Sstevel@tonic-gate 
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate /*
260*0Sstevel@tonic-gate  * This index is used to associate a given pfn to a place on the freelist.
261*0Sstevel@tonic-gate  * This results in dispersing pfn assignment over all the boards in the
262*0Sstevel@tonic-gate  * system.
263*0Sstevel@tonic-gate  * Choose the index randomly to prevent clustering pages of different
264*0Sstevel@tonic-gate  * colors on the same board.
265*0Sstevel@tonic-gate  */
266*0Sstevel@tonic-gate static uint_t random_idx(int ubound);
267*0Sstevel@tonic-gate 
268*0Sstevel@tonic-gate #define	PFN_2_LBN(pfn)	(((pfn) >> (STARFIRE_MC_MEMBOARD_SHIFT - PAGESHIFT)) % \
269*0Sstevel@tonic-gate 			STARFIRE_MAX_BOARDS)
270*0Sstevel@tonic-gate 
271*0Sstevel@tonic-gate void
272*0Sstevel@tonic-gate plat_freelist_process(int mnode)
273*0Sstevel@tonic-gate {
274*0Sstevel@tonic-gate 	page_t		*page, **freelist;
275*0Sstevel@tonic-gate 	page_t		*bdlist[STARFIRE_MAX_BOARDS];
276*0Sstevel@tonic-gate 	page_t		 **sortlist[STARFIRE_MAX_BOARDS];
277*0Sstevel@tonic-gate 	uint32_t	idx, idy, size, color, max_color, lbn;
278*0Sstevel@tonic-gate 	uint32_t	bd_flags, bd_cnt, result, bds;
279*0Sstevel@tonic-gate 	kmutex_t	*pcm;
280*0Sstevel@tonic-gate 	int 		mtype;
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 	/* for each page size */
283*0Sstevel@tonic-gate 	for (mtype = 0; mtype < MAX_MEM_TYPES; mtype++) {
284*0Sstevel@tonic-gate 		for (size = 0; size < mmu_page_sizes; size++) {
285*0Sstevel@tonic-gate 
286*0Sstevel@tonic-gate 			/*
287*0Sstevel@tonic-gate 			 * Compute the maximum # of phys colors based on
288*0Sstevel@tonic-gate 			 * page size.
289*0Sstevel@tonic-gate 			 */
290*0Sstevel@tonic-gate 			max_color = page_get_pagecolors(size);
291*0Sstevel@tonic-gate 
292*0Sstevel@tonic-gate 			/* for each color */
293*0Sstevel@tonic-gate 			for (color = 0; color < max_color; color++) {
294*0Sstevel@tonic-gate 
295*0Sstevel@tonic-gate 				bd_cnt = 0;
296*0Sstevel@tonic-gate 				bd_flags = 0;
297*0Sstevel@tonic-gate 				for (idx = 0; idx < STARFIRE_MAX_BOARDS;
298*0Sstevel@tonic-gate 						idx++) {
299*0Sstevel@tonic-gate 					bdlist[idx] = NULL;
300*0Sstevel@tonic-gate 					sortlist[idx] = NULL;
301*0Sstevel@tonic-gate 				}
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate 				/* find freelist */
304*0Sstevel@tonic-gate 				freelist = &PAGE_FREELISTS(mnode, size,
305*0Sstevel@tonic-gate 				    color, mtype);
306*0Sstevel@tonic-gate 
307*0Sstevel@tonic-gate 				if (*freelist == NULL)
308*0Sstevel@tonic-gate 					continue;
309*0Sstevel@tonic-gate 
310*0Sstevel@tonic-gate 				/* acquire locks */
311*0Sstevel@tonic-gate 				pcm = PC_BIN_MUTEX(mnode, color, PG_FREE_LIST);
312*0Sstevel@tonic-gate 				mutex_enter(pcm);
313*0Sstevel@tonic-gate 
314*0Sstevel@tonic-gate 				/*
315*0Sstevel@tonic-gate 				 * read freelist & sort pages by logical
316*0Sstevel@tonic-gate 				 * board number
317*0Sstevel@tonic-gate 				 */
318*0Sstevel@tonic-gate 				/* grab pages till last one. */
319*0Sstevel@tonic-gate 				while (*freelist) {
320*0Sstevel@tonic-gate 					page = *freelist;
321*0Sstevel@tonic-gate 					result = page_trylock(page, SE_EXCL);
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate 					ASSERT(result);
324*0Sstevel@tonic-gate 
325*0Sstevel@tonic-gate 					/* Delete from freelist */
326*0Sstevel@tonic-gate 					if (size != 0) {
327*0Sstevel@tonic-gate 						page_vpsub(freelist, page);
328*0Sstevel@tonic-gate 					} else {
329*0Sstevel@tonic-gate 						mach_page_sub(freelist, page);
330*0Sstevel@tonic-gate 					}
331*0Sstevel@tonic-gate 
332*0Sstevel@tonic-gate 					/* detect the lbn */
333*0Sstevel@tonic-gate 					lbn = PFN_2_LBN(page->p_pagenum);
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate 					/* add to bdlist[lbn] */
336*0Sstevel@tonic-gate 					if (size != 0) {
337*0Sstevel@tonic-gate 						page_vpadd(&bdlist[lbn], page);
338*0Sstevel@tonic-gate 					} else {
339*0Sstevel@tonic-gate 						mach_page_add(&bdlist[lbn],
340*0Sstevel@tonic-gate 						    page);
341*0Sstevel@tonic-gate 					}
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate 					/* if lbn new */
344*0Sstevel@tonic-gate 					if ((bd_flags & (1 << lbn)) == 0) {
345*0Sstevel@tonic-gate 						bd_flags |= (1 << lbn);
346*0Sstevel@tonic-gate 						bd_cnt++;
347*0Sstevel@tonic-gate 					}
348*0Sstevel@tonic-gate 					page_unlock(page);
349*0Sstevel@tonic-gate 				}
350*0Sstevel@tonic-gate 
351*0Sstevel@tonic-gate 				/*
352*0Sstevel@tonic-gate 				 * Make the sortlist so
353*0Sstevel@tonic-gate 				 * bd_cnt choices show up
354*0Sstevel@tonic-gate 				 */
355*0Sstevel@tonic-gate 				bds = 0;
356*0Sstevel@tonic-gate 				for (idx = 0; idx < STARFIRE_MAX_BOARDS;
357*0Sstevel@tonic-gate 						idx++) {
358*0Sstevel@tonic-gate 					if (bdlist[idx])
359*0Sstevel@tonic-gate 						sortlist[bds++] = &bdlist[idx];
360*0Sstevel@tonic-gate 				}
361*0Sstevel@tonic-gate 
362*0Sstevel@tonic-gate 				/*
363*0Sstevel@tonic-gate 				 * Set random start.
364*0Sstevel@tonic-gate 				 */
365*0Sstevel@tonic-gate 				(void) random_idx(-color);
366*0Sstevel@tonic-gate 
367*0Sstevel@tonic-gate 				/*
368*0Sstevel@tonic-gate 				 * now rebuild the freelist by shuffling
369*0Sstevel@tonic-gate 				 * pages from bd lists
370*0Sstevel@tonic-gate 				 */
371*0Sstevel@tonic-gate 				while (bd_cnt) {
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate 					/*
374*0Sstevel@tonic-gate 					 * get "random" index between 0 &
375*0Sstevel@tonic-gate 					 * bd_cnt
376*0Sstevel@tonic-gate 					 */
377*0Sstevel@tonic-gate 
378*0Sstevel@tonic-gate 					ASSERT(bd_cnt &&
379*0Sstevel@tonic-gate 					    (bd_cnt < STARFIRE_MAX_BOARDS+1));
380*0Sstevel@tonic-gate 
381*0Sstevel@tonic-gate 					idx = random_idx(bd_cnt);
382*0Sstevel@tonic-gate 
383*0Sstevel@tonic-gate 					page = *sortlist[idx];
384*0Sstevel@tonic-gate 					result = page_trylock(page, SE_EXCL);
385*0Sstevel@tonic-gate 
386*0Sstevel@tonic-gate 					ASSERT(result);
387*0Sstevel@tonic-gate 
388*0Sstevel@tonic-gate 					/* Delete from sort_list */
389*0Sstevel@tonic-gate 					/*  & Append to freelist */
390*0Sstevel@tonic-gate 					/* Big pages use vp_add - 8k don't */
391*0Sstevel@tonic-gate 					if (size != 0) {
392*0Sstevel@tonic-gate 						page_vpsub(sortlist[idx], page);
393*0Sstevel@tonic-gate 						page_vpadd(freelist, page);
394*0Sstevel@tonic-gate 					} else {
395*0Sstevel@tonic-gate 						mach_page_sub(sortlist[idx],
396*0Sstevel@tonic-gate 						    page);
397*0Sstevel@tonic-gate 						mach_page_add(freelist, page);
398*0Sstevel@tonic-gate 					}
399*0Sstevel@tonic-gate 
400*0Sstevel@tonic-gate 					/* needed for indexing tmp lists */
401*0Sstevel@tonic-gate 					lbn = PFN_2_LBN(page->p_pagenum);
402*0Sstevel@tonic-gate 
403*0Sstevel@tonic-gate 					/*
404*0Sstevel@tonic-gate 					 * if this was the last page on this
405*0Sstevel@tonic-gate 					 * list?
406*0Sstevel@tonic-gate 					 */
407*0Sstevel@tonic-gate 					if (*sortlist[idx] == NULL) {
408*0Sstevel@tonic-gate 
409*0Sstevel@tonic-gate 						/* have to find brd list */
410*0Sstevel@tonic-gate 
411*0Sstevel@tonic-gate 						/* idx is lbn? -- No! */
412*0Sstevel@tonic-gate 						/* sortlist, brdlist */
413*0Sstevel@tonic-gate 						/*  have diff indexs */
414*0Sstevel@tonic-gate 						bd_flags &= ~(1 << lbn);
415*0Sstevel@tonic-gate 						--bd_cnt;
416*0Sstevel@tonic-gate 
417*0Sstevel@tonic-gate 						/*
418*0Sstevel@tonic-gate 						 * redo the sortlist so only
419*0Sstevel@tonic-gate 						 * bd_cnt choices show up
420*0Sstevel@tonic-gate 						 */
421*0Sstevel@tonic-gate 						bds = 0;
422*0Sstevel@tonic-gate 						for (idy = 0;
423*0Sstevel@tonic-gate 						    idy < STARFIRE_MAX_BOARDS;
424*0Sstevel@tonic-gate 						    idy++) {
425*0Sstevel@tonic-gate 							if (bdlist[idy]) {
426*0Sstevel@tonic-gate 								sortlist[bds++]
427*0Sstevel@tonic-gate 								= &bdlist[idy];
428*0Sstevel@tonic-gate 							}
429*0Sstevel@tonic-gate 						}
430*0Sstevel@tonic-gate 					}
431*0Sstevel@tonic-gate 					page_unlock(page);
432*0Sstevel@tonic-gate 				}
433*0Sstevel@tonic-gate 				mutex_exit(pcm);
434*0Sstevel@tonic-gate 			}
435*0Sstevel@tonic-gate 		}
436*0Sstevel@tonic-gate 	}
437*0Sstevel@tonic-gate }
438*0Sstevel@tonic-gate 
439*0Sstevel@tonic-gate /*
440*0Sstevel@tonic-gate  * If ubound > 0, will return an int between 0 & ubound
441*0Sstevel@tonic-gate  * If ubound < 0, will set "random seed"
442*0Sstevel@tonic-gate  */
443*0Sstevel@tonic-gate static uint_t
444*0Sstevel@tonic-gate random_idx(int ubound)
445*0Sstevel@tonic-gate {
446*0Sstevel@tonic-gate 	static int idx = 0;
447*0Sstevel@tonic-gate 
448*0Sstevel@tonic-gate 	if (ubound > 0) {
449*0Sstevel@tonic-gate 		idx = (idx + 1) % ubound;
450*0Sstevel@tonic-gate 		return (idx);
451*0Sstevel@tonic-gate 	}
452*0Sstevel@tonic-gate 	idx = -ubound;
453*0Sstevel@tonic-gate 	return (0);
454*0Sstevel@tonic-gate }
455*0Sstevel@tonic-gate 
456*0Sstevel@tonic-gate /*
457*0Sstevel@tonic-gate  * No platform drivers on this platform
458*0Sstevel@tonic-gate  */
459*0Sstevel@tonic-gate char *platform_module_list[] = {
460*0Sstevel@tonic-gate 	(char *)0
461*0Sstevel@tonic-gate };
462*0Sstevel@tonic-gate 
463*0Sstevel@tonic-gate /*ARGSUSED*/
464*0Sstevel@tonic-gate void
465*0Sstevel@tonic-gate plat_tod_fault(enum tod_fault_type tod_bad)
466*0Sstevel@tonic-gate {
467*0Sstevel@tonic-gate }
468*0Sstevel@tonic-gate 
469*0Sstevel@tonic-gate /*
470*0Sstevel@tonic-gate  * Update signature block and the signature ring buffer of a given cpu_id.
471*0Sstevel@tonic-gate  */
472*0Sstevel@tonic-gate void
473*0Sstevel@tonic-gate cpu_sgn_update(ushort_t sgn, uchar_t state, uchar_t sub_state, int cpuid)
474*0Sstevel@tonic-gate {
475*0Sstevel@tonic-gate 	uchar_t idx;
476*0Sstevel@tonic-gate 	cpu_sgnblk_t *cpu_sgnblkptr;
477*0Sstevel@tonic-gate 
478*0Sstevel@tonic-gate 	/*
479*0Sstevel@tonic-gate 	 * cpuid == -1 indicates that the operation applies to all cpus.
480*0Sstevel@tonic-gate 	 */
481*0Sstevel@tonic-gate 	if (cpuid < 0) {
482*0Sstevel@tonic-gate 		sgn_update_all_cpus(sgn, state, sub_state);
483*0Sstevel@tonic-gate 		return;
484*0Sstevel@tonic-gate 	}
485*0Sstevel@tonic-gate 
486*0Sstevel@tonic-gate 	if (cpu_sgnblkp[cpuid] == NULL)
487*0Sstevel@tonic-gate 		return;
488*0Sstevel@tonic-gate 
489*0Sstevel@tonic-gate 	cpu_sgnblkptr = cpu_sgnblkp[cpuid];
490*0Sstevel@tonic-gate 
491*0Sstevel@tonic-gate 	/*
492*0Sstevel@tonic-gate 	 *  Map new generic cpu states to older Starfire states.
493*0Sstevel@tonic-gate 	 */
494*0Sstevel@tonic-gate 	switch (state) {
495*0Sstevel@tonic-gate 	case SIGST_OFFLINE:
496*0Sstevel@tonic-gate 		state = SIGBST_OFFLINE;
497*0Sstevel@tonic-gate 		break;
498*0Sstevel@tonic-gate 	case SIGST_RESUME_INPROGRESS:
499*0Sstevel@tonic-gate 		state = SIGBST_RESUME_INPROGRESS;
500*0Sstevel@tonic-gate 		break;
501*0Sstevel@tonic-gate 	case SIGST_QUIESCE_INPROGRESS:
502*0Sstevel@tonic-gate 		state = SIGBST_QUIESCE_INPROGRESS;
503*0Sstevel@tonic-gate 		break;
504*0Sstevel@tonic-gate 	case SIGST_QUIESCED:
505*0Sstevel@tonic-gate 		state = SIGBST_QUIESCED;
506*0Sstevel@tonic-gate 		break;
507*0Sstevel@tonic-gate 	case SIGST_EXIT:
508*0Sstevel@tonic-gate 		switch (sub_state) {
509*0Sstevel@tonic-gate 		case SIGSUBST_DEBUG:
510*0Sstevel@tonic-gate 			state = SIGBST_RUN;
511*0Sstevel@tonic-gate 			sub_state = EXIT_NULL;
512*0Sstevel@tonic-gate 			break;
513*0Sstevel@tonic-gate 		case SIGSUBST_PANIC_CONT:
514*0Sstevel@tonic-gate 			state = SIGBST_RUN;
515*0Sstevel@tonic-gate 			sub_state = EXIT_PANIC2;
516*0Sstevel@tonic-gate 			break;
517*0Sstevel@tonic-gate 		case SIGSUBST_DUMP:
518*0Sstevel@tonic-gate 			state = SIGBST_EXIT;
519*0Sstevel@tonic-gate 			sub_state = EXIT_PANIC2;
520*0Sstevel@tonic-gate 			break;
521*0Sstevel@tonic-gate 		default:
522*0Sstevel@tonic-gate 			break;
523*0Sstevel@tonic-gate 		}
524*0Sstevel@tonic-gate 		break;
525*0Sstevel@tonic-gate 	default:
526*0Sstevel@tonic-gate 		break;
527*0Sstevel@tonic-gate 	}
528*0Sstevel@tonic-gate 
529*0Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_signature.state_t.sig = sgn;
530*0Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_signature.state_t.state = state;
531*0Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_signature.state_t.sub_state = sub_state;
532*0Sstevel@tonic-gate 
533*0Sstevel@tonic-gate 	/* Update the ring buffer */
534*0Sstevel@tonic-gate 	idx = cpu_sgnblkptr->sigb_ringbuf.wr_ptr;
535*0Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.sig = sgn;
536*0Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.state = state;
537*0Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.sub_state = sub_state;
538*0Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_ringbuf.wr_ptr += 1;
539*0Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_ringbuf.wr_ptr &= RB_IDX_MASK;
540*0Sstevel@tonic-gate }
541*0Sstevel@tonic-gate 
542*0Sstevel@tonic-gate /*
543*0Sstevel@tonic-gate  * Update signature block and the signature ring buffer of all CPUs.
544*0Sstevel@tonic-gate  */
545*0Sstevel@tonic-gate void
546*0Sstevel@tonic-gate sgn_update_all_cpus(ushort_t sgn, uchar_t state, uchar_t sub_state)
547*0Sstevel@tonic-gate {
548*0Sstevel@tonic-gate 	int i = 0;
549*0Sstevel@tonic-gate 	uchar_t cpu_state;
550*0Sstevel@tonic-gate 	uchar_t cpu_sub_state;
551*0Sstevel@tonic-gate 
552*0Sstevel@tonic-gate 	for (i = 0; i < NCPU; i++) {
553*0Sstevel@tonic-gate 		cpu_sgnblk_t *sblkp;
554*0Sstevel@tonic-gate 
555*0Sstevel@tonic-gate 		sblkp = cpu_sgnblkp[i];
556*0Sstevel@tonic-gate 		cpu_sub_state = sub_state;
557*0Sstevel@tonic-gate 
558*0Sstevel@tonic-gate 		if ((sblkp != NULL) && (cpu[i] != NULL && (cpu[i]->cpu_flags &
559*0Sstevel@tonic-gate 				(CPU_EXISTS|CPU_QUIESCED)))) {
560*0Sstevel@tonic-gate 
561*0Sstevel@tonic-gate 			if (sub_state == EXIT_REBOOT) {
562*0Sstevel@tonic-gate 				cpu_sub_state =
563*0Sstevel@tonic-gate 					sblkp->sigb_signature.state_t.sub_state;
564*0Sstevel@tonic-gate 
565*0Sstevel@tonic-gate 				if ((cpu_sub_state == EXIT_PANIC1) ||
566*0Sstevel@tonic-gate 					(cpu_sub_state == EXIT_PANIC2))
567*0Sstevel@tonic-gate 					cpu_sub_state = EXIT_PANIC_REBOOT;
568*0Sstevel@tonic-gate 				else
569*0Sstevel@tonic-gate 					cpu_sub_state = EXIT_REBOOT;
570*0Sstevel@tonic-gate 			}
571*0Sstevel@tonic-gate 
572*0Sstevel@tonic-gate 			/*
573*0Sstevel@tonic-gate 			 * If we get here from an OBP sync after watchdog,
574*0Sstevel@tonic-gate 			 * we need to retain the watchdog sync state so that
575*0Sstevel@tonic-gate 			 * hostmon knows what's going on.  So if we're in
576*0Sstevel@tonic-gate 			 * watchdog we don't update the state.
577*0Sstevel@tonic-gate 			 */
578*0Sstevel@tonic-gate 
579*0Sstevel@tonic-gate 			cpu_state = sblkp->sigb_signature.state_t.state;
580*0Sstevel@tonic-gate 			if (cpu_state == SIGBST_WATCHDOG_SYNC)
581*0Sstevel@tonic-gate 				cpu_sgn_update(sgn, SIGBST_WATCHDOG_SYNC,
582*0Sstevel@tonic-gate 					cpu_sub_state, i);
583*0Sstevel@tonic-gate 			else if (cpu_state == SIGBST_REDMODE_SYNC)
584*0Sstevel@tonic-gate 				cpu_sgn_update(sgn, SIGBST_REDMODE_SYNC,
585*0Sstevel@tonic-gate 					cpu_sub_state, i);
586*0Sstevel@tonic-gate 			else
587*0Sstevel@tonic-gate 				cpu_sgn_update(sgn, state, cpu_sub_state, i);
588*0Sstevel@tonic-gate 		}
589*0Sstevel@tonic-gate 	}
590*0Sstevel@tonic-gate }
591*0Sstevel@tonic-gate 
592*0Sstevel@tonic-gate int
593*0Sstevel@tonic-gate cpu_sgn_exists(int cpuid)
594*0Sstevel@tonic-gate {
595*0Sstevel@tonic-gate 	return (cpu_sgnblkp[cpuid] != NULL);
596*0Sstevel@tonic-gate }
597*0Sstevel@tonic-gate 
598*0Sstevel@tonic-gate ushort_t
599*0Sstevel@tonic-gate get_cpu_sgn(int cpuid)
600*0Sstevel@tonic-gate {
601*0Sstevel@tonic-gate 	if (cpu_sgnblkp[cpuid] == NULL)
602*0Sstevel@tonic-gate 		return ((ushort_t)-1);
603*0Sstevel@tonic-gate 
604*0Sstevel@tonic-gate 	return (cpu_sgnblkp[cpuid]->sigb_signature.state_t.sig);
605*0Sstevel@tonic-gate }
606*0Sstevel@tonic-gate 
607*0Sstevel@tonic-gate uchar_t
608*0Sstevel@tonic-gate get_cpu_sgn_state(int cpuid)
609*0Sstevel@tonic-gate {
610*0Sstevel@tonic-gate 	if (cpu_sgnblkp[cpuid] == NULL)
611*0Sstevel@tonic-gate 		return ((uchar_t)-1);
612*0Sstevel@tonic-gate 
613*0Sstevel@tonic-gate 	return (cpu_sgnblkp[cpuid]->sigb_signature.state_t.state);
614*0Sstevel@tonic-gate }
615*0Sstevel@tonic-gate 
616*0Sstevel@tonic-gate /*
617*0Sstevel@tonic-gate  * KDI functions - used by the in-situ kernel debugger (kmdb) to perform
618*0Sstevel@tonic-gate  * platform-specific operations.  These functions execute when the world is
619*0Sstevel@tonic-gate  * stopped, and as such cannot make any blocking calls, hold locks, etc.
620*0Sstevel@tonic-gate  * promif functions are a special case, and may be used.
621*0Sstevel@tonic-gate  */
622*0Sstevel@tonic-gate 
623*0Sstevel@tonic-gate static void
624*0Sstevel@tonic-gate starfire_system_claim(void)
625*0Sstevel@tonic-gate {
626*0Sstevel@tonic-gate 	prom_interpret("sigb-sig! my-sigb-sig!", OBP_SIG, OBP_SIG, 0, 0, 0);
627*0Sstevel@tonic-gate }
628*0Sstevel@tonic-gate 
629*0Sstevel@tonic-gate static void
630*0Sstevel@tonic-gate starfire_system_release(void)
631*0Sstevel@tonic-gate {
632*0Sstevel@tonic-gate 	prom_interpret("sigb-sig! my-sigb-sig!", OS_SIG, OS_SIG, 0, 0, 0);
633*0Sstevel@tonic-gate }
634*0Sstevel@tonic-gate 
635*0Sstevel@tonic-gate void
636*0Sstevel@tonic-gate plat_kdi_init(kdi_t *kdi)
637*0Sstevel@tonic-gate {
638*0Sstevel@tonic-gate 	kdi->pkdi_system_claim = starfire_system_claim;
639*0Sstevel@tonic-gate 	kdi->pkdi_system_release = starfire_system_release;
640*0Sstevel@tonic-gate }
641