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