Home | History | Annotate | Line # | Download | only in sgimips
      1 /*	$NetBSD: machdep.c,v 1.156 2024/05/23 06:14:12 skrll Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2000 Soren S. Jorvang
      5  * Copyright (c) 2001, 2002, 2003 Rafal K. Boni
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *          This product includes software developed for the
     19  *          NetBSD Project.  See http://www.NetBSD.org/ for
     20  *          information about NetBSD.
     21  * 4. The name of the author may not be used to endorse or promote products
     22  *    derived from this software without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     34  */
     35 
     36 #include <sys/cdefs.h>
     37 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.156 2024/05/23 06:14:12 skrll Exp $");
     38 
     39 #include "opt_ddb.h"
     40 #include "opt_kgdb.h"
     41 #include "opt_execfmt.h"
     42 #include "opt_cputype.h"
     43 #include "opt_mips_cache.h"
     44 #include "opt_modular.h"
     45 
     46 #define __INTR_PRIVATE
     47 
     48 #include <sys/param.h>
     49 #include <sys/systm.h>
     50 #include <sys/kernel.h>
     51 #include <sys/proc.h>
     52 #include <sys/buf.h>
     53 #include <sys/bus.h>
     54 #include <sys/reboot.h>
     55 #include <sys/conf.h>
     56 #include <sys/file.h>
     57 #include <sys/intr.h>
     58 #include <sys/mbuf.h>
     59 #include <sys/msgbuf.h>
     60 #include <sys/device.h>
     61 #include <sys/exec.h>
     62 #include <sys/mount.h>
     63 #include <sys/syscallargs.h>
     64 #include <sys/kcore.h>
     65 #include <sys/boot_flag.h>
     66 #include <sys/ksyms.h>
     67 #include <sys/cpu.h>
     68 
     69 #include <uvm/uvm_extern.h>
     70 
     71 #include <mips/locore.h>
     72 
     73 #include <machine/reg.h>
     74 #include <machine/psl.h>
     75 #include <machine/autoconf.h>
     76 #include <machine/machtype.h>
     77 #include <machine/sysconf.h>
     78 #include <machine/bootinfo.h>
     79 
     80 #include <mips/cache.h>
     81 #include <mips/cache_r5k.h>
     82 #ifdef ENABLE_MIPS4_CACHE_R10K
     83 #include <mips/cache_r10k.h>
     84 #endif
     85 
     86 #include <sgimips/dev/int2reg.h>
     87 #include <sgimips/dev/crimevar.h>
     88 #include <sgimips/sgimips/arcemu.h>
     89 
     90 #include <dev/arcbios/arcbios.h>
     91 #include <dev/arcbios/arcbiosvar.h>
     92 
     93 #include "ksyms.h"
     94 
     95 #if NKSYMS || defined(DDB) || defined(MODULAR) || defined(KGDB)
     96 #include <machine/db_machdep.h>
     97 #include <ddb/db_access.h>
     98 #include <ddb/db_sym.h>
     99 #include <ddb/db_extern.h>
    100 #include <sys/exec_elf.h>
    101 #endif
    102 
    103 #include "mcclock_mace.h"
    104 #include "crime.h"
    105 
    106 #if NMCCLOCK_MACE > 0
    107 void mcclock_poweroff(void);
    108 #endif
    109 
    110 struct sgimips_intrhand intrtab[NINTR];
    111 
    112 /* Maps for VM objects. */
    113 struct vm_map *phys_map = NULL;
    114 
    115 int mach_type = 0;	/* IPxx type */
    116 int mach_subtype = 0;	/* subtype: eg., Guinness/Fullhouse for IP22 */
    117 int mach_boardrev = 0;	/* machine board revision, in case it matters */
    118 
    119 int arcsmem;		/* Memory used by the ARCS firmware */
    120 
    121 int ncpus;
    122 
    123 #define IPL2SPL_TABLE_COMMON					\
    124 	[IPL_NONE] =		0,				\
    125 	[IPL_SOFTCLOCK] =	MIPS_SOFT_INT_MASK_0,		\
    126 	[IPL_SOFTNET] =		MIPS_SOFT_INT_MASK,		\
    127 	[IPL_DDB] =		MIPS_INT_MASK,			\
    128 	[IPL_HIGH] =		MIPS_INT_MASK
    129 
    130 /* CPU interrupt sr maps */
    131 #if defined(MIPS1)
    132 static const struct ipl_sr_map sgi_ip6_ipl_sr_map = {
    133     .sr_bits = {
    134 	IPL2SPL_TABLE_COMMON,
    135 	[IPL_VM] = MIPS_INT_MASK_1|MIPS_INT_MASK_0|MIPS_SOFT_INT_MASK,
    136 	[IPL_SCHED] = MIPS_INT_MASK_4|MIPS_INT_MASK_2|
    137 	    MIPS_INT_MASK_1|MIPS_INT_MASK_0|MIPS_SOFT_INT_MASK,
    138     },
    139 };
    140 static const struct ipl_sr_map sgi_ip12_ipl_sr_map = {
    141     .sr_bits = {
    142 	IPL2SPL_TABLE_COMMON,
    143 	[IPL_VM] = MIPS_INT_MASK_2|MIPS_INT_MASK_1|MIPS_INT_MASK_0|
    144 	    MIPS_SOFT_INT_MASK,
    145 	[IPL_SCHED] = MIPS_INT_MASK_4|MIPS_INT_MASK_3|MIPS_INT_MASK_2|
    146 	    MIPS_INT_MASK_1|MIPS_INT_MASK_0|MIPS_SOFT_INT_MASK,
    147     },
    148 };
    149 #endif /* defined(MIPS1) */
    150 
    151 #if defined(MIPS3)
    152 static const struct ipl_sr_map sgi_ip2x_ipl_sr_map = {
    153     .sr_bits = {
    154 	IPL2SPL_TABLE_COMMON,
    155 	[IPL_VM] = MIPS_INT_MASK_1|MIPS_INT_MASK_0|MIPS_SOFT_INT_MASK,
    156 	[IPL_SCHED] = MIPS_INT_MASK,
    157     },
    158 };
    159 static const struct ipl_sr_map sgi_ip3x_ipl_sr_map = {
    160     .sr_bits = {
    161 	IPL2SPL_TABLE_COMMON,
    162 	[IPL_VM] = MIPS_INT_MASK_0|MIPS_SOFT_INT_MASK,
    163 	[IPL_SCHED] = MIPS_INT_MASK_5|MIPS_INT_MASK_0|MIPS_SOFT_INT_MASK,
    164     },
    165 };
    166 #endif /* defined(MIPS3) */
    167 
    168 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
    169 int mem_cluster_cnt;
    170 
    171 #if defined(INDY_R4600_CACHE)
    172 extern void	ip22_sdcache_disable(void);
    173 extern void	ip22_sdcache_enable(void);
    174 #endif
    175 
    176 #if defined(MIPS3)
    177 extern void mips3_clock_intr(vaddr_t, uint32_t, uint32_t);
    178 #endif
    179 
    180 void	mach_init(int, int32_t *, uintptr_t, int32_t);
    181 
    182 void	sgimips_count_cpus(struct arcbios_component *,
    183 	    struct arcbios_treewalk_context *);
    184 
    185 #ifdef KGDB
    186 void kgdb_port_init(void);
    187 void kgdb_connect(int);
    188 #endif
    189 
    190 void mips_machdep_find_l2cache(struct arcbios_component *comp, struct arcbios_treewalk_context *atc);
    191 
    192 /* Motherboard or system-specific initialization vector */
    193 static void	unimpl_bus_reset(void);
    194 static void	unimpl_cons_init(void);
    195 static void	*unimpl_intr_establish(int, int, int (*)(void *), void *);
    196 static void	unimpl_intr(vaddr_t, uint32_t, uint32_t);
    197 static unsigned	long nulllong(void);
    198 static void	nullvoid(void);
    199 
    200 void ddb_trap_hook(int where);
    201 
    202 static int badaddr_workaround(void *, size_t);
    203 
    204 struct platform platform = {
    205 	.badaddr		= badaddr_workaround,
    206 	.bus_reset		= unimpl_bus_reset,
    207 	.cons_init		= unimpl_cons_init,
    208 	.intr_establish		= unimpl_intr_establish,
    209 	.clkread		= nulllong,
    210 	.watchdog_reset		= nullvoid,
    211 	.watchdog_disable	= nullvoid,
    212 	.watchdog_enable	= nullvoid,
    213 	.intr0			= unimpl_intr,
    214 	.intr1			= unimpl_intr,
    215 	.intr2			= unimpl_intr,
    216 	.intr3			= unimpl_intr,
    217 	.intr4			= unimpl_intr,
    218 	.intr5			= unimpl_intr
    219 };
    220 
    221 extern u_int32_t ssir;
    222 extern char kernel_text[], edata[], end[];
    223 
    224 uint8_t *bootinfo;			/* pointer to bootinfo structure */
    225 static uint8_t bi_buf[BOOTINFO_SIZE];	/* buffer to store bootinfo data */
    226 static const char *bootinfo_msg = NULL;
    227 
    228 #define ARCS_VECTOR MIPS_PHYS_TO_KSEG0(0x00001000)
    229 
    230 /*
    231  * Do all the stuff that locore normally does before calling main().
    232  * Process arguments passed to us by the ARCS firmware.
    233  */
    234 void
    235 mach_init(int argc, int32_t argv32[], uintptr_t magic, int32_t bip32)
    236 {
    237 	paddr_t first, last;
    238 	vsize_t size;
    239 	void *bip = (void *)(intptr_t)bip32;
    240 	struct arcbios_mem *mem;
    241 	const char *cpufreq, *osload;
    242 	char *bootpath = NULL;
    243 	vaddr_t kernend;
    244 	u_int i;
    245 	int rv;
    246 #if NKSYMS || defined(DDB) || defined(MODULAR)
    247 	int nsym = 0;
    248 	char *ssym = NULL;
    249 	char *esym = NULL;
    250 	struct btinfo_symtab *bi_syms;
    251 #endif /* NKSYMS || defined(DDB) || defined(MODULAR) */
    252 #ifdef _LP64
    253 	char *argv[20];
    254 
    255 	if (argc >= __arraycount(argv))
    256 		panic("too many args");
    257 
    258 	for (i = 0; i < argc; i++) {
    259 		argv[i] = (void *)(intptr_t)argv32[i];
    260 	}
    261 #else
    262 	char **argv = (void *)argv32;
    263 #endif
    264 
    265 	/*
    266 	 * Initialize firmware.  This will set up the bootstrap console.
    267 	 * At this point we do not yet know the machine type, so we
    268 	 * try to init real arcbios, and if that fails (return value 1),
    269 	 * fall back to the emulator.  If the latter fails also we
    270 	 * don't have much to panic with.
    271 	 *
    272 	 * The third argument (magic) is the environment variable array if
    273 	 * there's no bootinfo.
    274 	 */
    275 	if (arcbios_init(ARCS_VECTOR) == 1) {
    276 #ifdef _LP64
    277 		panic("no ARCS firmware");
    278 #else
    279 		if (magic == BOOTINFO_MAGIC)
    280 			arcemu_init(NULL);	/* XXX - need some prom env */
    281 		else
    282 			arcemu_init((const char **)magic);
    283 #endif
    284 	}
    285 
    286 	cpu_setmodel("%s", arcbios_system_identifier);
    287 
    288 	/*
    289 	 * Copy exception-dispatch code down to exception vector.
    290 	 * Initialize locore-function vector.
    291 	 * Clear out the I and D caches.
    292 	 */
    293 	mips_vector_init(NULL, false);
    294 
    295 	uvm_md_init();
    296 
    297 	/* set up bootinfo structures */
    298 	if (magic == BOOTINFO_MAGIC && bip != NULL) {
    299 		struct btinfo_magic *bi_magic;
    300 		struct btinfo_bootpath *bi_path;
    301 
    302 		memcpy(bi_buf, bip, BOOTINFO_SIZE);
    303 		bootinfo = bi_buf;
    304 		bi_magic = lookup_bootinfo(BTINFO_MAGIC);
    305 		if (bi_magic != NULL && bi_magic->magic == BOOTINFO_MAGIC) {
    306 			bootinfo_msg = "bootinfo found.\n";
    307 			bi_path = lookup_bootinfo(BTINFO_BOOTPATH);
    308 			if (bi_path != NULL)
    309 				bootpath = bi_path->bootpath;
    310 		} else
    311 			bootinfo_msg =
    312 			    "invalid magic number in bootinfo structure.\n";
    313 	} else
    314 		bootinfo_msg = "no bootinfo found. (old bootblocks?)\n";
    315 
    316 #if NKSYMS || defined(DDB) || defined(MODULAR)
    317 	bi_syms = lookup_bootinfo(BTINFO_SYMTAB);
    318 
    319 	/* check whether there is valid bootinfo symtab info */
    320 	if (bi_syms != NULL) {
    321 		nsym = bi_syms->nsym;
    322 		ssym = (char *)bi_syms->ssym;
    323 		esym = (char *)bi_syms->esym;
    324 		kernend = mips_round_page(esym);
    325 	} else
    326 #endif /* NKSYMS || defined(DDB) || defined(MODULAR) */
    327 	{
    328 		kernend = mips_round_page(end);
    329 	}
    330 
    331 	cpufreq = arcbios_GetEnvironmentVariable("cpufreq");
    332 
    333 	if (cpufreq == 0)
    334 		panic("no $cpufreq");
    335 
    336 	/*
    337 	 * Note initial estimate of CPU speed... If we care enough, we'll
    338 	 * use the RTC to get a better estimate later.
    339 	 */
    340 	curcpu()->ci_cpu_freq = strtoul(cpufreq, NULL, 10) * 1000000;
    341 
    342 	/*
    343 	 * Also initialize ci members for delay and clock by the temporary
    344 	 * ci_cpu_freq value for early use of delay(9).
    345 	 * These values will be calibrated later in MD code:
    346 	 *  - int_attach() in dev/int.c for IP6/10/12/20/22
    347 	 *  - crime_attach() in dev/crime.c for IP32
    348 	 *
    349 	 * XXX: ci_divisor_delay is for mips3_delay() in mips/mips3_clock.c
    350 	 *      but sgimips abuse it as "instructions per microsecond"
    351 	 *      for traditional delay(9) implementation derived from
    352 	 *      4.4BSD/mips (also used in pmax and news3400).
    353 	 *	(see sys/arch/mips/mips/mips_mcclock.c etc.)
    354 	 *
    355 	 * Note ci_cycles_per_hz is for mips3_clockintr.c for MIPS3 so
    356 	 * there is no early use, but initialize it as a sane default.
    357 	 */
    358 	curcpu()->ci_cycles_per_hz = curcpu()->ci_cpu_freq / (2 * hz);
    359 	curcpu()->ci_divisor_delay = curcpu()->ci_cpu_freq / (2 * 1000000);
    360 
    361 	/*
    362 	 * Check machine (IPn) type.
    363 	 *
    364 	 * Note even on IP12 (which doesn't have ARCBIOS),
    365 	 * arcbios_system_identifiler[] has been initilialized
    366 	 * in arcemu_ip12_init().
    367 	 */
    368 	for (i = 0; arcbios_system_identifier[i] != '\0'; i++) {
    369 		if (mach_type == 0 &&
    370 		    arcbios_system_identifier[i] >= '0' &&
    371 		    arcbios_system_identifier[i] <= '9') {
    372 			mach_type = strtoul(&arcbios_system_identifier[i],
    373 			    NULL, 10);
    374 			break;
    375 		}
    376 	}
    377 	if (mach_type <= 0)
    378 		panic("invalid architecture");
    379 
    380 	/*
    381 	 * Get boot device information.
    382 	 */
    383 
    384 	/* Try to get the boot device information from bootinfo first. */
    385 	if (bootpath != NULL)
    386 		makebootdev(bootpath);
    387 	else {
    388 		/*
    389 		 * The old bootloader prior to 5.0 doesn't pass bootinfo.
    390 		 * If argv[0] is the bootloader, then argv[1] might be
    391 		 * the kernel that was loaded.
    392 		 * If argv[1] isn't an environment string, try to use it
    393 		 * to set the boot device.
    394 		 */
    395 		if (argc > 1 && strchr(argv[1], '=') != 0)
    396 			makebootdev(argv[1]);
    397 
    398 		/*
    399 		 * If we are loaded directly by ARCBIOS,
    400 		 * argv[0] is the path of the loaded kernel,
    401 		 * but booted_partition could be SGIVOLHDR in such case,
    402 		 * so assume root is partition a.
    403 		 */
    404 		if (argc > 0 && argv[0] != NULL) {
    405 			makebootdev(argv[0]);
    406 			booted_partition = 0;
    407 		}
    408 	}
    409 
    410 	/*
    411 	 * Also try to get the default bootpath from ARCBIOS environment
    412 	 * because bootpath is not set properly by old bootloaders and
    413 	 * argv[0] might be invalid on some machine.
    414 	 */
    415 	osload = arcbios_GetEnvironmentVariable("OSLoadPartition");
    416 	if (osload != NULL)
    417 		makebootdev(osload);
    418 
    419 	/*
    420 	 * The case where the kernel has been loaded by a
    421 	 * boot loader will usually have been caught by
    422 	 * the first makebootdev() case earlier on, but
    423 	 * we still use OSLoadPartition to get the preferred
    424 	 * root filesystem location, even if it's not
    425 	 * actually the location of the loaded kernel.
    426 	 */
    427 	for (i = 0; i < argc; i++) {
    428 		if (strncmp(argv[i], "OSLoadPartition=", 15) == 0)
    429 			makebootdev(argv[i] + 16);
    430 	}
    431 
    432 	/*
    433 	 * When the kernel is loaded directly by the firmware, and
    434 	 * no explicit OSLoadPartition is set, we fall back on
    435 	 * SystemPartition for the boot device.
    436 	 */
    437 	for (i = 0; i < argc; i++) {
    438 		if (strncmp(argv[i], "SystemPartition", 15) == 0)
    439 			makebootdev(argv[i] + 16);
    440 	}
    441 
    442 	/*
    443 	 * Single- or multi-user ('auto' in SGI terms).
    444 	 *
    445 	 * Query ARCBIOS first, then default to environment variables.
    446 	 */
    447 
    448 	/* Set default to single user. */
    449 	boothowto = RB_SINGLE;
    450 
    451 	osload = arcbios_GetEnvironmentVariable("OSLoadOptions");
    452 	if (osload != NULL && strcmp(osload, "auto") == 0)
    453 		boothowto &= ~RB_SINGLE;
    454 
    455 	for (i = 0; i < argc; i++) {
    456 		if (strcmp(argv[i], "OSLoadOptions=auto") == 0)
    457 			boothowto &= ~RB_SINGLE;
    458 	}
    459 
    460 	/*
    461 	 * Pass the args again to check for flags -- This is done
    462 	 * AFTER checking for OSLoadOptions to ensure that "auto"
    463 	 * does not override the "-s" flag.
    464 	 */
    465 
    466 	for (i = 0; i < argc; i++) {
    467 		/*
    468 		 * Unfortunately, it appears that IP12's prom passes a '-a'
    469 		 * flag when booting a kernel directly from a disk volume
    470 		 * header. This corresponds to RB_ASKNAME in NetBSD, but
    471 		 * appears to mean 'autoboot' in prehistoric SGI-speak.
    472 		 */
    473 		if (mach_type < MACH_SGI_IP20 && bootinfo == NULL &&
    474 		    strcmp(argv[i], "-a") == 0)
    475 			continue;
    476 
    477 		/*
    478 		 * Extract out any flags passed for the kernel in the
    479 		 * argument string.  Warn for unknown/invalid flags,
    480 		 * but silently skip non-flag arguments, as they are
    481 		 * likely PROM environment values (if I knew those
    482 		 * would always precede *any* flags, then I'd say we
    483 		 * should warn about *all* unexpected values, but for
    484 		 * now this should be fine).
    485 		 *
    486 		 * Use the MI boot-flag extractor since we don't use
    487 		 * any special MD flags and to make sure we're up-to
    488 		 * date with new MI flags whenever they're added.
    489 		 */
    490 		if (argv[i][0] == '-') {
    491 			rv = 0;
    492 			BOOT_FLAG(argv[i][1], rv);
    493 
    494 			if (rv == 0) {
    495 				printf("Unexpected option '%s' ignored",
    496 				    argv[i]);
    497 			} else {
    498 				boothowto |= rv;
    499 			}
    500 		}
    501 	}
    502 
    503 #ifdef DEBUG
    504 	boothowto |= AB_DEBUG;
    505 #endif
    506 	aprint_debug("argc = %d\n", argc);
    507 	for (i = 0; i < argc; i++)
    508 		aprint_debug("argv[%d] = %s\n", i, argv[i]);
    509 
    510 #if NKSYMS || defined(DDB) || defined(MODULAR)
    511 	/* init symbols if present */
    512 	if (esym)
    513 		ksyms_addsyms_elf(nsym, ssym, esym);
    514 #endif /* NKSYMS || defined(DDB) || defined(MODULAR) */
    515 
    516 #if defined(KGDB) || defined(DDB)
    517 	/* Set up DDB hook to turn off watchdog on entry */
    518 	db_trap_callback = ddb_trap_hook;
    519 
    520 #ifdef DDB
    521 	if (boothowto & RB_KDB)
    522 		Debugger();
    523 #endif
    524 
    525 #ifdef KGDB
    526 	kgdb_port_init();
    527 
    528 	if (boothowto & RB_KDB)
    529 		kgdb_connect(0);
    530 #endif
    531 #endif
    532 
    533 	switch (mach_type) {
    534 #if defined(MIPS1)
    535 	case MACH_SGI_IP6 | MACH_SGI_IP10:
    536 		platform.intr3 = mips1_fpu_intr;
    537 		ipl_sr_map = sgi_ip6_ipl_sr_map;
    538 		break;
    539 
    540 	case MACH_SGI_IP12:
    541 		i = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(0x1fbd0000);
    542         	mach_boardrev = (i & 0x7000) >> 12;
    543 
    544 		if ((i & 0x8000) == 0) {
    545 			if (mach_boardrev < 7)
    546 				mach_subtype = MACH_SGI_IP12_4D_3X;
    547 			else
    548 				mach_subtype = MACH_SGI_IP12_VIP12;
    549 		} else {
    550 			if (mach_boardrev < 6)
    551 				mach_subtype = MACH_SGI_IP12_HP1;
    552 			else
    553 				mach_subtype = MACH_SGI_IP12_HPLC;
    554                 }
    555 
    556 		ipl_sr_map = sgi_ip12_ipl_sr_map;
    557 		platform.intr0 = mips1_fpu_intr;
    558 		break;
    559 #endif /* MIPS1 */
    560 
    561 #if defined(MIPS3)
    562 	case MACH_SGI_IP20:
    563 		i = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(0x1fbd0000);
    564 		mach_boardrev = (i & 0x7000) >> 12;
    565 		ipl_sr_map = sgi_ip2x_ipl_sr_map;
    566 		platform.intr5 = mips3_clock_intr;
    567 		break;
    568 	case MACH_SGI_IP22:
    569 		ipl_sr_map = sgi_ip2x_ipl_sr_map;
    570 		platform.intr5 = mips3_clock_intr;
    571 		break;
    572 	case MACH_SGI_IP30:
    573 		ipl_sr_map = sgi_ip3x_ipl_sr_map;
    574 		platform.intr5 = mips3_clock_intr;
    575 		break;
    576 	case MACH_SGI_IP32:
    577 		ipl_sr_map = sgi_ip3x_ipl_sr_map;
    578 		platform.intr5 = mips3_clock_intr;
    579 		break;
    580 #endif /* MIPS3 */
    581 	default:
    582 		panic("IP%d architecture not supported", mach_type);
    583 		break;
    584 	}
    585 
    586 	physmem = arcsmem = 0;
    587 	mem_cluster_cnt = 0;
    588 	mem = NULL;
    589 
    590 #ifdef DEBUG
    591 	i = 0;
    592 	mem = NULL;
    593 
    594 	do {
    595 		if ((mem = arcbios_GetMemoryDescriptor(mem)) != NULL) {
    596 			i++;
    597 			printf("Mem block %d: type %d, "
    598 			    "base 0x%04"PRIx32", size 0x%04"PRIx32"\n",
    599 			    i, mem->Type, mem->BasePage, mem->PageCount);
    600 		}
    601 	} while (mem != NULL);
    602 #endif
    603 
    604 	/*
    605 	 * XXX This code assumes that ARCS provides the memory
    606 	 * XXX sorted in ascending order.
    607 	 */
    608 	mem = NULL;
    609 	for (i = 0; mem_cluster_cnt < VM_PHYSSEG_MAX; i++) {
    610 		mem = arcbios_GetMemoryDescriptor(mem);
    611 
    612 		if (mem == NULL)
    613 			break;
    614 
    615 		first = round_page(mem->BasePage * ARCBIOS_PAGESIZE);
    616 		last = trunc_page(first + mem->PageCount * ARCBIOS_PAGESIZE);
    617 		size = last - first;
    618 
    619 		switch (mem->Type) {
    620 		case ARCBIOS_MEM_FreeContiguous:
    621 		case ARCBIOS_MEM_FreeMemory:
    622 		case ARCBIOS_MEM_LoadedProgram:
    623 			mem_clusters[mem_cluster_cnt].start = first;
    624 			mem_clusters[mem_cluster_cnt].size = size;
    625 			mem_cluster_cnt++;
    626 			break;
    627 
    628 		case ARCBIOS_MEM_FirmwareTemporary:
    629 		case ARCBIOS_MEM_FirmwarePermanent:
    630 			arcsmem += btoc(size);
    631 			break;
    632 
    633 		case ARCBIOS_MEM_ExceptionBlock:
    634 		case ARCBIOS_MEM_SystemParameterBlock:
    635 		case ARCBIOS_MEM_BadMemory:
    636 			break;
    637 
    638 		default:
    639 			panic("unknown memory descriptor %d type %d",
    640 				i, mem->Type);
    641 		}
    642 
    643 		physmem += btoc(size);
    644 
    645 	}
    646 
    647 	if (mem_cluster_cnt == 0)
    648 		panic("no free memory descriptors found");
    649 
    650 	/* Leave 1 page before kernel untouched as that's where our initial
    651 	 * kernel stack is */
    652 	/* XXX We could free it in cpu_startup() though XXX */
    653 	mips_page_physload((vaddr_t)kernel_text - PAGE_SIZE, (vaddr_t)kernend,
    654 	    mem_clusters, mem_cluster_cnt, NULL, 0);
    655 
    656 	/* We can now no longer use bootinfo. */
    657 	bootinfo = NULL;
    658 
    659 	/*
    660 	 * Initialize mips version-dependent DMA handlers.
    661 	 */
    662 	sgimips_bus_dma_init();
    663 
    664 	/*
    665 	 * Walk the component tree and count the number of CPUs
    666 	 * present in the system.
    667 	 */
    668 	arcbios_tree_walk(sgimips_count_cpus, NULL);
    669 
    670 	/*
    671 	 * Initialize error message buffer (at end of core).
    672 	 */
    673 	mips_init_msgbuf();
    674 
    675 	pmap_bootstrap();
    676 
    677 	/*
    678 	 * Allocate uarea for lwp0 and set it.
    679 	 */
    680 	mips_init_lwp0_uarea();
    681 }
    682 
    683 void
    684 sgimips_count_cpus(struct arcbios_component *node,
    685     struct arcbios_treewalk_context *atc)
    686 {
    687 
    688 	switch (node->Class) {
    689 	case COMPONENT_CLASS_ProcessorClass:
    690 		if (node->Type == COMPONENT_TYPE_CPU)
    691 			ncpus++;
    692 		break;
    693 
    694 	default:
    695 		break;
    696 	}
    697 }
    698 
    699 /*
    700  * Allocate memory for variable-sized tables.
    701  */
    702 void
    703 cpu_startup(void)
    704 {
    705 	vaddr_t minaddr, maxaddr;
    706 	char pbuf[9];
    707 
    708 #ifdef BOOTINFO_DEBUG
    709 	if (bootinfo_msg)
    710 		printf(bootinfo_msg);
    711 #endif
    712 
    713 	printf("%s%s", copyright, version);
    714 
    715 	format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
    716 	printf("total memory = %s\n", pbuf);
    717 	format_bytes(pbuf, sizeof(pbuf), ctob(arcsmem));
    718 	printf("(%s reserved for ARCS)\n", pbuf);
    719 
    720 	minaddr = 0;
    721 	/*
    722 	 * Allocate a submap for physio.
    723 	 */
    724 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
    725 				    VM_PHYS_SIZE, 0, false, NULL);
    726 
    727 	/*
    728 	 * (No need to allocate an mbuf cluster submap.  Mbuf clusters
    729 	 * are allocated via the pool allocator, and we use KSEG to
    730 	 * map those pages.)
    731 	 */
    732 	format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false)));
    733 	printf("avail memory = %s\n", pbuf);
    734 }
    735 
    736 int	waittime = -1;
    737 
    738 void
    739 cpu_reboot(int howto, char *bootstr)
    740 {
    741 	/* Take a snapshot before clobbering any registers. */
    742 	savectx(curpcb);
    743 
    744 	if (cold) {
    745 		howto |= RB_HALT;
    746 		goto haltsys;
    747 	}
    748 
    749 	/* If "always halt" was specified as a boot flag, obey. */
    750 	if (boothowto & RB_HALT)
    751 		howto |= RB_HALT;
    752 
    753 	boothowto = howto;
    754 	if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) {
    755 		waittime = 0;
    756 		vfs_shutdown();
    757 	}
    758 
    759 	/* Clear and disable watchdog timer. */
    760 	(void)(*platform.watchdog_disable)();
    761 
    762 	splhigh();
    763 
    764 	if (howto & RB_DUMP)
    765 		dumpsys();
    766 
    767 haltsys:
    768 
    769 	doshutdownhooks();
    770 
    771 	pmf_system_shutdown(boothowto);
    772 
    773 	/*
    774 	 * Calling arcbios_PowerDown() results in a "CP1 unusable trap"
    775 	 * which lands me back in DDB, at least on my Indy.  So, enable
    776 	 * the FPU before asking the PROM to power down to avoid this..
    777 	 * It seems to want the FPU to play the `poweroff tune' 8-/
    778 	 */
    779 	if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
    780 		/* Set CP1 usable bit in SR */
    781 	 	mips_cp0_status_write(mips_cp0_status_read() |
    782 					MIPS_SR_COP_1_BIT);
    783 
    784 		printf("powering off...\n\n");
    785 		delay(500000);
    786 #if NMCCLOCK_MACE > 0
    787 		if (mach_type == MACH_SGI_IP32) {
    788 			mcclock_poweroff();
    789 		} else
    790 #endif
    791 			arcbios_PowerDown();
    792 		printf("WARNING: powerdown failed\n");
    793 		/*
    794 		 * RB_POWERDOWN implies RB_HALT... fall into it...
    795 		 */
    796 	}
    797 
    798 	if (howto & RB_HALT) {
    799 		printf("halting...\n\n");
    800 		arcbios_EnterInteractiveMode();
    801 	}
    802 
    803 	printf("rebooting...\n\n");
    804 #if NCRIME > 0
    805 	if (mach_type == MACH_SGI_IP32) {
    806 		crime_reboot();
    807 	} else
    808 #endif
    809 		arcbios_Reboot();
    810 
    811 	for (;;);
    812 }
    813 
    814 void delay(unsigned long n)
    815 {
    816 	register int __N = curcpu()->ci_divisor_delay * n;
    817 
    818 	do {
    819 		__asm("addiu %0,%1,-1" : "=r" (__N) : "0" (__N));
    820 	} while (__N > 0);
    821 }
    822 
    823 /*
    824  * IP12 appears to be buggy and unable to reliably support badaddr.
    825  * Approximately 1.8% of the time a false negative (bad address said to
    826  * be good) is generated and we stomp on invalid registers. Testing has
    827  * not shown false positives, nor consecutive false negatives to occur.
    828  */
    829 static int
    830 badaddr_workaround(void *addr, size_t size)
    831 {
    832 	int i, bad;
    833 
    834 	for (i = bad = 0; i < 100; i++) {
    835 		if (badaddr(addr, size))
    836 			bad++;
    837 	}
    838 
    839 	/* false positives appear not to occur */
    840 	return (bad != 0);
    841 }
    842 
    843 /*
    844  *  Ensure all platform vectors are always initialized.
    845  */
    846 static void
    847 unimpl_bus_reset(void)
    848 {
    849 
    850 	panic("target init didn't set bus_reset");
    851 }
    852 
    853 static void
    854 unimpl_cons_init(void)
    855 {
    856 
    857 	panic("target init didn't set cons_init");
    858 }
    859 
    860 static void *
    861 unimpl_intr_establish(int level, int ipl, int (*handler) (void *), void *arg)
    862 {
    863 	panic("target init didn't set intr_establish");
    864 	return NULL;
    865 }
    866 
    867 static void
    868 unimpl_intr(vaddr_t pc, uint32_t status, uint32_t pending)
    869 {
    870 	printf("spurious interrupt pending %#x\n", pending);
    871 }
    872 
    873 static unsigned long
    874 nulllong(void)
    875 {
    876 	printf("nulllong\n");
    877 	return (0);
    878 }
    879 
    880 static void
    881 nullvoid(void)
    882 {
    883 	printf("nullvoid\n");
    884 	return;
    885 }
    886 
    887 void *
    888 lookup_bootinfo(int type)
    889 {
    890 	struct btinfo_common *bt;
    891 	uint8_t *bip;
    892 
    893 	/* check for a bootinfo record first */
    894 	if (bootinfo == NULL)
    895 		return NULL;
    896 
    897 	bip = bootinfo;
    898 	do {
    899 		bt = (struct btinfo_common *)bip;
    900 		if (bt->type == type)
    901 			return (void *)bt;
    902 		bip += bt->next;
    903 	} while (bt->next != 0 &&
    904 	    bt->next < BOOTINFO_SIZE /* sanity */ &&
    905 	    (size_t)bip < (size_t)bootinfo + BOOTINFO_SIZE);
    906 
    907 	return NULL;
    908 }
    909 
    910 #if defined(DDB) || defined(KGDB)
    911 
    912 void ddb_trap_hook(int where)
    913 {
    914 	switch (where) {
    915 	case 1:		/* Entry to DDB, turn watchdog off */
    916 		(void)(*platform.watchdog_disable)();
    917 		break;
    918 
    919 	case 0:		/* Exit from DDB, turn watchdog back on */
    920 		(void)(*platform.watchdog_enable)();
    921 		break;
    922 	}
    923 }
    924 
    925 #endif
    926 
    927 void mips_machdep_cache_config(void)
    928 {
    929 
    930 	arcbios_tree_walk(mips_machdep_find_l2cache, NULL);
    931 
    932 	switch (MIPS_PRID_IMPL(mips_options.mips_cpu_id)) {
    933 #if defined(INDY_R4600_CACHE)
    934 	case MIPS_R4600:
    935 		/*
    936 		 * R4600 is on Indy-class machines only.  Disable and
    937 		 * flush pcache.
    938 		 */
    939 		mips_cache_info.mci_sdcache_size = 0;
    940 		mips_cache_info.mci_sdcache_line_size = 0;
    941 		ip22_sdcache_disable();
    942 		break;
    943 #endif
    944 #if defined(MIPS3)
    945 	case MIPS_R5000:
    946 	case MIPS_RM5200:
    947 		r5k_enable_sdcache();
    948 		break;
    949 #endif
    950 	}
    951 }
    952 
    953 void
    954 mips_machdep_find_l2cache(struct arcbios_component *comp, struct arcbios_treewalk_context *atc)
    955 {
    956 	struct mips_cache_info * const mci = &mips_cache_info;
    957 	device_t self = atc->atc_cookie;
    958 
    959 	if (comp->Class != COMPONENT_CLASS_CacheClass)
    960 		return;
    961 
    962 	switch (comp->Type) {
    963 	case COMPONENT_TYPE_SecondaryICache:
    964 		panic("%s: split L2 cache", device_xname(self));
    965 	case COMPONENT_TYPE_SecondaryDCache:
    966 	case COMPONENT_TYPE_SecondaryCache:
    967 		mci->mci_sdcache_size = COMPONENT_KEY_Cache_CacheSize(comp->Key);
    968 		mci->mci_sdcache_line_size =
    969 		    COMPONENT_KEY_Cache_LineSize(comp->Key);
    970 		/* XXX */
    971 		mci->mci_sdcache_ways = 1;
    972 		break;
    973 	}
    974 }
    975