xref: /titanic_51/usr/src/uts/sun4u/starfire/os/starfire.c (revision d94ffb286aba68edc813c6eda61754891db7f7a1)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
585f58038Sdp78419  * Common Development and Distribution License (the "License").
685f58038Sdp78419  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2107d06da5SSurya Prakki 
227c478bd9Sstevel@tonic-gate /*
23*d94ffb28Sjmcp  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*d94ffb28Sjmcp  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <sys/param.h>
287c478bd9Sstevel@tonic-gate #include <sys/systm.h>
297c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
307c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
317c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
327c478bd9Sstevel@tonic-gate #include <sys/promif.h>
337c478bd9Sstevel@tonic-gate #include <sys/machparam.h>
347c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
357c478bd9Sstevel@tonic-gate #include <sys/mem_cage.h>
367c478bd9Sstevel@tonic-gate #include <sys/starfire.h>
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #include <sys/platform_module.h>
397c478bd9Sstevel@tonic-gate #include <sys/errno.h>
407c478bd9Sstevel@tonic-gate #include <vm/page.h>
417c478bd9Sstevel@tonic-gate #include <vm/hat_sfmmu.h>
427c478bd9Sstevel@tonic-gate #include <sys/memnode.h>
437c478bd9Sstevel@tonic-gate #include <vm/vm_dep.h>
447c478bd9Sstevel@tonic-gate #include <sys/cpu_sgnblk_defs.h>
457c478bd9Sstevel@tonic-gate #include <sys/cpu_sgn.h>
467c478bd9Sstevel@tonic-gate #include <sys/kdi_impl.h>
47d3d50737SRafael Vanoni #include <sys/clock_impl.h>
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate extern cpu_sgnblk_t *cpu_sgnblkp[];
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate /* Preallocation of spare tsb's for DR - none for now */
527c478bd9Sstevel@tonic-gate int starfire_tsb_spares = STARFIRE_MAX_BOARDS << 1;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /* Set the maximum number of boards... for DR */
557c478bd9Sstevel@tonic-gate int starfire_boards = STARFIRE_MAX_BOARDS;
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate /* Maximum number of cpus per board... for DR */
587c478bd9Sstevel@tonic-gate int starfire_cpu_per_board = 4;
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate /* Maximum number of mem-units per board... for DR */
617c478bd9Sstevel@tonic-gate int starfire_mem_per_board = 1;
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate /* Maximum number of io-units (buses) per board... for DR */
647c478bd9Sstevel@tonic-gate int starfire_io_per_board = 2;
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate /* Preferred minimum cage size (expressed in pages)... for DR */
677c478bd9Sstevel@tonic-gate pgcnt_t starfire_startup_cage_size = 0;
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate void sgn_update_all_cpus(ushort_t, uchar_t, uchar_t);
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate int
727c478bd9Sstevel@tonic-gate set_platform_max_ncpus(void)
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate 	starfire_boards = MIN(starfire_boards, STARFIRE_MAX_BOARDS);
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 	if (starfire_boards < 1)
777c478bd9Sstevel@tonic-gate 		starfire_boards = 1;
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 	return (starfire_boards * starfire_cpu_per_board);
807c478bd9Sstevel@tonic-gate }
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate void
837c478bd9Sstevel@tonic-gate startup_platform(void)
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate }
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate int
887c478bd9Sstevel@tonic-gate set_platform_tsb_spares()
897c478bd9Sstevel@tonic-gate {
907c478bd9Sstevel@tonic-gate 	return (MIN(starfire_tsb_spares, MAX_UPA));
917c478bd9Sstevel@tonic-gate }
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate void
947c478bd9Sstevel@tonic-gate set_platform_defaults(void)
957c478bd9Sstevel@tonic-gate {
967c478bd9Sstevel@tonic-gate 	extern char *tod_module_name;
977c478bd9Sstevel@tonic-gate 	extern int ts_dispatch_extended;
987c478bd9Sstevel@tonic-gate 	extern void cpu_sgn_update(ushort_t, uchar_t, uchar_t, int);
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	uint32_t	revlevel;
1017c478bd9Sstevel@tonic-gate 	char		buf[20];
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate #ifdef DEBUG
1047c478bd9Sstevel@tonic-gate 	ce_verbose_memory = 2;
1057c478bd9Sstevel@tonic-gate 	ce_verbose_other = 2;
1067c478bd9Sstevel@tonic-gate #endif
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	/*
1097c478bd9Sstevel@tonic-gate 	 * Check to see if we have the right firmware
1107c478bd9Sstevel@tonic-gate 	 * We simply do a prom_test to see if
1117c478bd9Sstevel@tonic-gate 	 * "SUNW,UE10000-prom-version" interface exist.
1127c478bd9Sstevel@tonic-gate 	 */
1137c478bd9Sstevel@tonic-gate 	if (prom_test("SUNW,UE10000-prom-version") != 0) {
1147c478bd9Sstevel@tonic-gate 		halt("Firmware upgrade is required to boot this OS!");
1157c478bd9Sstevel@tonic-gate 	} else {
1167c478bd9Sstevel@tonic-gate 		/*
1177c478bd9Sstevel@tonic-gate 		 * Versions 5 to 50 and 150 or above  can support this OS
1187c478bd9Sstevel@tonic-gate 		 */
11907d06da5SSurya Prakki 		(void) sprintf(buf, "cpu-prom-version swap l!");
120360e6f5eSmathue 		prom_interpret(buf, (uintptr_t)&revlevel, 0, 0, 0, 0);
1217c478bd9Sstevel@tonic-gate 		if ((revlevel < 5) || ((revlevel > 50) && (revlevel < 150)))
1227c478bd9Sstevel@tonic-gate 			halt("Firmware upgrade is required to boot this OS!");
1237c478bd9Sstevel@tonic-gate 	}
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	/* Set the CPU signature function pointer */
1267c478bd9Sstevel@tonic-gate 	cpu_sgn_func = cpu_sgn_update;
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	/* Set appropriate tod module for starfire */
1297c478bd9Sstevel@tonic-gate 	ASSERT(tod_module_name == NULL);
1307c478bd9Sstevel@tonic-gate 	tod_module_name = "todstarfire";
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	/*
1337c478bd9Sstevel@tonic-gate 	 * Use the alternate TS dispatch table, which is better
1347c478bd9Sstevel@tonic-gate 	 * tuned for large servers.
1357c478bd9Sstevel@tonic-gate 	 */
1367c478bd9Sstevel@tonic-gate 	if (ts_dispatch_extended == -1) /* use platform default */
1377c478bd9Sstevel@tonic-gate 		ts_dispatch_extended = 1;
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate #ifdef DEBUG
1417c478bd9Sstevel@tonic-gate pgcnt_t starfire_cage_size_limit;
1427c478bd9Sstevel@tonic-gate #endif
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate void
1457c478bd9Sstevel@tonic-gate set_platform_cage_params(void)
1467c478bd9Sstevel@tonic-gate {
1477c478bd9Sstevel@tonic-gate 	extern pgcnt_t total_pages;
1487c478bd9Sstevel@tonic-gate 	extern struct memlist *phys_avail;
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	if (kernel_cage_enable) {
1517c478bd9Sstevel@tonic-gate 		pgcnt_t preferred_cage_size;
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 		preferred_cage_size =
1547c478bd9Sstevel@tonic-gate 		    MAX(starfire_startup_cage_size, total_pages / 256);
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate #ifdef DEBUG
1577c478bd9Sstevel@tonic-gate 		if (starfire_cage_size_limit)
1587c478bd9Sstevel@tonic-gate 			preferred_cage_size = starfire_cage_size_limit;
1597c478bd9Sstevel@tonic-gate #endif
1607c478bd9Sstevel@tonic-gate 		/*
1617c478bd9Sstevel@tonic-gate 		 * Note: we are assuming that post has load the
1627c478bd9Sstevel@tonic-gate 		 * whole show in to the high end of memory. Having
1637c478bd9Sstevel@tonic-gate 		 * taken this leap, we copy the whole of phys_avail
1647c478bd9Sstevel@tonic-gate 		 * the glist and arrange for the cage to grow
1657c478bd9Sstevel@tonic-gate 		 * downward (descending pfns).
1667c478bd9Sstevel@tonic-gate 		 */
16785f58038Sdp78419 		kcage_range_init(phys_avail, KCAGE_DOWN, preferred_cage_size);
1687c478bd9Sstevel@tonic-gate 	}
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	if (kcage_on)
1717c478bd9Sstevel@tonic-gate 		cmn_err(CE_NOTE, "!DR Kernel Cage is ENABLED");
1727c478bd9Sstevel@tonic-gate 	else
1737c478bd9Sstevel@tonic-gate 		cmn_err(CE_NOTE, "!DR Kernel Cage is DISABLED");
1747c478bd9Sstevel@tonic-gate }
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate void
1777c478bd9Sstevel@tonic-gate load_platform_drivers(void)
1787c478bd9Sstevel@tonic-gate {
1797c478bd9Sstevel@tonic-gate 	/* load the NGDR driver */
1807c478bd9Sstevel@tonic-gate 	if (i_ddi_attach_pseudo_node("ngdr") == NULL) {
1817c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "ngdr failed to load");
1827c478bd9Sstevel@tonic-gate 	}
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate /*
1867c478bd9Sstevel@tonic-gate  * Starfire does not support power control of CPUs from the OS.
1877c478bd9Sstevel@tonic-gate  */
1887c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1897c478bd9Sstevel@tonic-gate int
1907c478bd9Sstevel@tonic-gate plat_cpu_poweron(struct cpu *cp)
1917c478bd9Sstevel@tonic-gate {
1927c478bd9Sstevel@tonic-gate 	int (*starfire_cpu_poweron)(struct cpu *) = NULL;
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	starfire_cpu_poweron =
1957c478bd9Sstevel@tonic-gate 	    (int (*)(struct cpu *))kobj_getsymvalue("drmach_cpu_poweron", 0);
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	if (starfire_cpu_poweron == NULL)
1987c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
1997c478bd9Sstevel@tonic-gate 	else
2007c478bd9Sstevel@tonic-gate 		return ((starfire_cpu_poweron)(cp));
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2047c478bd9Sstevel@tonic-gate int
2057c478bd9Sstevel@tonic-gate plat_cpu_poweroff(struct cpu *cp)
2067c478bd9Sstevel@tonic-gate {
2077c478bd9Sstevel@tonic-gate 	int (*starfire_cpu_poweroff)(struct cpu *) = NULL;
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	starfire_cpu_poweroff =
2107c478bd9Sstevel@tonic-gate 	    (int (*)(struct cpu *))kobj_getsymvalue("drmach_cpu_poweroff", 0);
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 	if (starfire_cpu_poweroff == NULL)
2137c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
2147c478bd9Sstevel@tonic-gate 	else
2157c478bd9Sstevel@tonic-gate 		return ((starfire_cpu_poweroff)(cp));
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate void
2197c478bd9Sstevel@tonic-gate plat_dmv_params(uint_t *hwint, uint_t *swint)
2207c478bd9Sstevel@tonic-gate {
2217c478bd9Sstevel@tonic-gate 	*hwint = STARFIRE_DMV_HWINT;
2227c478bd9Sstevel@tonic-gate 	*swint = 0;
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate /*
2267c478bd9Sstevel@tonic-gate  * The following our currently private to Starfire DR
2277c478bd9Sstevel@tonic-gate  */
2287c478bd9Sstevel@tonic-gate int
2297c478bd9Sstevel@tonic-gate plat_max_boards()
2307c478bd9Sstevel@tonic-gate {
2317c478bd9Sstevel@tonic-gate 	return (starfire_boards);
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate int
2357c478bd9Sstevel@tonic-gate plat_max_cpu_units_per_board()
2367c478bd9Sstevel@tonic-gate {
2377c478bd9Sstevel@tonic-gate 	return (starfire_cpu_per_board);
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate int
2417c478bd9Sstevel@tonic-gate plat_max_mem_units_per_board()
2427c478bd9Sstevel@tonic-gate {
2437c478bd9Sstevel@tonic-gate 	return (starfire_mem_per_board);
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate int
2477c478bd9Sstevel@tonic-gate plat_max_io_units_per_board()
2487c478bd9Sstevel@tonic-gate {
2497c478bd9Sstevel@tonic-gate 	return (starfire_io_per_board);
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate /*
2547c478bd9Sstevel@tonic-gate  * This index is used to associate a given pfn to a place on the freelist.
2557c478bd9Sstevel@tonic-gate  * This results in dispersing pfn assignment over all the boards in the
2567c478bd9Sstevel@tonic-gate  * system.
2577c478bd9Sstevel@tonic-gate  * Choose the index randomly to prevent clustering pages of different
2587c478bd9Sstevel@tonic-gate  * colors on the same board.
2597c478bd9Sstevel@tonic-gate  */
2607c478bd9Sstevel@tonic-gate static uint_t random_idx(int ubound);
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate #define	PFN_2_LBN(pfn)	(((pfn) >> (STARFIRE_MC_MEMBOARD_SHIFT - PAGESHIFT)) % \
2637c478bd9Sstevel@tonic-gate 			STARFIRE_MAX_BOARDS)
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate void
2667c478bd9Sstevel@tonic-gate plat_freelist_process(int mnode)
2677c478bd9Sstevel@tonic-gate {
2687c478bd9Sstevel@tonic-gate 	page_t		*page, **freelist;
2697c478bd9Sstevel@tonic-gate 	page_t		*bdlist[STARFIRE_MAX_BOARDS];
2707c478bd9Sstevel@tonic-gate 	page_t		 **sortlist[STARFIRE_MAX_BOARDS];
2717c478bd9Sstevel@tonic-gate 	uint32_t	idx, idy, size, color, max_color, lbn;
2727c478bd9Sstevel@tonic-gate 	uint32_t	bd_flags, bd_cnt, result, bds;
2737c478bd9Sstevel@tonic-gate 	kmutex_t	*pcm;
2747c478bd9Sstevel@tonic-gate 	int 		mtype;
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	/* for each page size */
2777c478bd9Sstevel@tonic-gate 	for (mtype = 0; mtype < MAX_MEM_TYPES; mtype++) {
2787c478bd9Sstevel@tonic-gate 		for (size = 0; size < mmu_page_sizes; size++) {
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 			/*
2817c478bd9Sstevel@tonic-gate 			 * Compute the maximum # of phys colors based on
2827c478bd9Sstevel@tonic-gate 			 * page size.
2837c478bd9Sstevel@tonic-gate 			 */
2847c478bd9Sstevel@tonic-gate 			max_color = page_get_pagecolors(size);
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 			/* for each color */
2877c478bd9Sstevel@tonic-gate 			for (color = 0; color < max_color; color++) {
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 				bd_cnt = 0;
2907c478bd9Sstevel@tonic-gate 				bd_flags = 0;
2917c478bd9Sstevel@tonic-gate 				for (idx = 0; idx < STARFIRE_MAX_BOARDS;
2927c478bd9Sstevel@tonic-gate 				    idx++) {
2937c478bd9Sstevel@tonic-gate 					bdlist[idx] = NULL;
2947c478bd9Sstevel@tonic-gate 					sortlist[idx] = NULL;
2957c478bd9Sstevel@tonic-gate 				}
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 				/* find freelist */
298*d94ffb28Sjmcp 				freelist = &PAGE_FREELISTS(mnode, size,
299*d94ffb28Sjmcp 				    color, mtype);
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 				if (*freelist == NULL)
3027c478bd9Sstevel@tonic-gate 					continue;
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 				/* acquire locks */
305*d94ffb28Sjmcp 				pcm = PC_BIN_MUTEX(mnode, color, PG_FREE_LIST);
3067c478bd9Sstevel@tonic-gate 				mutex_enter(pcm);
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 				/*
3097c478bd9Sstevel@tonic-gate 				 * read freelist & sort pages by logical
3107c478bd9Sstevel@tonic-gate 				 * board number
3117c478bd9Sstevel@tonic-gate 				 */
3127c478bd9Sstevel@tonic-gate 				/* grab pages till last one. */
3137c478bd9Sstevel@tonic-gate 				while (*freelist) {
3147c478bd9Sstevel@tonic-gate 					page = *freelist;
3157c478bd9Sstevel@tonic-gate 					result = page_trylock(page, SE_EXCL);
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 					ASSERT(result);
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 					/* Delete from freelist */
3207c478bd9Sstevel@tonic-gate 					if (size != 0) {
3217c478bd9Sstevel@tonic-gate 						page_vpsub(freelist, page);
3227c478bd9Sstevel@tonic-gate 					} else {
3237c478bd9Sstevel@tonic-gate 						mach_page_sub(freelist, page);
3247c478bd9Sstevel@tonic-gate 					}
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 					/* detect the lbn */
3277c478bd9Sstevel@tonic-gate 					lbn = PFN_2_LBN(page->p_pagenum);
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 					/* add to bdlist[lbn] */
3307c478bd9Sstevel@tonic-gate 					if (size != 0) {
3317c478bd9Sstevel@tonic-gate 						page_vpadd(&bdlist[lbn], page);
3327c478bd9Sstevel@tonic-gate 					} else {
3337c478bd9Sstevel@tonic-gate 						mach_page_add(&bdlist[lbn],
3347c478bd9Sstevel@tonic-gate 						    page);
3357c478bd9Sstevel@tonic-gate 					}
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 					/* if lbn new */
3387c478bd9Sstevel@tonic-gate 					if ((bd_flags & (1 << lbn)) == 0) {
3397c478bd9Sstevel@tonic-gate 						bd_flags |= (1 << lbn);
3407c478bd9Sstevel@tonic-gate 						bd_cnt++;
3417c478bd9Sstevel@tonic-gate 					}
3427c478bd9Sstevel@tonic-gate 					page_unlock(page);
3437c478bd9Sstevel@tonic-gate 				}
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 				/*
3467c478bd9Sstevel@tonic-gate 				 * Make the sortlist so
3477c478bd9Sstevel@tonic-gate 				 * bd_cnt choices show up
3487c478bd9Sstevel@tonic-gate 				 */
3497c478bd9Sstevel@tonic-gate 				bds = 0;
3507c478bd9Sstevel@tonic-gate 				for (idx = 0; idx < STARFIRE_MAX_BOARDS;
3517c478bd9Sstevel@tonic-gate 				    idx++) {
3527c478bd9Sstevel@tonic-gate 					if (bdlist[idx])
3537c478bd9Sstevel@tonic-gate 						sortlist[bds++] = &bdlist[idx];
3547c478bd9Sstevel@tonic-gate 				}
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 				/*
3577c478bd9Sstevel@tonic-gate 				 * Set random start.
3587c478bd9Sstevel@tonic-gate 				 */
3597c478bd9Sstevel@tonic-gate 				(void) random_idx(-color);
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 				/*
3627c478bd9Sstevel@tonic-gate 				 * now rebuild the freelist by shuffling
3637c478bd9Sstevel@tonic-gate 				 * pages from bd lists
3647c478bd9Sstevel@tonic-gate 				 */
3657c478bd9Sstevel@tonic-gate 				while (bd_cnt) {
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 					/*
3687c478bd9Sstevel@tonic-gate 					 * get "random" index between 0 &
3697c478bd9Sstevel@tonic-gate 					 * bd_cnt
3707c478bd9Sstevel@tonic-gate 					 */
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 					ASSERT(bd_cnt &&
3737c478bd9Sstevel@tonic-gate 					    (bd_cnt < STARFIRE_MAX_BOARDS+1));
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 					idx = random_idx(bd_cnt);
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 					page = *sortlist[idx];
3787c478bd9Sstevel@tonic-gate 					result = page_trylock(page, SE_EXCL);
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 					ASSERT(result);
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 					/* Delete from sort_list */
3837c478bd9Sstevel@tonic-gate 					/*  & Append to freelist */
3847c478bd9Sstevel@tonic-gate 					/* Big pages use vp_add - 8k don't */
3857c478bd9Sstevel@tonic-gate 					if (size != 0) {
3867c478bd9Sstevel@tonic-gate 						page_vpsub(sortlist[idx], page);
3877c478bd9Sstevel@tonic-gate 						page_vpadd(freelist, page);
3887c478bd9Sstevel@tonic-gate 					} else {
3897c478bd9Sstevel@tonic-gate 						mach_page_sub(sortlist[idx],
3907c478bd9Sstevel@tonic-gate 						    page);
3917c478bd9Sstevel@tonic-gate 						mach_page_add(freelist, page);
3927c478bd9Sstevel@tonic-gate 					}
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 					/* needed for indexing tmp lists */
3957c478bd9Sstevel@tonic-gate 					lbn = PFN_2_LBN(page->p_pagenum);
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 					/*
3987c478bd9Sstevel@tonic-gate 					 * if this was the last page on this
3997c478bd9Sstevel@tonic-gate 					 * list?
4007c478bd9Sstevel@tonic-gate 					 */
4017c478bd9Sstevel@tonic-gate 					if (*sortlist[idx] == NULL) {
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 						/* have to find brd list */
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 						/* idx is lbn? -- No! */
4067c478bd9Sstevel@tonic-gate 						/* sortlist, brdlist */
4077c478bd9Sstevel@tonic-gate 						/*  have diff indexs */
4087c478bd9Sstevel@tonic-gate 						bd_flags &= ~(1 << lbn);
4097c478bd9Sstevel@tonic-gate 						--bd_cnt;
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 						/*
4127c478bd9Sstevel@tonic-gate 						 * redo the sortlist so only
4137c478bd9Sstevel@tonic-gate 						 * bd_cnt choices show up
4147c478bd9Sstevel@tonic-gate 						 */
4157c478bd9Sstevel@tonic-gate 						bds = 0;
4167c478bd9Sstevel@tonic-gate 						for (idy = 0;
4177c478bd9Sstevel@tonic-gate 						    idy < STARFIRE_MAX_BOARDS;
4187c478bd9Sstevel@tonic-gate 						    idy++) {
4197c478bd9Sstevel@tonic-gate 							if (bdlist[idy]) {
4207c478bd9Sstevel@tonic-gate 								sortlist[bds++]
421d3d50737SRafael Vanoni 								/* CSTYLED */
4227c478bd9Sstevel@tonic-gate 								= &bdlist[idy];
4237c478bd9Sstevel@tonic-gate 							}
4247c478bd9Sstevel@tonic-gate 						}
4257c478bd9Sstevel@tonic-gate 					}
4267c478bd9Sstevel@tonic-gate 					page_unlock(page);
4277c478bd9Sstevel@tonic-gate 				}
4287c478bd9Sstevel@tonic-gate 				mutex_exit(pcm);
4297c478bd9Sstevel@tonic-gate 			}
4307c478bd9Sstevel@tonic-gate 		}
4317c478bd9Sstevel@tonic-gate 	}
4327c478bd9Sstevel@tonic-gate }
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate /*
4357c478bd9Sstevel@tonic-gate  * If ubound > 0, will return an int between 0 & ubound
4367c478bd9Sstevel@tonic-gate  * If ubound < 0, will set "random seed"
4377c478bd9Sstevel@tonic-gate  */
4387c478bd9Sstevel@tonic-gate static uint_t
4397c478bd9Sstevel@tonic-gate random_idx(int ubound)
4407c478bd9Sstevel@tonic-gate {
4417c478bd9Sstevel@tonic-gate 	static int idx = 0;
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	if (ubound > 0) {
4447c478bd9Sstevel@tonic-gate 		idx = (idx + 1) % ubound;
4457c478bd9Sstevel@tonic-gate 		return (idx);
4467c478bd9Sstevel@tonic-gate 	}
4477c478bd9Sstevel@tonic-gate 	idx = -ubound;
4487c478bd9Sstevel@tonic-gate 	return (0);
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate /*
4527c478bd9Sstevel@tonic-gate  * No platform drivers on this platform
4537c478bd9Sstevel@tonic-gate  */
4547c478bd9Sstevel@tonic-gate char *platform_module_list[] = {
4557c478bd9Sstevel@tonic-gate 	(char *)0
4567c478bd9Sstevel@tonic-gate };
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4597c478bd9Sstevel@tonic-gate void
4607c478bd9Sstevel@tonic-gate plat_tod_fault(enum tod_fault_type tod_bad)
4617c478bd9Sstevel@tonic-gate {
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate /*
4657c478bd9Sstevel@tonic-gate  * Update signature block and the signature ring buffer of a given cpu_id.
4667c478bd9Sstevel@tonic-gate  */
4677c478bd9Sstevel@tonic-gate void
4687c478bd9Sstevel@tonic-gate cpu_sgn_update(ushort_t sgn, uchar_t state, uchar_t sub_state, int cpuid)
4697c478bd9Sstevel@tonic-gate {
4707c478bd9Sstevel@tonic-gate 	uchar_t idx;
4717c478bd9Sstevel@tonic-gate 	cpu_sgnblk_t *cpu_sgnblkptr;
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	/*
4747c478bd9Sstevel@tonic-gate 	 * cpuid == -1 indicates that the operation applies to all cpus.
4757c478bd9Sstevel@tonic-gate 	 */
4767c478bd9Sstevel@tonic-gate 	if (cpuid < 0) {
4777c478bd9Sstevel@tonic-gate 		sgn_update_all_cpus(sgn, state, sub_state);
4787c478bd9Sstevel@tonic-gate 		return;
4797c478bd9Sstevel@tonic-gate 	}
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	if (cpu_sgnblkp[cpuid] == NULL)
4827c478bd9Sstevel@tonic-gate 		return;
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	cpu_sgnblkptr = cpu_sgnblkp[cpuid];
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	/*
4877c478bd9Sstevel@tonic-gate 	 *  Map new generic cpu states to older Starfire states.
4887c478bd9Sstevel@tonic-gate 	 */
4897c478bd9Sstevel@tonic-gate 	switch (state) {
4907c478bd9Sstevel@tonic-gate 	case SIGST_OFFLINE:
4917c478bd9Sstevel@tonic-gate 		state = SIGBST_OFFLINE;
4927c478bd9Sstevel@tonic-gate 		break;
4937c478bd9Sstevel@tonic-gate 	case SIGST_RESUME_INPROGRESS:
4947c478bd9Sstevel@tonic-gate 		state = SIGBST_RESUME_INPROGRESS;
4957c478bd9Sstevel@tonic-gate 		break;
4967c478bd9Sstevel@tonic-gate 	case SIGST_QUIESCE_INPROGRESS:
4977c478bd9Sstevel@tonic-gate 		state = SIGBST_QUIESCE_INPROGRESS;
4987c478bd9Sstevel@tonic-gate 		break;
4997c478bd9Sstevel@tonic-gate 	case SIGST_QUIESCED:
5007c478bd9Sstevel@tonic-gate 		state = SIGBST_QUIESCED;
5017c478bd9Sstevel@tonic-gate 		break;
5027c478bd9Sstevel@tonic-gate 	case SIGST_EXIT:
5037c478bd9Sstevel@tonic-gate 		switch (sub_state) {
5047c478bd9Sstevel@tonic-gate 		case SIGSUBST_DEBUG:
5057c478bd9Sstevel@tonic-gate 			state = SIGBST_RUN;
5067c478bd9Sstevel@tonic-gate 			sub_state = EXIT_NULL;
5077c478bd9Sstevel@tonic-gate 			break;
5087c478bd9Sstevel@tonic-gate 		case SIGSUBST_PANIC_CONT:
5097c478bd9Sstevel@tonic-gate 			state = SIGBST_RUN;
5107c478bd9Sstevel@tonic-gate 			sub_state = EXIT_PANIC2;
5117c478bd9Sstevel@tonic-gate 			break;
5127c478bd9Sstevel@tonic-gate 		case SIGSUBST_DUMP:
5137c478bd9Sstevel@tonic-gate 			state = SIGBST_EXIT;
5147c478bd9Sstevel@tonic-gate 			sub_state = EXIT_PANIC2;
5157c478bd9Sstevel@tonic-gate 			break;
5167c478bd9Sstevel@tonic-gate 		default:
5177c478bd9Sstevel@tonic-gate 			break;
5187c478bd9Sstevel@tonic-gate 		}
5197c478bd9Sstevel@tonic-gate 		break;
5207c478bd9Sstevel@tonic-gate 	default:
5217c478bd9Sstevel@tonic-gate 		break;
5227c478bd9Sstevel@tonic-gate 	}
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_signature.state_t.sig = sgn;
5257c478bd9Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_signature.state_t.state = state;
5267c478bd9Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_signature.state_t.sub_state = sub_state;
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 	/* Update the ring buffer */
5297c478bd9Sstevel@tonic-gate 	idx = cpu_sgnblkptr->sigb_ringbuf.wr_ptr;
5307c478bd9Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.sig = sgn;
5317c478bd9Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.state = state;
5327c478bd9Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.sub_state = sub_state;
5337c478bd9Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_ringbuf.wr_ptr += 1;
5347c478bd9Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_ringbuf.wr_ptr &= RB_IDX_MASK;
5357c478bd9Sstevel@tonic-gate }
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate /*
5387c478bd9Sstevel@tonic-gate  * Update signature block and the signature ring buffer of all CPUs.
5397c478bd9Sstevel@tonic-gate  */
5407c478bd9Sstevel@tonic-gate void
5417c478bd9Sstevel@tonic-gate sgn_update_all_cpus(ushort_t sgn, uchar_t state, uchar_t sub_state)
5427c478bd9Sstevel@tonic-gate {
5437c478bd9Sstevel@tonic-gate 	int i = 0;
5447c478bd9Sstevel@tonic-gate 	uchar_t cpu_state;
5457c478bd9Sstevel@tonic-gate 	uchar_t cpu_sub_state;
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	for (i = 0; i < NCPU; i++) {
5487c478bd9Sstevel@tonic-gate 		cpu_sgnblk_t *sblkp;
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 		sblkp = cpu_sgnblkp[i];
5517c478bd9Sstevel@tonic-gate 		cpu_sub_state = sub_state;
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 		if ((sblkp != NULL) && (cpu[i] != NULL && (cpu[i]->cpu_flags &
5547c478bd9Sstevel@tonic-gate 		    (CPU_EXISTS|CPU_QUIESCED)))) {
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 			if (sub_state == EXIT_REBOOT) {
5577c478bd9Sstevel@tonic-gate 				cpu_sub_state =
5587c478bd9Sstevel@tonic-gate 				    sblkp->sigb_signature.state_t.sub_state;
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 				if ((cpu_sub_state == EXIT_PANIC1) ||
5617c478bd9Sstevel@tonic-gate 				    (cpu_sub_state == EXIT_PANIC2))
5627c478bd9Sstevel@tonic-gate 					cpu_sub_state = EXIT_PANIC_REBOOT;
5637c478bd9Sstevel@tonic-gate 				else
5647c478bd9Sstevel@tonic-gate 					cpu_sub_state = EXIT_REBOOT;
5657c478bd9Sstevel@tonic-gate 			}
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 			/*
5687c478bd9Sstevel@tonic-gate 			 * If we get here from an OBP sync after watchdog,
5697c478bd9Sstevel@tonic-gate 			 * we need to retain the watchdog sync state so that
5707c478bd9Sstevel@tonic-gate 			 * hostmon knows what's going on.  So if we're in
5717c478bd9Sstevel@tonic-gate 			 * watchdog we don't update the state.
5727c478bd9Sstevel@tonic-gate 			 */
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate 			cpu_state = sblkp->sigb_signature.state_t.state;
5757c478bd9Sstevel@tonic-gate 			if (cpu_state == SIGBST_WATCHDOG_SYNC)
5767c478bd9Sstevel@tonic-gate 				cpu_sgn_update(sgn, SIGBST_WATCHDOG_SYNC,
5777c478bd9Sstevel@tonic-gate 				    cpu_sub_state, i);
5787c478bd9Sstevel@tonic-gate 			else if (cpu_state == SIGBST_REDMODE_SYNC)
5797c478bd9Sstevel@tonic-gate 				cpu_sgn_update(sgn, SIGBST_REDMODE_SYNC,
5807c478bd9Sstevel@tonic-gate 				    cpu_sub_state, i);
5817c478bd9Sstevel@tonic-gate 			else
5827c478bd9Sstevel@tonic-gate 				cpu_sgn_update(sgn, state, cpu_sub_state, i);
5837c478bd9Sstevel@tonic-gate 		}
5847c478bd9Sstevel@tonic-gate 	}
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate int
5887c478bd9Sstevel@tonic-gate cpu_sgn_exists(int cpuid)
5897c478bd9Sstevel@tonic-gate {
5907c478bd9Sstevel@tonic-gate 	return (cpu_sgnblkp[cpuid] != NULL);
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate ushort_t
5947c478bd9Sstevel@tonic-gate get_cpu_sgn(int cpuid)
5957c478bd9Sstevel@tonic-gate {
5967c478bd9Sstevel@tonic-gate 	if (cpu_sgnblkp[cpuid] == NULL)
5977c478bd9Sstevel@tonic-gate 		return ((ushort_t)-1);
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 	return (cpu_sgnblkp[cpuid]->sigb_signature.state_t.sig);
6007c478bd9Sstevel@tonic-gate }
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate uchar_t
6037c478bd9Sstevel@tonic-gate get_cpu_sgn_state(int cpuid)
6047c478bd9Sstevel@tonic-gate {
6057c478bd9Sstevel@tonic-gate 	if (cpu_sgnblkp[cpuid] == NULL)
6067c478bd9Sstevel@tonic-gate 		return ((uchar_t)-1);
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	return (cpu_sgnblkp[cpuid]->sigb_signature.state_t.state);
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate /*
6127c478bd9Sstevel@tonic-gate  * KDI functions - used by the in-situ kernel debugger (kmdb) to perform
6137c478bd9Sstevel@tonic-gate  * platform-specific operations.  These functions execute when the world is
6147c478bd9Sstevel@tonic-gate  * stopped, and as such cannot make any blocking calls, hold locks, etc.
6157c478bd9Sstevel@tonic-gate  * promif functions are a special case, and may be used.
6167c478bd9Sstevel@tonic-gate  */
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate static void
6197c478bd9Sstevel@tonic-gate starfire_system_claim(void)
6207c478bd9Sstevel@tonic-gate {
621d3d50737SRafael Vanoni 	lbolt_debug_entry();
622d3d50737SRafael Vanoni 
6237c478bd9Sstevel@tonic-gate 	prom_interpret("sigb-sig! my-sigb-sig!", OBP_SIG, OBP_SIG, 0, 0, 0);
6247c478bd9Sstevel@tonic-gate }
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate static void
6277c478bd9Sstevel@tonic-gate starfire_system_release(void)
6287c478bd9Sstevel@tonic-gate {
6297c478bd9Sstevel@tonic-gate 	prom_interpret("sigb-sig! my-sigb-sig!", OS_SIG, OS_SIG, 0, 0, 0);
630d3d50737SRafael Vanoni 
631d3d50737SRafael Vanoni 	lbolt_debug_return();
6327c478bd9Sstevel@tonic-gate }
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate void
6357c478bd9Sstevel@tonic-gate plat_kdi_init(kdi_t *kdi)
6367c478bd9Sstevel@tonic-gate {
6377c478bd9Sstevel@tonic-gate 	kdi->pkdi_system_claim = starfire_system_claim;
6387c478bd9Sstevel@tonic-gate 	kdi->pkdi_system_release = starfire_system_release;
6397c478bd9Sstevel@tonic-gate }
640