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