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
107void mcclock_poweroff(void);
108#endif
109
110struct sgimips_intrhand intrtab[NINTR];
111
112/* Maps for VM objects. */
113struct vm_map *phys_map = NULL;
114
115int mach_type = 0;	/* IPxx type */
116int mach_subtype = 0;	/* subtype: eg., Guinness/Fullhouse for IP22 */
117int mach_boardrev = 0;	/* machine board revision, in case it matters */
118
119int arcsmem;		/* Memory used by the ARCS firmware */
120
121int 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)
132static 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};
140static 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)
152static 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};
159static 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
168phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
169int mem_cluster_cnt;
170
171#if defined(INDY_R4600_CACHE)
172extern void	ip22_sdcache_disable(void);
173extern void	ip22_sdcache_enable(void);
174#endif
175
176#if defined(MIPS3)
177extern void mips3_clock_intr(vaddr_t, uint32_t, uint32_t);
178#endif
179
180void	mach_init(int, int32_t *, uintptr_t, int32_t);
181
182void	sgimips_count_cpus(struct arcbios_component *,
183	    struct arcbios_treewalk_context *);
184
185#ifdef KGDB
186void kgdb_port_init(void);
187void kgdb_connect(int);
188#endif
189
190void mips_machdep_find_l2cache(struct arcbios_component *comp, struct arcbios_treewalk_context *atc);
191
192/* Motherboard or system-specific initialization vector */
193static void	unimpl_bus_reset(void);
194static void	unimpl_cons_init(void);
195static void	*unimpl_intr_establish(int, int, int (*)(void *), void *);
196static void	unimpl_intr(vaddr_t, uint32_t, uint32_t);
197static unsigned	long nulllong(void);
198static void	nullvoid(void);
199
200void ddb_trap_hook(int where);
201
202static int badaddr_workaround(void *, size_t);
203
204struct 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
221extern u_int32_t ssir;
222extern char kernel_text[], edata[], end[];
223
224uint8_t *bootinfo;			/* pointer to bootinfo structure */
225static uint8_t bi_buf[BOOTINFO_SIZE];	/* buffer to store bootinfo data */
226static 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 */
234void
235mach_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
683void
684sgimips_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 */
702void
703cpu_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
736int	waittime = -1;
737
738void
739cpu_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
767haltsys:
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
814void 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 */
829static int
830badaddr_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 */
846static void
847unimpl_bus_reset(void)
848{
849
850	panic("target init didn't set bus_reset");
851}
852
853static void
854unimpl_cons_init(void)
855{
856
857	panic("target init didn't set cons_init");
858}
859
860static void *
861unimpl_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
867static void
868unimpl_intr(vaddr_t pc, uint32_t status, uint32_t pending)
869{
870	printf("spurious interrupt pending %#x\n", pending);
871}
872
873static unsigned long
874nulllong(void)
875{
876	printf("nulllong\n");
877	return (0);
878}
879
880static void
881nullvoid(void)
882{
883	printf("nullvoid\n");
884	return;
885}
886
887void *
888lookup_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
912void 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
927void 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
953void
954mips_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