xref: /onnv-gate/usr/src/uts/sun4u/starfire/os/starfire.c (revision 4266:c151d8b35988)
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
5*4266Sdp78419  * Common Development and Distribution License (the "License").
6*4266Sdp78419  * 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 /*
22*4266Sdp78419  * 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/param.h>
290Sstevel@tonic-gate #include <sys/systm.h>
300Sstevel@tonic-gate #include <sys/sysmacros.h>
310Sstevel@tonic-gate #include <sys/sunddi.h>
320Sstevel@tonic-gate #include <sys/modctl.h>
330Sstevel@tonic-gate #include <sys/promif.h>
340Sstevel@tonic-gate #include <sys/machparam.h>
350Sstevel@tonic-gate #include <sys/kobj.h>
360Sstevel@tonic-gate #include <sys/mem_cage.h>
370Sstevel@tonic-gate #include <sys/starfire.h>
380Sstevel@tonic-gate 
390Sstevel@tonic-gate #include <sys/platform_module.h>
400Sstevel@tonic-gate #include <sys/errno.h>
410Sstevel@tonic-gate #include <vm/page.h>
420Sstevel@tonic-gate #include <vm/hat_sfmmu.h>
430Sstevel@tonic-gate #include <sys/memnode.h>
440Sstevel@tonic-gate #include <vm/vm_dep.h>
450Sstevel@tonic-gate #include <sys/cpu_sgnblk_defs.h>
460Sstevel@tonic-gate #include <sys/cpu_sgn.h>
470Sstevel@tonic-gate #include <sys/kdi_impl.h>
480Sstevel@tonic-gate 
490Sstevel@tonic-gate extern cpu_sgnblk_t *cpu_sgnblkp[];
500Sstevel@tonic-gate 
510Sstevel@tonic-gate /* Preallocation of spare tsb's for DR - none for now */
520Sstevel@tonic-gate int starfire_tsb_spares = STARFIRE_MAX_BOARDS << 1;
530Sstevel@tonic-gate 
540Sstevel@tonic-gate /* Set the maximum number of boards... for DR */
550Sstevel@tonic-gate int starfire_boards = STARFIRE_MAX_BOARDS;
560Sstevel@tonic-gate 
570Sstevel@tonic-gate /* Maximum number of cpus per board... for DR */
580Sstevel@tonic-gate int starfire_cpu_per_board = 4;
590Sstevel@tonic-gate 
600Sstevel@tonic-gate /* Maximum number of mem-units per board... for DR */
610Sstevel@tonic-gate int starfire_mem_per_board = 1;
620Sstevel@tonic-gate 
630Sstevel@tonic-gate /* Maximum number of io-units (buses) per board... for DR */
640Sstevel@tonic-gate int starfire_io_per_board = 2;
650Sstevel@tonic-gate 
660Sstevel@tonic-gate /* Preferred minimum cage size (expressed in pages)... for DR */
670Sstevel@tonic-gate pgcnt_t starfire_startup_cage_size = 0;
680Sstevel@tonic-gate 
690Sstevel@tonic-gate void sgn_update_all_cpus(ushort_t, uchar_t, uchar_t);
700Sstevel@tonic-gate 
710Sstevel@tonic-gate int
720Sstevel@tonic-gate set_platform_max_ncpus(void)
730Sstevel@tonic-gate {
740Sstevel@tonic-gate 	starfire_boards = MIN(starfire_boards, STARFIRE_MAX_BOARDS);
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 	if (starfire_boards < 1)
770Sstevel@tonic-gate 		starfire_boards = 1;
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 	return (starfire_boards * starfire_cpu_per_board);
800Sstevel@tonic-gate }
810Sstevel@tonic-gate 
820Sstevel@tonic-gate void
830Sstevel@tonic-gate startup_platform(void)
840Sstevel@tonic-gate {
850Sstevel@tonic-gate }
860Sstevel@tonic-gate 
870Sstevel@tonic-gate int
880Sstevel@tonic-gate set_platform_tsb_spares()
890Sstevel@tonic-gate {
900Sstevel@tonic-gate 	return (MIN(starfire_tsb_spares, MAX_UPA));
910Sstevel@tonic-gate }
920Sstevel@tonic-gate 
930Sstevel@tonic-gate void
940Sstevel@tonic-gate set_platform_defaults(void)
950Sstevel@tonic-gate {
960Sstevel@tonic-gate 	extern char *tod_module_name;
970Sstevel@tonic-gate 	extern int ts_dispatch_extended;
980Sstevel@tonic-gate 	extern void cpu_sgn_update(ushort_t, uchar_t, uchar_t, int);
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	uint32_t	revlevel;
1010Sstevel@tonic-gate 	char		buf[20];
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate #ifdef DEBUG
1040Sstevel@tonic-gate 	ce_verbose_memory = 2;
1050Sstevel@tonic-gate 	ce_verbose_other = 2;
1060Sstevel@tonic-gate #endif
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate 	/*
1090Sstevel@tonic-gate 	 * Check to see if we have the right firmware
1100Sstevel@tonic-gate 	 * We simply do a prom_test to see if
1110Sstevel@tonic-gate 	 * "SUNW,UE10000-prom-version" interface exist.
1120Sstevel@tonic-gate 	 */
1130Sstevel@tonic-gate 	if (prom_test("SUNW,UE10000-prom-version") != 0) {
1140Sstevel@tonic-gate 		halt("Firmware upgrade is required to boot this OS!");
1150Sstevel@tonic-gate 	} else {
1160Sstevel@tonic-gate 		/*
1170Sstevel@tonic-gate 		 * Versions 5 to 50 and 150 or above  can support this OS
1180Sstevel@tonic-gate 		 */
1190Sstevel@tonic-gate 		sprintf(buf, "cpu-prom-version swap l!");
120796Smathue 		prom_interpret(buf, (uintptr_t)&revlevel, 0, 0, 0, 0);
1210Sstevel@tonic-gate 		if ((revlevel < 5) || ((revlevel > 50) && (revlevel < 150)))
1220Sstevel@tonic-gate 			halt("Firmware upgrade is required to boot this OS!");
1230Sstevel@tonic-gate 	}
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate 	/* Set the CPU signature function pointer */
1260Sstevel@tonic-gate 	cpu_sgn_func = cpu_sgn_update;
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 	/* Set appropriate tod module for starfire */
1290Sstevel@tonic-gate 	ASSERT(tod_module_name == NULL);
1300Sstevel@tonic-gate 	tod_module_name = "todstarfire";
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	/*
1330Sstevel@tonic-gate 	 * Use the alternate TS dispatch table, which is better
1340Sstevel@tonic-gate 	 * tuned for large servers.
1350Sstevel@tonic-gate 	 */
1360Sstevel@tonic-gate 	if (ts_dispatch_extended == -1) /* use platform default */
1370Sstevel@tonic-gate 		ts_dispatch_extended = 1;
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate #ifdef DEBUG
1410Sstevel@tonic-gate pgcnt_t starfire_cage_size_limit;
1420Sstevel@tonic-gate #endif
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate void
1450Sstevel@tonic-gate set_platform_cage_params(void)
1460Sstevel@tonic-gate {
1470Sstevel@tonic-gate 	extern pgcnt_t total_pages;
1480Sstevel@tonic-gate 	extern struct memlist *phys_avail;
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	if (kernel_cage_enable) {
1510Sstevel@tonic-gate 		pgcnt_t preferred_cage_size;
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 		preferred_cage_size =
1540Sstevel@tonic-gate 			MAX(starfire_startup_cage_size, total_pages / 256);
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate #ifdef DEBUG
1570Sstevel@tonic-gate 		if (starfire_cage_size_limit)
1580Sstevel@tonic-gate 			preferred_cage_size = starfire_cage_size_limit;
1590Sstevel@tonic-gate #endif
1600Sstevel@tonic-gate 		/*
1610Sstevel@tonic-gate 		 * Note: we are assuming that post has load the
1620Sstevel@tonic-gate 		 * whole show in to the high end of memory. Having
1630Sstevel@tonic-gate 		 * taken this leap, we copy the whole of phys_avail
1640Sstevel@tonic-gate 		 * the glist and arrange for the cage to grow
1650Sstevel@tonic-gate 		 * downward (descending pfns).
1660Sstevel@tonic-gate 		 */
167*4266Sdp78419 		kcage_range_init(phys_avail, KCAGE_DOWN, preferred_cage_size);
1680Sstevel@tonic-gate 	}
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	if (kcage_on)
1710Sstevel@tonic-gate 		cmn_err(CE_NOTE, "!DR Kernel Cage is ENABLED");
1720Sstevel@tonic-gate 	else
1730Sstevel@tonic-gate 		cmn_err(CE_NOTE, "!DR Kernel Cage is DISABLED");
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate void
1770Sstevel@tonic-gate load_platform_drivers(void)
1780Sstevel@tonic-gate {
1790Sstevel@tonic-gate 	/* load the NGDR driver */
1800Sstevel@tonic-gate 	if (i_ddi_attach_pseudo_node("ngdr") == NULL) {
1810Sstevel@tonic-gate 		cmn_err(CE_WARN, "ngdr failed to load");
1820Sstevel@tonic-gate 	}
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate /*
1860Sstevel@tonic-gate  * Starfire does not support power control of CPUs from the OS.
1870Sstevel@tonic-gate  */
1880Sstevel@tonic-gate /*ARGSUSED*/
1890Sstevel@tonic-gate int
1900Sstevel@tonic-gate plat_cpu_poweron(struct cpu *cp)
1910Sstevel@tonic-gate {
1920Sstevel@tonic-gate 	int (*starfire_cpu_poweron)(struct cpu *) = NULL;
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 	starfire_cpu_poweron =
1950Sstevel@tonic-gate 	    (int (*)(struct cpu *))kobj_getsymvalue("drmach_cpu_poweron", 0);
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	if (starfire_cpu_poweron == NULL)
1980Sstevel@tonic-gate 		return (ENOTSUP);
1990Sstevel@tonic-gate 	else
2000Sstevel@tonic-gate 		return ((starfire_cpu_poweron)(cp));
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate /*ARGSUSED*/
2040Sstevel@tonic-gate int
2050Sstevel@tonic-gate plat_cpu_poweroff(struct cpu *cp)
2060Sstevel@tonic-gate {
2070Sstevel@tonic-gate 	int (*starfire_cpu_poweroff)(struct cpu *) = NULL;
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 	starfire_cpu_poweroff =
2100Sstevel@tonic-gate 	    (int (*)(struct cpu *))kobj_getsymvalue("drmach_cpu_poweroff", 0);
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 	if (starfire_cpu_poweroff == NULL)
2130Sstevel@tonic-gate 		return (ENOTSUP);
2140Sstevel@tonic-gate 	else
2150Sstevel@tonic-gate 		return ((starfire_cpu_poweroff)(cp));
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate void
2190Sstevel@tonic-gate plat_dmv_params(uint_t *hwint, uint_t *swint)
2200Sstevel@tonic-gate {
2210Sstevel@tonic-gate 	*hwint = STARFIRE_DMV_HWINT;
2220Sstevel@tonic-gate 	*swint = 0;
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate /*
2260Sstevel@tonic-gate  * The following our currently private to Starfire DR
2270Sstevel@tonic-gate  */
2280Sstevel@tonic-gate int
2290Sstevel@tonic-gate plat_max_boards()
2300Sstevel@tonic-gate {
2310Sstevel@tonic-gate 	return (starfire_boards);
2320Sstevel@tonic-gate }
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate int
2350Sstevel@tonic-gate plat_max_cpu_units_per_board()
2360Sstevel@tonic-gate {
2370Sstevel@tonic-gate 	return (starfire_cpu_per_board);
2380Sstevel@tonic-gate }
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate int
2410Sstevel@tonic-gate plat_max_mem_units_per_board()
2420Sstevel@tonic-gate {
2430Sstevel@tonic-gate 	return (starfire_mem_per_board);
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate int
2470Sstevel@tonic-gate plat_max_io_units_per_board()
2480Sstevel@tonic-gate {
2490Sstevel@tonic-gate 	return (starfire_io_per_board);
2500Sstevel@tonic-gate }
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate /*
2540Sstevel@tonic-gate  * This index is used to associate a given pfn to a place on the freelist.
2550Sstevel@tonic-gate  * This results in dispersing pfn assignment over all the boards in the
2560Sstevel@tonic-gate  * system.
2570Sstevel@tonic-gate  * Choose the index randomly to prevent clustering pages of different
2580Sstevel@tonic-gate  * colors on the same board.
2590Sstevel@tonic-gate  */
2600Sstevel@tonic-gate static uint_t random_idx(int ubound);
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate #define	PFN_2_LBN(pfn)	(((pfn) >> (STARFIRE_MC_MEMBOARD_SHIFT - PAGESHIFT)) % \
2630Sstevel@tonic-gate 			STARFIRE_MAX_BOARDS)
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate void
2660Sstevel@tonic-gate plat_freelist_process(int mnode)
2670Sstevel@tonic-gate {
2680Sstevel@tonic-gate 	page_t		*page, **freelist;
2690Sstevel@tonic-gate 	page_t		*bdlist[STARFIRE_MAX_BOARDS];
2700Sstevel@tonic-gate 	page_t		 **sortlist[STARFIRE_MAX_BOARDS];
2710Sstevel@tonic-gate 	uint32_t	idx, idy, size, color, max_color, lbn;
2720Sstevel@tonic-gate 	uint32_t	bd_flags, bd_cnt, result, bds;
2730Sstevel@tonic-gate 	kmutex_t	*pcm;
2740Sstevel@tonic-gate 	int 		mtype;
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 	/* for each page size */
2770Sstevel@tonic-gate 	for (mtype = 0; mtype < MAX_MEM_TYPES; mtype++) {
2780Sstevel@tonic-gate 		for (size = 0; size < mmu_page_sizes; size++) {
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 			/*
2810Sstevel@tonic-gate 			 * Compute the maximum # of phys colors based on
2820Sstevel@tonic-gate 			 * page size.
2830Sstevel@tonic-gate 			 */
2840Sstevel@tonic-gate 			max_color = page_get_pagecolors(size);
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 			/* for each color */
2870Sstevel@tonic-gate 			for (color = 0; color < max_color; color++) {
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 				bd_cnt = 0;
2900Sstevel@tonic-gate 				bd_flags = 0;
2910Sstevel@tonic-gate 				for (idx = 0; idx < STARFIRE_MAX_BOARDS;
2920Sstevel@tonic-gate 						idx++) {
2930Sstevel@tonic-gate 					bdlist[idx] = NULL;
2940Sstevel@tonic-gate 					sortlist[idx] = NULL;
2950Sstevel@tonic-gate 				}
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate 				/* find freelist */
2980Sstevel@tonic-gate 				freelist = &PAGE_FREELISTS(mnode, size,
2990Sstevel@tonic-gate 				    color, mtype);
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 				if (*freelist == NULL)
3020Sstevel@tonic-gate 					continue;
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 				/* acquire locks */
3050Sstevel@tonic-gate 				pcm = PC_BIN_MUTEX(mnode, color, PG_FREE_LIST);
3060Sstevel@tonic-gate 				mutex_enter(pcm);
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 				/*
3090Sstevel@tonic-gate 				 * read freelist & sort pages by logical
3100Sstevel@tonic-gate 				 * board number
3110Sstevel@tonic-gate 				 */
3120Sstevel@tonic-gate 				/* grab pages till last one. */
3130Sstevel@tonic-gate 				while (*freelist) {
3140Sstevel@tonic-gate 					page = *freelist;
3150Sstevel@tonic-gate 					result = page_trylock(page, SE_EXCL);
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 					ASSERT(result);
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 					/* Delete from freelist */
3200Sstevel@tonic-gate 					if (size != 0) {
3210Sstevel@tonic-gate 						page_vpsub(freelist, page);
3220Sstevel@tonic-gate 					} else {
3230Sstevel@tonic-gate 						mach_page_sub(freelist, page);
3240Sstevel@tonic-gate 					}
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 					/* detect the lbn */
3270Sstevel@tonic-gate 					lbn = PFN_2_LBN(page->p_pagenum);
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 					/* add to bdlist[lbn] */
3300Sstevel@tonic-gate 					if (size != 0) {
3310Sstevel@tonic-gate 						page_vpadd(&bdlist[lbn], page);
3320Sstevel@tonic-gate 					} else {
3330Sstevel@tonic-gate 						mach_page_add(&bdlist[lbn],
3340Sstevel@tonic-gate 						    page);
3350Sstevel@tonic-gate 					}
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 					/* if lbn new */
3380Sstevel@tonic-gate 					if ((bd_flags & (1 << lbn)) == 0) {
3390Sstevel@tonic-gate 						bd_flags |= (1 << lbn);
3400Sstevel@tonic-gate 						bd_cnt++;
3410Sstevel@tonic-gate 					}
3420Sstevel@tonic-gate 					page_unlock(page);
3430Sstevel@tonic-gate 				}
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 				/*
3460Sstevel@tonic-gate 				 * Make the sortlist so
3470Sstevel@tonic-gate 				 * bd_cnt choices show up
3480Sstevel@tonic-gate 				 */
3490Sstevel@tonic-gate 				bds = 0;
3500Sstevel@tonic-gate 				for (idx = 0; idx < STARFIRE_MAX_BOARDS;
3510Sstevel@tonic-gate 						idx++) {
3520Sstevel@tonic-gate 					if (bdlist[idx])
3530Sstevel@tonic-gate 						sortlist[bds++] = &bdlist[idx];
3540Sstevel@tonic-gate 				}
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 				/*
3570Sstevel@tonic-gate 				 * Set random start.
3580Sstevel@tonic-gate 				 */
3590Sstevel@tonic-gate 				(void) random_idx(-color);
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 				/*
3620Sstevel@tonic-gate 				 * now rebuild the freelist by shuffling
3630Sstevel@tonic-gate 				 * pages from bd lists
3640Sstevel@tonic-gate 				 */
3650Sstevel@tonic-gate 				while (bd_cnt) {
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate 					/*
3680Sstevel@tonic-gate 					 * get "random" index between 0 &
3690Sstevel@tonic-gate 					 * bd_cnt
3700Sstevel@tonic-gate 					 */
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 					ASSERT(bd_cnt &&
3730Sstevel@tonic-gate 					    (bd_cnt < STARFIRE_MAX_BOARDS+1));
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 					idx = random_idx(bd_cnt);
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate 					page = *sortlist[idx];
3780Sstevel@tonic-gate 					result = page_trylock(page, SE_EXCL);
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 					ASSERT(result);
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 					/* Delete from sort_list */
3830Sstevel@tonic-gate 					/*  & Append to freelist */
3840Sstevel@tonic-gate 					/* Big pages use vp_add - 8k don't */
3850Sstevel@tonic-gate 					if (size != 0) {
3860Sstevel@tonic-gate 						page_vpsub(sortlist[idx], page);
3870Sstevel@tonic-gate 						page_vpadd(freelist, page);
3880Sstevel@tonic-gate 					} else {
3890Sstevel@tonic-gate 						mach_page_sub(sortlist[idx],
3900Sstevel@tonic-gate 						    page);
3910Sstevel@tonic-gate 						mach_page_add(freelist, page);
3920Sstevel@tonic-gate 					}
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 					/* needed for indexing tmp lists */
3950Sstevel@tonic-gate 					lbn = PFN_2_LBN(page->p_pagenum);
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 					/*
3980Sstevel@tonic-gate 					 * if this was the last page on this
3990Sstevel@tonic-gate 					 * list?
4000Sstevel@tonic-gate 					 */
4010Sstevel@tonic-gate 					if (*sortlist[idx] == NULL) {
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 						/* have to find brd list */
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 						/* idx is lbn? -- No! */
4060Sstevel@tonic-gate 						/* sortlist, brdlist */
4070Sstevel@tonic-gate 						/*  have diff indexs */
4080Sstevel@tonic-gate 						bd_flags &= ~(1 << lbn);
4090Sstevel@tonic-gate 						--bd_cnt;
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 						/*
4120Sstevel@tonic-gate 						 * redo the sortlist so only
4130Sstevel@tonic-gate 						 * bd_cnt choices show up
4140Sstevel@tonic-gate 						 */
4150Sstevel@tonic-gate 						bds = 0;
4160Sstevel@tonic-gate 						for (idy = 0;
4170Sstevel@tonic-gate 						    idy < STARFIRE_MAX_BOARDS;
4180Sstevel@tonic-gate 						    idy++) {
4190Sstevel@tonic-gate 							if (bdlist[idy]) {
4200Sstevel@tonic-gate 								sortlist[bds++]
4210Sstevel@tonic-gate 								= &bdlist[idy];
4220Sstevel@tonic-gate 							}
4230Sstevel@tonic-gate 						}
4240Sstevel@tonic-gate 					}
4250Sstevel@tonic-gate 					page_unlock(page);
4260Sstevel@tonic-gate 				}
4270Sstevel@tonic-gate 				mutex_exit(pcm);
4280Sstevel@tonic-gate 			}
4290Sstevel@tonic-gate 		}
4300Sstevel@tonic-gate 	}
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate /*
4340Sstevel@tonic-gate  * If ubound > 0, will return an int between 0 & ubound
4350Sstevel@tonic-gate  * If ubound < 0, will set "random seed"
4360Sstevel@tonic-gate  */
4370Sstevel@tonic-gate static uint_t
4380Sstevel@tonic-gate random_idx(int ubound)
4390Sstevel@tonic-gate {
4400Sstevel@tonic-gate 	static int idx = 0;
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	if (ubound > 0) {
4430Sstevel@tonic-gate 		idx = (idx + 1) % ubound;
4440Sstevel@tonic-gate 		return (idx);
4450Sstevel@tonic-gate 	}
4460Sstevel@tonic-gate 	idx = -ubound;
4470Sstevel@tonic-gate 	return (0);
4480Sstevel@tonic-gate }
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate /*
4510Sstevel@tonic-gate  * No platform drivers on this platform
4520Sstevel@tonic-gate  */
4530Sstevel@tonic-gate char *platform_module_list[] = {
4540Sstevel@tonic-gate 	(char *)0
4550Sstevel@tonic-gate };
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate /*ARGSUSED*/
4580Sstevel@tonic-gate void
4590Sstevel@tonic-gate plat_tod_fault(enum tod_fault_type tod_bad)
4600Sstevel@tonic-gate {
4610Sstevel@tonic-gate }
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate /*
4640Sstevel@tonic-gate  * Update signature block and the signature ring buffer of a given cpu_id.
4650Sstevel@tonic-gate  */
4660Sstevel@tonic-gate void
4670Sstevel@tonic-gate cpu_sgn_update(ushort_t sgn, uchar_t state, uchar_t sub_state, int cpuid)
4680Sstevel@tonic-gate {
4690Sstevel@tonic-gate 	uchar_t idx;
4700Sstevel@tonic-gate 	cpu_sgnblk_t *cpu_sgnblkptr;
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate 	/*
4730Sstevel@tonic-gate 	 * cpuid == -1 indicates that the operation applies to all cpus.
4740Sstevel@tonic-gate 	 */
4750Sstevel@tonic-gate 	if (cpuid < 0) {
4760Sstevel@tonic-gate 		sgn_update_all_cpus(sgn, state, sub_state);
4770Sstevel@tonic-gate 		return;
4780Sstevel@tonic-gate 	}
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate 	if (cpu_sgnblkp[cpuid] == NULL)
4810Sstevel@tonic-gate 		return;
4820Sstevel@tonic-gate 
4830Sstevel@tonic-gate 	cpu_sgnblkptr = cpu_sgnblkp[cpuid];
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate 	/*
4860Sstevel@tonic-gate 	 *  Map new generic cpu states to older Starfire states.
4870Sstevel@tonic-gate 	 */
4880Sstevel@tonic-gate 	switch (state) {
4890Sstevel@tonic-gate 	case SIGST_OFFLINE:
4900Sstevel@tonic-gate 		state = SIGBST_OFFLINE;
4910Sstevel@tonic-gate 		break;
4920Sstevel@tonic-gate 	case SIGST_RESUME_INPROGRESS:
4930Sstevel@tonic-gate 		state = SIGBST_RESUME_INPROGRESS;
4940Sstevel@tonic-gate 		break;
4950Sstevel@tonic-gate 	case SIGST_QUIESCE_INPROGRESS:
4960Sstevel@tonic-gate 		state = SIGBST_QUIESCE_INPROGRESS;
4970Sstevel@tonic-gate 		break;
4980Sstevel@tonic-gate 	case SIGST_QUIESCED:
4990Sstevel@tonic-gate 		state = SIGBST_QUIESCED;
5000Sstevel@tonic-gate 		break;
5010Sstevel@tonic-gate 	case SIGST_EXIT:
5020Sstevel@tonic-gate 		switch (sub_state) {
5030Sstevel@tonic-gate 		case SIGSUBST_DEBUG:
5040Sstevel@tonic-gate 			state = SIGBST_RUN;
5050Sstevel@tonic-gate 			sub_state = EXIT_NULL;
5060Sstevel@tonic-gate 			break;
5070Sstevel@tonic-gate 		case SIGSUBST_PANIC_CONT:
5080Sstevel@tonic-gate 			state = SIGBST_RUN;
5090Sstevel@tonic-gate 			sub_state = EXIT_PANIC2;
5100Sstevel@tonic-gate 			break;
5110Sstevel@tonic-gate 		case SIGSUBST_DUMP:
5120Sstevel@tonic-gate 			state = SIGBST_EXIT;
5130Sstevel@tonic-gate 			sub_state = EXIT_PANIC2;
5140Sstevel@tonic-gate 			break;
5150Sstevel@tonic-gate 		default:
5160Sstevel@tonic-gate 			break;
5170Sstevel@tonic-gate 		}
5180Sstevel@tonic-gate 		break;
5190Sstevel@tonic-gate 	default:
5200Sstevel@tonic-gate 		break;
5210Sstevel@tonic-gate 	}
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_signature.state_t.sig = sgn;
5240Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_signature.state_t.state = state;
5250Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_signature.state_t.sub_state = sub_state;
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 	/* Update the ring buffer */
5280Sstevel@tonic-gate 	idx = cpu_sgnblkptr->sigb_ringbuf.wr_ptr;
5290Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.sig = sgn;
5300Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.state = state;
5310Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.sub_state = sub_state;
5320Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_ringbuf.wr_ptr += 1;
5330Sstevel@tonic-gate 	cpu_sgnblkptr->sigb_ringbuf.wr_ptr &= RB_IDX_MASK;
5340Sstevel@tonic-gate }
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate /*
5370Sstevel@tonic-gate  * Update signature block and the signature ring buffer of all CPUs.
5380Sstevel@tonic-gate  */
5390Sstevel@tonic-gate void
5400Sstevel@tonic-gate sgn_update_all_cpus(ushort_t sgn, uchar_t state, uchar_t sub_state)
5410Sstevel@tonic-gate {
5420Sstevel@tonic-gate 	int i = 0;
5430Sstevel@tonic-gate 	uchar_t cpu_state;
5440Sstevel@tonic-gate 	uchar_t cpu_sub_state;
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 	for (i = 0; i < NCPU; i++) {
5470Sstevel@tonic-gate 		cpu_sgnblk_t *sblkp;
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate 		sblkp = cpu_sgnblkp[i];
5500Sstevel@tonic-gate 		cpu_sub_state = sub_state;
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate 		if ((sblkp != NULL) && (cpu[i] != NULL && (cpu[i]->cpu_flags &
5530Sstevel@tonic-gate 				(CPU_EXISTS|CPU_QUIESCED)))) {
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 			if (sub_state == EXIT_REBOOT) {
5560Sstevel@tonic-gate 				cpu_sub_state =
5570Sstevel@tonic-gate 					sblkp->sigb_signature.state_t.sub_state;
5580Sstevel@tonic-gate 
5590Sstevel@tonic-gate 				if ((cpu_sub_state == EXIT_PANIC1) ||
5600Sstevel@tonic-gate 					(cpu_sub_state == EXIT_PANIC2))
5610Sstevel@tonic-gate 					cpu_sub_state = EXIT_PANIC_REBOOT;
5620Sstevel@tonic-gate 				else
5630Sstevel@tonic-gate 					cpu_sub_state = EXIT_REBOOT;
5640Sstevel@tonic-gate 			}
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate 			/*
5670Sstevel@tonic-gate 			 * If we get here from an OBP sync after watchdog,
5680Sstevel@tonic-gate 			 * we need to retain the watchdog sync state so that
5690Sstevel@tonic-gate 			 * hostmon knows what's going on.  So if we're in
5700Sstevel@tonic-gate 			 * watchdog we don't update the state.
5710Sstevel@tonic-gate 			 */
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 			cpu_state = sblkp->sigb_signature.state_t.state;
5740Sstevel@tonic-gate 			if (cpu_state == SIGBST_WATCHDOG_SYNC)
5750Sstevel@tonic-gate 				cpu_sgn_update(sgn, SIGBST_WATCHDOG_SYNC,
5760Sstevel@tonic-gate 					cpu_sub_state, i);
5770Sstevel@tonic-gate 			else if (cpu_state == SIGBST_REDMODE_SYNC)
5780Sstevel@tonic-gate 				cpu_sgn_update(sgn, SIGBST_REDMODE_SYNC,
5790Sstevel@tonic-gate 					cpu_sub_state, i);
5800Sstevel@tonic-gate 			else
5810Sstevel@tonic-gate 				cpu_sgn_update(sgn, state, cpu_sub_state, i);
5820Sstevel@tonic-gate 		}
5830Sstevel@tonic-gate 	}
5840Sstevel@tonic-gate }
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate int
5870Sstevel@tonic-gate cpu_sgn_exists(int cpuid)
5880Sstevel@tonic-gate {
5890Sstevel@tonic-gate 	return (cpu_sgnblkp[cpuid] != NULL);
5900Sstevel@tonic-gate }
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate ushort_t
5930Sstevel@tonic-gate get_cpu_sgn(int cpuid)
5940Sstevel@tonic-gate {
5950Sstevel@tonic-gate 	if (cpu_sgnblkp[cpuid] == NULL)
5960Sstevel@tonic-gate 		return ((ushort_t)-1);
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate 	return (cpu_sgnblkp[cpuid]->sigb_signature.state_t.sig);
5990Sstevel@tonic-gate }
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate uchar_t
6020Sstevel@tonic-gate get_cpu_sgn_state(int cpuid)
6030Sstevel@tonic-gate {
6040Sstevel@tonic-gate 	if (cpu_sgnblkp[cpuid] == NULL)
6050Sstevel@tonic-gate 		return ((uchar_t)-1);
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate 	return (cpu_sgnblkp[cpuid]->sigb_signature.state_t.state);
6080Sstevel@tonic-gate }
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate /*
6110Sstevel@tonic-gate  * KDI functions - used by the in-situ kernel debugger (kmdb) to perform
6120Sstevel@tonic-gate  * platform-specific operations.  These functions execute when the world is
6130Sstevel@tonic-gate  * stopped, and as such cannot make any blocking calls, hold locks, etc.
6140Sstevel@tonic-gate  * promif functions are a special case, and may be used.
6150Sstevel@tonic-gate  */
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate static void
6180Sstevel@tonic-gate starfire_system_claim(void)
6190Sstevel@tonic-gate {
6200Sstevel@tonic-gate 	prom_interpret("sigb-sig! my-sigb-sig!", OBP_SIG, OBP_SIG, 0, 0, 0);
6210Sstevel@tonic-gate }
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate static void
6240Sstevel@tonic-gate starfire_system_release(void)
6250Sstevel@tonic-gate {
6260Sstevel@tonic-gate 	prom_interpret("sigb-sig! my-sigb-sig!", OS_SIG, OS_SIG, 0, 0, 0);
6270Sstevel@tonic-gate }
6280Sstevel@tonic-gate 
6290Sstevel@tonic-gate void
6300Sstevel@tonic-gate plat_kdi_init(kdi_t *kdi)
6310Sstevel@tonic-gate {
6320Sstevel@tonic-gate 	kdi->pkdi_system_claim = starfire_system_claim;
6330Sstevel@tonic-gate 	kdi->pkdi_system_release = starfire_system_release;
6340Sstevel@tonic-gate }
635