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
54266Sdp78419 * Common Development and Distribution License (the "License").
64266Sdp78419 * 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 */
2111311SSurya.Prakki@Sun.COM
220Sstevel@tonic-gate /*
23*12293SJames.McPherson@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24*12293SJames.McPherson@Sun.COM * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #include <sys/param.h>
280Sstevel@tonic-gate #include <sys/systm.h>
290Sstevel@tonic-gate #include <sys/sysmacros.h>
300Sstevel@tonic-gate #include <sys/sunddi.h>
310Sstevel@tonic-gate #include <sys/modctl.h>
320Sstevel@tonic-gate #include <sys/promif.h>
330Sstevel@tonic-gate #include <sys/machparam.h>
340Sstevel@tonic-gate #include <sys/kobj.h>
350Sstevel@tonic-gate #include <sys/mem_cage.h>
360Sstevel@tonic-gate #include <sys/starfire.h>
370Sstevel@tonic-gate
380Sstevel@tonic-gate #include <sys/platform_module.h>
390Sstevel@tonic-gate #include <sys/errno.h>
400Sstevel@tonic-gate #include <vm/page.h>
410Sstevel@tonic-gate #include <vm/hat_sfmmu.h>
420Sstevel@tonic-gate #include <sys/memnode.h>
430Sstevel@tonic-gate #include <vm/vm_dep.h>
440Sstevel@tonic-gate #include <sys/cpu_sgnblk_defs.h>
450Sstevel@tonic-gate #include <sys/cpu_sgn.h>
460Sstevel@tonic-gate #include <sys/kdi_impl.h>
4711066Srafael.vanoni@sun.com #include <sys/clock_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
set_platform_max_ncpus(void)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
startup_platform(void)830Sstevel@tonic-gate startup_platform(void)
840Sstevel@tonic-gate {
850Sstevel@tonic-gate }
860Sstevel@tonic-gate
870Sstevel@tonic-gate int
set_platform_tsb_spares()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
set_platform_defaults(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 */
11911311SSurya.Prakki@Sun.COM (void) 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
set_platform_cage_params(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 =
15411066Srafael.vanoni@sun.com 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 */
1674266Sdp78419 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
load_platform_drivers(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
plat_cpu_poweron(struct cpu * cp)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
plat_cpu_poweroff(struct cpu * cp)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
plat_dmv_params(uint_t * hwint,uint_t * swint)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
plat_max_boards()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
plat_max_cpu_units_per_board()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
plat_max_mem_units_per_board()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
plat_max_io_units_per_board()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
plat_freelist_process(int mnode)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;
29211066Srafael.vanoni@sun.com idx++) {
2930Sstevel@tonic-gate bdlist[idx] = NULL;
2940Sstevel@tonic-gate sortlist[idx] = NULL;
2950Sstevel@tonic-gate }
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate /* find freelist */
298*12293SJames.McPherson@Sun.COM freelist = &PAGE_FREELISTS(mnode, size,
299*12293SJames.McPherson@Sun.COM color, mtype);
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate if (*freelist == NULL)
3020Sstevel@tonic-gate continue;
3030Sstevel@tonic-gate
3040Sstevel@tonic-gate /* acquire locks */
305*12293SJames.McPherson@Sun.COM 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;
35111066Srafael.vanoni@sun.com 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++]
42111066Srafael.vanoni@sun.com /* CSTYLED */
4220Sstevel@tonic-gate = &bdlist[idy];
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate }
4260Sstevel@tonic-gate page_unlock(page);
4270Sstevel@tonic-gate }
4280Sstevel@tonic-gate mutex_exit(pcm);
4290Sstevel@tonic-gate }
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate }
4330Sstevel@tonic-gate
4340Sstevel@tonic-gate /*
4350Sstevel@tonic-gate * If ubound > 0, will return an int between 0 & ubound
4360Sstevel@tonic-gate * If ubound < 0, will set "random seed"
4370Sstevel@tonic-gate */
4380Sstevel@tonic-gate static uint_t
random_idx(int ubound)4390Sstevel@tonic-gate random_idx(int ubound)
4400Sstevel@tonic-gate {
4410Sstevel@tonic-gate static int idx = 0;
4420Sstevel@tonic-gate
4430Sstevel@tonic-gate if (ubound > 0) {
4440Sstevel@tonic-gate idx = (idx + 1) % ubound;
4450Sstevel@tonic-gate return (idx);
4460Sstevel@tonic-gate }
4470Sstevel@tonic-gate idx = -ubound;
4480Sstevel@tonic-gate return (0);
4490Sstevel@tonic-gate }
4500Sstevel@tonic-gate
4510Sstevel@tonic-gate /*
4520Sstevel@tonic-gate * No platform drivers on this platform
4530Sstevel@tonic-gate */
4540Sstevel@tonic-gate char *platform_module_list[] = {
4550Sstevel@tonic-gate (char *)0
4560Sstevel@tonic-gate };
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate /*ARGSUSED*/
4590Sstevel@tonic-gate void
plat_tod_fault(enum tod_fault_type tod_bad)4600Sstevel@tonic-gate plat_tod_fault(enum tod_fault_type tod_bad)
4610Sstevel@tonic-gate {
4620Sstevel@tonic-gate }
4630Sstevel@tonic-gate
4640Sstevel@tonic-gate /*
4650Sstevel@tonic-gate * Update signature block and the signature ring buffer of a given cpu_id.
4660Sstevel@tonic-gate */
4670Sstevel@tonic-gate void
cpu_sgn_update(ushort_t sgn,uchar_t state,uchar_t sub_state,int cpuid)4680Sstevel@tonic-gate cpu_sgn_update(ushort_t sgn, uchar_t state, uchar_t sub_state, int cpuid)
4690Sstevel@tonic-gate {
4700Sstevel@tonic-gate uchar_t idx;
4710Sstevel@tonic-gate cpu_sgnblk_t *cpu_sgnblkptr;
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate /*
4740Sstevel@tonic-gate * cpuid == -1 indicates that the operation applies to all cpus.
4750Sstevel@tonic-gate */
4760Sstevel@tonic-gate if (cpuid < 0) {
4770Sstevel@tonic-gate sgn_update_all_cpus(sgn, state, sub_state);
4780Sstevel@tonic-gate return;
4790Sstevel@tonic-gate }
4800Sstevel@tonic-gate
4810Sstevel@tonic-gate if (cpu_sgnblkp[cpuid] == NULL)
4820Sstevel@tonic-gate return;
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate cpu_sgnblkptr = cpu_sgnblkp[cpuid];
4850Sstevel@tonic-gate
4860Sstevel@tonic-gate /*
4870Sstevel@tonic-gate * Map new generic cpu states to older Starfire states.
4880Sstevel@tonic-gate */
4890Sstevel@tonic-gate switch (state) {
4900Sstevel@tonic-gate case SIGST_OFFLINE:
4910Sstevel@tonic-gate state = SIGBST_OFFLINE;
4920Sstevel@tonic-gate break;
4930Sstevel@tonic-gate case SIGST_RESUME_INPROGRESS:
4940Sstevel@tonic-gate state = SIGBST_RESUME_INPROGRESS;
4950Sstevel@tonic-gate break;
4960Sstevel@tonic-gate case SIGST_QUIESCE_INPROGRESS:
4970Sstevel@tonic-gate state = SIGBST_QUIESCE_INPROGRESS;
4980Sstevel@tonic-gate break;
4990Sstevel@tonic-gate case SIGST_QUIESCED:
5000Sstevel@tonic-gate state = SIGBST_QUIESCED;
5010Sstevel@tonic-gate break;
5020Sstevel@tonic-gate case SIGST_EXIT:
5030Sstevel@tonic-gate switch (sub_state) {
5040Sstevel@tonic-gate case SIGSUBST_DEBUG:
5050Sstevel@tonic-gate state = SIGBST_RUN;
5060Sstevel@tonic-gate sub_state = EXIT_NULL;
5070Sstevel@tonic-gate break;
5080Sstevel@tonic-gate case SIGSUBST_PANIC_CONT:
5090Sstevel@tonic-gate state = SIGBST_RUN;
5100Sstevel@tonic-gate sub_state = EXIT_PANIC2;
5110Sstevel@tonic-gate break;
5120Sstevel@tonic-gate case SIGSUBST_DUMP:
5130Sstevel@tonic-gate state = SIGBST_EXIT;
5140Sstevel@tonic-gate sub_state = EXIT_PANIC2;
5150Sstevel@tonic-gate break;
5160Sstevel@tonic-gate default:
5170Sstevel@tonic-gate break;
5180Sstevel@tonic-gate }
5190Sstevel@tonic-gate break;
5200Sstevel@tonic-gate default:
5210Sstevel@tonic-gate break;
5220Sstevel@tonic-gate }
5230Sstevel@tonic-gate
5240Sstevel@tonic-gate cpu_sgnblkptr->sigb_signature.state_t.sig = sgn;
5250Sstevel@tonic-gate cpu_sgnblkptr->sigb_signature.state_t.state = state;
5260Sstevel@tonic-gate cpu_sgnblkptr->sigb_signature.state_t.sub_state = sub_state;
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate /* Update the ring buffer */
5290Sstevel@tonic-gate idx = cpu_sgnblkptr->sigb_ringbuf.wr_ptr;
5300Sstevel@tonic-gate cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.sig = sgn;
5310Sstevel@tonic-gate cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.state = state;
5320Sstevel@tonic-gate cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.sub_state = sub_state;
5330Sstevel@tonic-gate cpu_sgnblkptr->sigb_ringbuf.wr_ptr += 1;
5340Sstevel@tonic-gate cpu_sgnblkptr->sigb_ringbuf.wr_ptr &= RB_IDX_MASK;
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate
5370Sstevel@tonic-gate /*
5380Sstevel@tonic-gate * Update signature block and the signature ring buffer of all CPUs.
5390Sstevel@tonic-gate */
5400Sstevel@tonic-gate void
sgn_update_all_cpus(ushort_t sgn,uchar_t state,uchar_t sub_state)5410Sstevel@tonic-gate sgn_update_all_cpus(ushort_t sgn, uchar_t state, uchar_t sub_state)
5420Sstevel@tonic-gate {
5430Sstevel@tonic-gate int i = 0;
5440Sstevel@tonic-gate uchar_t cpu_state;
5450Sstevel@tonic-gate uchar_t cpu_sub_state;
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate for (i = 0; i < NCPU; i++) {
5480Sstevel@tonic-gate cpu_sgnblk_t *sblkp;
5490Sstevel@tonic-gate
5500Sstevel@tonic-gate sblkp = cpu_sgnblkp[i];
5510Sstevel@tonic-gate cpu_sub_state = sub_state;
5520Sstevel@tonic-gate
5530Sstevel@tonic-gate if ((sblkp != NULL) && (cpu[i] != NULL && (cpu[i]->cpu_flags &
55411066Srafael.vanoni@sun.com (CPU_EXISTS|CPU_QUIESCED)))) {
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate if (sub_state == EXIT_REBOOT) {
5570Sstevel@tonic-gate cpu_sub_state =
55811066Srafael.vanoni@sun.com sblkp->sigb_signature.state_t.sub_state;
5590Sstevel@tonic-gate
5600Sstevel@tonic-gate if ((cpu_sub_state == EXIT_PANIC1) ||
56111066Srafael.vanoni@sun.com (cpu_sub_state == EXIT_PANIC2))
5620Sstevel@tonic-gate cpu_sub_state = EXIT_PANIC_REBOOT;
5630Sstevel@tonic-gate else
5640Sstevel@tonic-gate cpu_sub_state = EXIT_REBOOT;
5650Sstevel@tonic-gate }
5660Sstevel@tonic-gate
5670Sstevel@tonic-gate /*
5680Sstevel@tonic-gate * If we get here from an OBP sync after watchdog,
5690Sstevel@tonic-gate * we need to retain the watchdog sync state so that
5700Sstevel@tonic-gate * hostmon knows what's going on. So if we're in
5710Sstevel@tonic-gate * watchdog we don't update the state.
5720Sstevel@tonic-gate */
5730Sstevel@tonic-gate
5740Sstevel@tonic-gate cpu_state = sblkp->sigb_signature.state_t.state;
5750Sstevel@tonic-gate if (cpu_state == SIGBST_WATCHDOG_SYNC)
5760Sstevel@tonic-gate cpu_sgn_update(sgn, SIGBST_WATCHDOG_SYNC,
57711066Srafael.vanoni@sun.com cpu_sub_state, i);
5780Sstevel@tonic-gate else if (cpu_state == SIGBST_REDMODE_SYNC)
5790Sstevel@tonic-gate cpu_sgn_update(sgn, SIGBST_REDMODE_SYNC,
58011066Srafael.vanoni@sun.com cpu_sub_state, i);
5810Sstevel@tonic-gate else
5820Sstevel@tonic-gate cpu_sgn_update(sgn, state, cpu_sub_state, i);
5830Sstevel@tonic-gate }
5840Sstevel@tonic-gate }
5850Sstevel@tonic-gate }
5860Sstevel@tonic-gate
5870Sstevel@tonic-gate int
cpu_sgn_exists(int cpuid)5880Sstevel@tonic-gate cpu_sgn_exists(int cpuid)
5890Sstevel@tonic-gate {
5900Sstevel@tonic-gate return (cpu_sgnblkp[cpuid] != NULL);
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate ushort_t
get_cpu_sgn(int cpuid)5940Sstevel@tonic-gate get_cpu_sgn(int cpuid)
5950Sstevel@tonic-gate {
5960Sstevel@tonic-gate if (cpu_sgnblkp[cpuid] == NULL)
5970Sstevel@tonic-gate return ((ushort_t)-1);
5980Sstevel@tonic-gate
5990Sstevel@tonic-gate return (cpu_sgnblkp[cpuid]->sigb_signature.state_t.sig);
6000Sstevel@tonic-gate }
6010Sstevel@tonic-gate
6020Sstevel@tonic-gate uchar_t
get_cpu_sgn_state(int cpuid)6030Sstevel@tonic-gate get_cpu_sgn_state(int cpuid)
6040Sstevel@tonic-gate {
6050Sstevel@tonic-gate if (cpu_sgnblkp[cpuid] == NULL)
6060Sstevel@tonic-gate return ((uchar_t)-1);
6070Sstevel@tonic-gate
6080Sstevel@tonic-gate return (cpu_sgnblkp[cpuid]->sigb_signature.state_t.state);
6090Sstevel@tonic-gate }
6100Sstevel@tonic-gate
6110Sstevel@tonic-gate /*
6120Sstevel@tonic-gate * KDI functions - used by the in-situ kernel debugger (kmdb) to perform
6130Sstevel@tonic-gate * platform-specific operations. These functions execute when the world is
6140Sstevel@tonic-gate * stopped, and as such cannot make any blocking calls, hold locks, etc.
6150Sstevel@tonic-gate * promif functions are a special case, and may be used.
6160Sstevel@tonic-gate */
6170Sstevel@tonic-gate
6180Sstevel@tonic-gate static void
starfire_system_claim(void)6190Sstevel@tonic-gate starfire_system_claim(void)
6200Sstevel@tonic-gate {
62111066Srafael.vanoni@sun.com lbolt_debug_entry();
62211066Srafael.vanoni@sun.com
6230Sstevel@tonic-gate prom_interpret("sigb-sig! my-sigb-sig!", OBP_SIG, OBP_SIG, 0, 0, 0);
6240Sstevel@tonic-gate }
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate static void
starfire_system_release(void)6270Sstevel@tonic-gate starfire_system_release(void)
6280Sstevel@tonic-gate {
6290Sstevel@tonic-gate prom_interpret("sigb-sig! my-sigb-sig!", OS_SIG, OS_SIG, 0, 0, 0);
63011066Srafael.vanoni@sun.com
63111066Srafael.vanoni@sun.com lbolt_debug_return();
6320Sstevel@tonic-gate }
6330Sstevel@tonic-gate
6340Sstevel@tonic-gate void
plat_kdi_init(kdi_t * kdi)6350Sstevel@tonic-gate plat_kdi_init(kdi_t *kdi)
6360Sstevel@tonic-gate {
6370Sstevel@tonic-gate kdi->pkdi_system_claim = starfire_system_claim;
6380Sstevel@tonic-gate kdi->pkdi_system_release = starfire_system_release;
6390Sstevel@tonic-gate }
640