xref: /netbsd/sys/arch/sgimips/sgimips/machdep.c (revision c4a72b64)
1 /*	$NetBSD: machdep.c,v 1.42 2002/11/09 19:20:18 thorpej Exp $	*/
2 
3 /*
4  * Copyright (c) 2000 Soren S. Jorvang
5  * Copyright (c) 2001, 2002 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 "opt_ddb.h"
37 #include "opt_kgdb.h"
38 #include "opt_execfmt.h"
39 #include "opt_cputype.h"
40 #include "opt_machtypes.h"
41 
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/proc.h>
46 #include <sys/buf.h>
47 #include <sys/reboot.h>
48 #include <sys/conf.h>
49 #include <sys/file.h>
50 #include <sys/malloc.h>
51 #include <sys/mbuf.h>
52 #include <sys/msgbuf.h>
53 #include <sys/device.h>
54 #include <sys/user.h>
55 #include <sys/exec.h>
56 #include <sys/mount.h>
57 #include <sys/syscallargs.h>
58 #include <sys/kcore.h>
59 
60 #include <uvm/uvm_extern.h>
61 
62 #include <machine/cpu.h>
63 #include <machine/reg.h>
64 #include <machine/psl.h>
65 #include <machine/pte.h>
66 #include <machine/autoconf.h>
67 #include <machine/machtype.h>
68 #include <machine/sysconf.h>
69 #include <machine/intr.h>
70 #include <machine/bootinfo.h>
71 #include <mips/locore.h>
72 
73 #include <dev/arcbios/arcbios.h>
74 #include <dev/arcbios/arcbiosvar.h>
75 
76 #if defined(DDB) || defined(KGDB)
77 #include <machine/db_machdep.h>
78 #include <ddb/db_access.h>
79 #include <ddb/db_sym.h>
80 #include <ddb/db_extern.h>
81 #ifndef DB_ELFSIZE
82 #error Must define DB_ELFSIZE!
83 #endif
84 #define ELFSIZE		DB_ELFSIZE
85 #include <sys/exec_elf.h>
86 #endif
87 
88 #include <dev/cons.h>
89 
90 /* For sysctl_hw. */
91 extern char cpu_model[];
92 
93 struct sgimips_intrhand intrtab[NINTR];
94 
95 /* Our exported CPU info; we can have only one. */
96 struct cpu_info cpu_info_store;
97 
98 /* Maps for VM objects. */
99 struct vm_map *exec_map = NULL;
100 struct vm_map *mb_map = NULL;
101 struct vm_map *phys_map = NULL;
102 
103 int mach_type;		/* IPxx type */
104 int mach_subtype;	/* subtype: eg., Guiness/Fullhouse for IP22 */
105 int mach_boardrev;	/* machine board revision, in case it matters */
106 
107 int physmem;		/* Total physical memory */
108 int arcsmem;		/* Memory used by the ARCS firmware */
109 
110 int ncpus;
111 
112 /* CPU interrupt masks */
113 u_int32_t biomask;
114 u_int32_t netmask;
115 u_int32_t ttymask;
116 u_int32_t clockmask;
117 
118 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
119 int mem_cluster_cnt;
120 
121 #ifdef IP20
122 void	ip20_init(void);
123 #endif
124 
125 #ifdef IP22
126 void	ip22_init(void);
127 #endif
128 
129 #ifdef IP32
130 void	ip32_init(void);
131 #endif
132 
133 void * cpu_intr_establish(int, int, int (*)(void *), void *);
134 
135 void	mach_init(int, char **, int, struct btinfo_common *);
136 void	unconfigured_system_type(int);
137 
138 void	sgimips_count_cpus(struct arcbios_component *,
139 	    struct arcbios_treewalk_context *);
140 
141 #ifdef KGDB
142 void zs_kgdb_init(void);
143 void kgdb_connect(int);
144 #endif
145 
146 /* Motherboard or system-specific initialization vector */
147 static void	unimpl_bus_reset(void);
148 static void	unimpl_cons_init(void);
149 static void	unimpl_iointr(unsigned, unsigned, unsigned, unsigned);
150 static void	unimpl_intr_establish(int, int, int (*)(void *), void *);
151 static unsigned	long nullwork(void);
152 
153 void ddb_trap_hook(int where);
154 
155 struct platform platform = {
156 	unimpl_bus_reset,
157 	unimpl_cons_init,
158 	unimpl_iointr,
159 	unimpl_intr_establish,
160 	(void *)nullwork,
161 };
162 
163 /*
164  * safepri is a safe priority for sleep to set for a spin-wait during
165  * autoconfiguration or after a panic.  Used as an argument to splx().
166  */
167 int	safepri = MIPS1_PSL_LOWIPL;
168 
169 extern caddr_t esym;
170 extern u_int32_t ssir;
171 extern struct user *proc0paddr;
172 
173 static struct btinfo_common *bootinfo;
174 
175 /*
176  * Do all the stuff that locore normally does before calling main().
177  * Process arguments passed to us by the ARCS firmware.
178  */
179 void
180 mach_init(argc, argv, magic, btinfo)
181 	int argc;
182 	char **argv;
183 	int magic;
184 	struct btinfo_common *btinfo;
185 {
186 	extern char kernel_text[], _end[];
187 	paddr_t first, last;
188 	int firstpfn, lastpfn;
189 	caddr_t v;
190 	vsize_t size;
191 	struct arcbios_mem *mem;
192 	char *cpufreq;
193 	struct btinfo_symtab *bi_syms;
194 	caddr_t ssym;
195 	vaddr_t kernend;
196 	int kernstartpfn, kernendpfn;
197 	int i, nsym;
198 
199 #if 0
200 	/* Clear the BSS segment.  XXX Is this really necessary? */
201 	memset(_edata, 0, _end - _edata);
202 #endif
203 
204 	/*
205 	 * Initialize ARCS.  This will set up the bootstrap console.
206 	 */
207 	arcbios_init(MIPS_PHYS_TO_KSEG0(0x00001000));
208 	strcpy(cpu_model, arcbios_system_identifier);
209 
210 	uvm_setpagesize();
211 
212 	if (magic == BOOTINFO_MAGIC && btinfo != NULL) {
213 #ifdef DEBUG
214 		printf("Found bootinfo at %p\n", btinfo);
215 #endif
216 		bootinfo = btinfo;
217 	}
218 
219 	bi_syms = lookup_bootinfo(BTINFO_SYMTAB);
220 	if (bi_syms != NULL) {
221 		nsym = bi_syms->nsym;
222 		ssym = (caddr_t) bi_syms->ssym;
223 		esym = (caddr_t) bi_syms->esym;
224 		kernend = round_page((vaddr_t) esym);
225 	} else {
226 		nsym = 0;
227 		ssym = esym = NULL;
228 		kernend = round_page((vaddr_t) _end);
229 	}
230 
231 	kernstartpfn = atop(MIPS_KSEG0_TO_PHYS((vaddr_t) kernel_text));
232 	kernendpfn = atop(MIPS_KSEG0_TO_PHYS(kernend));
233 
234 	/*
235 	 * Now set up the real console.
236 	 * XXX Should be done later after we determine systype.
237 	 */
238 	consinit();
239 
240 #if 1 /* skidt? */
241 	ARCBIOS->FlushAllCaches();
242 #endif
243 
244 	cpufreq = ARCBIOS->GetEnvironmentVariable("cpufreq");
245 
246 	if (cpufreq == 0)
247 		panic("no $cpufreq");
248 
249 	/*
250 	 * Note initial estimate of CPU speed... If we care enough, we'll
251 	 * use the RTC to get a better estimate later.
252 	 */
253 	curcpu()->ci_cpu_freq = strtoul(cpufreq, NULL, 10) * 1000000;
254 
255 	/*
256 	 * argv[0] can be either the bootloader loaded by the PROM, or a
257 	 * kernel loaded directly by the PROM.
258 	 *
259 	 * If argv[0] is the bootloader, then argv[1] might be the kernel
260 	 * that was loaded.  How to tell which one to use?
261 	 *
262 	 * If argv[1] isn't an environment string, try to use it to set the
263 	 * boot device.
264 	 */
265 	if (strchr(argv[1], '=') != 0)
266 		makebootdev(argv[1]);
267 
268 	boothowto = RB_SINGLE;
269 
270 	/*
271 	 * Single- or multi-user ('auto' in SGI terms).
272 	 */
273 	for (i = 0; i < argc; i++) {
274 		if (strcmp(argv[i], "OSLoadOptions=auto") == 0)
275 			boothowto &= ~RB_SINGLE;
276 
277 		/*
278 		 * The case where the kernel has been loaded by a
279 		 * boot loader will usually have been catched by
280 		 * the first makebootdev() case earlier on, but
281 		 * we still use OSLoadPartition to get the preferred
282 		 * root filesystem location, even if it's not
283 		 * actually the location of the loaded kernel.
284 		 */
285 		if (strncmp(argv[i], "OSLoadPartition=", 15) == 0)
286 			makebootdev(argv[i] + 16);
287 	}
288 
289 	/*
290 	 * When the kernel is loaded directly by the firmware, and
291 	 * no explicit OSLoadPartition is set, we fall back on
292 	 * SystemPartition for the boot device.
293 	 */
294 	for (i = 0; i < argc; i++) {
295 		if (strncmp(argv[i], "SystemPartition", 15) == 0)
296 			makebootdev(argv[i] + 16);
297 
298 #ifdef DEBUG
299 		printf("argv[%d]: %s\n", i, argv[i]);
300 #endif
301 	}
302 
303 #if defined(KGDB) || defined(DDB)
304 	/* Set up DDB hook to turn off watchdog on entry */
305 	db_trap_callback = ddb_trap_hook;
306 
307 #ifdef DDB
308 	ddb_init(nsym, ssym, esym);
309 	if (boothowto & RB_KDB)
310 		Debugger();
311 #endif
312 #ifdef KGDB
313 	zs_kgdb_init();			/* XXX */
314 	if (boothowto & RB_KDB)
315 		kgdb_connect(0);
316 #endif
317 #endif
318 
319 	for (i = 0; arcbios_system_identifier[i] != '\0'; i++) {
320 		if (arcbios_system_identifier[i] >= '0' &&
321 		    arcbios_system_identifier[i] <= '9') {
322 			mach_type = strtoul(&arcbios_system_identifier[i],
323 			    NULL, 10);
324 			break;
325 		}
326 	}
327 
328 	if (mach_type <= 0)
329 		panic("invalid architecture");
330 
331 	switch (mach_type) {
332 	case MACH_SGI_IP20:
333 #ifdef IP20
334 		ip20_init();
335 #else
336 		unconfigured_system_type(mach_type);
337 #endif
338 		break;
339 
340 	case MACH_SGI_IP22:
341 #ifdef IP22
342 		ip22_init();
343 #else
344 		unconfigured_system_type(mach_type);
345 #endif
346 		break;
347 
348 	case MACH_SGI_IP32:
349 #ifdef IP32
350 		ip32_init();
351 #else
352 		unconfigured_system_type(mach_type);
353 #endif
354 		break;
355 
356 	default:
357 		panic("IP%d architecture not yet supported", mach_type);
358 		break;
359 	}
360 
361 	physmem = arcsmem = 0;
362 	mem_cluster_cnt = 0;
363 	mem = NULL;
364 
365 #ifdef DEBUG
366 	i = 0;
367 	mem = NULL;
368 
369 	do {
370 		if ((mem = ARCBIOS->GetMemoryDescriptor(mem)) != NULL) {
371 			i++;
372 			printf("Mem block %d: type %d, base 0x%x, size 0x%x\n",
373 				i, mem->Type, mem->BasePage, mem->PageCount);
374 		}
375 	} while (mem != NULL);
376 #endif
377 
378 	/*
379 	 * XXX This code assumes that ARCS provides the memory
380 	 * XXX sorted in ascending order.
381 	 */
382 	mem = NULL;
383 	for (i = 0; mem_cluster_cnt < VM_PHYSSEG_MAX; i++) {
384 		mem = ARCBIOS->GetMemoryDescriptor(mem);
385 
386 		if (mem == NULL)
387 			break;
388 
389 		first = round_page(mem->BasePage * ARCBIOS_PAGESIZE);
390 		last = trunc_page(first + mem->PageCount * ARCBIOS_PAGESIZE);
391 		size = last - first;
392 
393 		firstpfn = atop(first);
394 		lastpfn = atop(last);
395 
396 		switch (mem->Type) {
397 		case ARCBIOS_MEM_FreeContiguous:
398 		case ARCBIOS_MEM_FreeMemory:
399 		case ARCBIOS_MEM_LoadedProgram:
400 			if (firstpfn <= kernstartpfn &&
401 			    kernendpfn <= lastpfn) {
402 				/*
403 				 * Must compute the location of the kernel
404 				 * within the segment.
405 				 */
406 #ifdef DEBUG
407 				printf("Cluster %d contains kernel\n", i);
408 #endif
409 				if (firstpfn < kernstartpfn) {
410 					/*
411 					 * There is a chunk before the kernel.
412 					 */
413 #ifdef DEBUG
414 					printf("Loading chunk before kernel: "
415 					    "0x%x / 0x%x\n", firstpfn,
416 					    kernstartpfn);
417 #endif
418 					uvm_page_physload(firstpfn,
419 					    kernstartpfn,
420 					    firstpfn, kernstartpfn,
421 					    VM_FREELIST_DEFAULT);
422 				}
423 				if (kernendpfn < lastpfn) {
424 					/*
425 					 * There is a chunk after the kernel.
426 					 */
427 #ifdef DEBUG
428 					printf("Loading chunk after kernel: "
429 					    "0x%x / 0x%x\n", kernendpfn,
430 					    lastpfn);
431 #endif
432 					uvm_page_physload(kernendpfn,
433 					    lastpfn, kernendpfn,
434 					    lastpfn, VM_FREELIST_DEFAULT);
435 				}
436 			} else {
437 				/*
438 				 * Just load this cluster as one chunk.
439 				 */
440 #ifdef DEBUG
441 				printf("Loading cluster %d: 0x%x / 0x%x\n", i,
442 				    firstpfn, lastpfn);
443 #endif
444 				uvm_page_physload(firstpfn, lastpfn,
445 				    firstpfn, lastpfn, VM_FREELIST_DEFAULT);
446 			}
447 			mem_clusters[mem_cluster_cnt].start = first;
448 			mem_clusters[mem_cluster_cnt].size = size;
449 			mem_cluster_cnt++;
450 			break;
451 
452 		case ARCBIOS_MEM_FirmwareTemporary:
453 		case ARCBIOS_MEM_FirmwarePermanent:
454 			arcsmem += btoc(size);
455 			break;
456 
457 		case ARCBIOS_MEM_ExecptionBlock:
458 		case ARCBIOS_MEM_SystemParameterBlock:
459 		case ARCBIOS_MEM_BadMemory:
460 			break;
461 
462 		default:
463 			panic("unknown memory descriptor %d type %d",
464 				i, mem->Type);
465 		}
466 
467 		physmem += btoc(size);
468 
469 	}
470 
471 	if (mem_cluster_cnt == 0)
472 		panic("no free memory descriptors found");
473 
474 	/* We can now no longer use bootinfo. */
475 	bootinfo = NULL;
476 
477 	/*
478 	 * Walk the component tree and count the number of CPUs
479 	 * present in the system.
480 	 */
481 	arcbios_tree_walk(sgimips_count_cpus, NULL);
482 
483 	/*
484 	 * Copy exception-dispatch code down to exception vector.
485 	 * Initialize locore-function vector.
486 	 * Clear out the I and D caches.
487 	 */
488 	mips_vector_init();
489 
490 	/*
491 	 * Initialize error message buffer (at end of core).
492 	 */
493 	mips_init_msgbuf();
494 
495 	/*
496 	 * Compute the size of system data structures.  pmap_bootstrap()
497 	 * needs some of this information.
498 	 */
499 	size = (vsize_t)allocsys(NULL, NULL);
500 
501 	pmap_bootstrap();
502 
503 	/*
504 	 * Allocate space for proc0's USPACE.
505 	 */
506 	v = (caddr_t)uvm_pageboot_alloc(USPACE);
507 	proc0.p_addr = proc0paddr = (struct user *)v;
508 	proc0.p_md.md_regs = (struct frame *)(v + USPACE) - 1;
509 	curpcb = &proc0.p_addr->u_pcb;
510 	curpcb->pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */
511 
512 	/*
513 	 * Allocate space for system data structures.  These data structures
514 	 * are allocated here instead of cpu_startup() because physical
515 	 * memory is directly addressable.  We don't have to map these into
516 	 * virtual address space.
517 	 */
518 	v = (caddr_t)uvm_pageboot_alloc(size);
519 	if ((vsize_t) (allocsys(v, NULL) - v) != size)
520 		panic("mach_init: table size inconsistency");
521 }
522 
523 void
524 sgimips_count_cpus(struct arcbios_component *node,
525     struct arcbios_treewalk_context *atc)
526 {
527 
528 	switch (node->Class) {
529 	case COMPONENT_CLASS_ProcessorClass:
530 		if (node->Type == COMPONENT_TYPE_CPU)
531 			ncpus++;
532 		break;
533 
534 	default:
535 		break;
536 	}
537 }
538 
539 /*
540  * Allocate memory for variable-sized tables.
541  */
542 void
543 cpu_startup()
544 {
545 	u_int i, base, residual;
546 	vaddr_t minaddr, maxaddr;
547 	vsize_t size;
548 	char pbuf[9];
549 
550 	printf(version);
551 
552 	format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
553 	printf("%s memory", pbuf);
554 
555 	/*
556 	 * Allocate virtual address space for file I/O buffers.
557 	 * Note they are different than the array of headers, 'buf',
558 	 * and usually occupy more virtual memory than physical.
559 	 */
560 	size = MAXBSIZE * nbuf;
561 	if (uvm_map(kernel_map, (vaddr_t *)&buffers, round_page(size),
562 		    NULL, UVM_UNKNOWN_OFFSET, 0,
563 		    UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
564 		    UVM_ADV_NORMAL, 0)) != 0)
565 		panic("startup: cannot allocate VM for buffers");
566 	minaddr = (vaddr_t)buffers;
567 	base = bufpages / nbuf;
568 	residual = bufpages % nbuf;
569 	for (i = 0; i < nbuf; i++) {
570 		vsize_t curbufsize;
571 		vaddr_t curbuf;
572 		struct vm_page *pg;
573 
574 		/*
575 		 * Each buffer has MAXBSIZE bytes of VM space allocated.  Of
576 		 * that MAXBSIZE space, we allocate and map (base+1) pages
577 		 * for the first "residual" buffers, and then we allocate
578 		 * "base" pages for the rest.
579 		 */
580 		curbuf = (vaddr_t) buffers + (i * MAXBSIZE);
581 		curbufsize = NBPG * ((i < residual) ? (base + 1) : base);
582 
583 		while (curbufsize) {
584 			pg = uvm_pagealloc(NULL, 0, NULL, 0);
585 			if (pg == NULL)
586 				panic("cpu_startup: not enough memory for "
587 					"buffer cache");
588 			pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg),
589 				       VM_PROT_READ|VM_PROT_WRITE);
590 			curbuf += PAGE_SIZE;
591 			curbufsize -= PAGE_SIZE;
592 		}
593 	}
594 	pmap_update(pmap_kernel());
595 
596 	/*
597 	 * Allocate a submap for exec arguments.  This map effectively
598 	 * limits the number of processes exec'ing at any time.
599 	 */
600 	exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
601 				    16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
602 	/*
603 	 * Allocate a submap for physio.
604 	 */
605 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
606 				    VM_PHYS_SIZE, 0, FALSE, NULL);
607 
608 	/*
609 	 * (No need to allocate an mbuf cluster submap.  Mbuf clusters
610 	 * are allocated via the pool allocator, and we use KSEG to
611 	 * map those pages.)
612 	 */
613 
614 	format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
615 	printf(", %s free", pbuf);
616 	format_bytes(pbuf, sizeof(pbuf), ctob(arcsmem));
617 	printf(", %s for ARCS", pbuf);
618 	format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG);
619 	printf(", %s in %u buffers\n", pbuf, nbuf);
620 
621 	/*
622 	 * Set up buffers, so they can be used to read disk labels.
623 	 */
624 	bufinit();
625 }
626 
627 int	waittime = -1;
628 
629 void
630 cpu_reboot(howto, bootstr)
631 	int howto;
632 	char *bootstr;
633 {
634 	/* Take a snapshot before clobbering any registers. */
635 	if (curproc)
636 		savectx((struct user *)curpcb);
637 
638 #if 1
639 	/* Clear and disable watchdog timer. */
640 	switch (mach_type) {
641 	case MACH_SGI_IP22:
642 		*(volatile u_int32_t *)0xbfa00014 = 0;
643 		*(volatile u_int32_t *)0xbfa00004 &= ~0x100;
644 		break;
645 
646 	case MACH_SGI_IP32:
647 		*(volatile u_int32_t *)0xb4000034 = 0;
648 		*(volatile u_int32_t *)0xb400000c &= ~0x200;
649 		break;
650 	}
651 #endif
652 
653 	if (cold) {
654 		howto |= RB_HALT;
655 		goto haltsys;
656 	}
657 
658 	/* If "always halt" was specified as a boot flag, obey. */
659 	if (boothowto & RB_HALT)
660 		howto |= RB_HALT;
661 
662 	boothowto = howto;
663 	if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) {
664 		waittime = 0;
665 		vfs_shutdown();
666 
667 		/*
668 		 * If we've been adjusting the clock, the todr
669 		 * will be out of synch; adjust it now.
670 		 */
671 		resettodr();
672 	}
673 
674 	splhigh();
675 
676 	if (howto & RB_DUMP)
677 		dumpsys();
678 
679 haltsys:
680 
681 	doshutdownhooks();
682 
683 	/*
684 	 * Calling ARCBIOS->PowerDown() results in a "CP1 unusable trap"
685 	 * which lands me back in DDB, at least on my Indy.  So, enable
686 	 * the FPU before asking the PROM to power down to avoid this..
687 	 * It seems to want the FPU to play the `poweroff tune' 8-/
688 	 */
689 	if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
690 		/* Set CP1 usable bit in SR */
691 	 	mips_cp0_status_write(mips_cp0_status_read() |
692 					MIPS_SR_COP_1_BIT);
693 
694 		printf("powering off...\n\n");
695 		delay(500000);
696 		ARCBIOS->PowerDown();
697 		printf("WARNING: powerdown failed\n");
698 		/*
699 		 * RB_POWERDOWN implies RB_HALT... fall into it...
700 		 */
701 	}
702 
703 	if (howto & RB_HALT) {
704 		printf("halting...\n\n");
705 		ARCBIOS->EnterInteractiveMode();
706 	}
707 
708 	printf("rebooting...\n\n");
709 	ARCBIOS->Reboot();
710 
711 	for (;;);
712 }
713 
714 void
715 microtime(tvp)
716 	struct timeval *tvp;
717 {
718 	int s = splclock();
719 	static struct timeval lasttime;
720 
721 	*tvp = time;
722 	tvp->tv_usec += (*platform.clkread)();
723 
724 	/*
725 	 * Make sure that the time returned is always greater
726 	 * than that returned by the previous call.
727 	 */
728 	if (tvp->tv_sec == lasttime.tv_sec &&
729 	    tvp->tv_usec <= lasttime.tv_usec &&
730 	    (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
731 		tvp->tv_sec++;
732 		tvp->tv_usec -= 1000000;
733 	}
734 	lasttime = *tvp;
735 	splx(s);
736 }
737 
738 __inline void
739 delay(n)
740 	unsigned long n;
741 {
742 	u_long i;
743 	long divisor = curcpu()->ci_divisor_delay;
744 
745 	while (n-- > 0)
746 		for (i = divisor; i > 0; i--)
747 			;
748 }
749 
750 /*
751  *  Ensure all platform vectors are always initialized.
752  */
753 static void
754 unimpl_bus_reset()
755 {
756 
757 	panic("target init didn't set bus_reset");
758 }
759 
760 static void
761 unimpl_cons_init()
762 {
763 
764 	panic("target init didn't set cons_init");
765 }
766 
767 static void
768 unimpl_iointr(mask, pc, statusreg, causereg)
769 	u_int mask;
770 	u_int pc;
771 	u_int statusreg;
772 	u_int causereg;
773 {
774 
775 	panic("target init didn't set intr");
776 }
777 
778 static void
779 unimpl_intr_establish(level, ipl, handler, arg)
780 	int level;
781 	int ipl;
782 	int (*handler) __P((void *));
783 	void *arg;
784 {
785 	panic("target init didn't set intr_establish");
786 }
787 
788 static unsigned long
789 nullwork()
790 {
791 
792 	return (0);
793 }
794 
795 void *
796 cpu_intr_establish(level, ipl, func, arg)
797 	int level;
798 	int ipl;
799 	int (*func)(void *);
800 	void *arg;
801 {
802 	(*platform.intr_establish)(level, ipl, func, arg);
803 	return (void *) -1;
804 }
805 
806 void
807 cpu_intr(status, cause, pc, ipending)
808 	u_int32_t status;
809 	u_int32_t cause;
810 	u_int32_t pc;
811 	u_int32_t ipending;
812 {
813 	uvmexp.intrs++;
814 
815 	if (ipending & MIPS_HARD_INT_MASK)
816 		(*platform.iointr)(status, cause, pc, ipending);
817 
818 	/*
819 	 * Service pending soft interrupts -- make sure to re-enable
820 	 * only those hardware interrupts that are not masked and
821 	 * that weren't pending on the current invocation of the
822 	 * interrupt handler, else we risk infinite stack growth
823 	 * due to nested interrupts.
824 	 */
825 	/* software simulated interrupt */
826 	if ((ipending & MIPS_SOFT_INT_MASK_1) ||
827 	    (ssir && (status & MIPS_SOFT_INT_MASK_1))) {
828 		_splset(MIPS_SR_INT_IE |
829 			    (status & ~ipending & MIPS_HARD_INT_MASK));
830 		_clrsoftintr(MIPS_SOFT_INT_MASK_1);
831 		softintr_dispatch();
832 	}
833 }
834 
835 void unconfigured_system_type(int ipnum)
836 {
837 	printf("Kernel not configured for IP%d support.  Add options `IP%d'\n",
838 								ipnum, ipnum);
839 	printf("to kernel configuration file to enable IP%d support!\n",
840 								ipnum);
841 	printf("\n");
842 
843 	panic("Kernel not configured for current hardware!");
844 }
845 
846 void *
847 lookup_bootinfo(int type)
848 {
849 	struct btinfo_common *b = bootinfo;
850 
851 	while (bootinfo != NULL) {
852 		if (b->type == type)
853 			return (b);
854 		b = b->next;
855 	}
856 
857 	return (NULL);
858 }
859 
860 #if defined(DDB) || defined(KGDB)
861 
862 void ddb_trap_hook(int where)
863 {
864 	switch (where) {
865 	case 1:		/* Entry to DDB, turn watchdog off */
866 		switch (mach_type) {
867 		case MACH_SGI_IP32:
868 			*(volatile u_int32_t *)0xb4000034 = 0;
869 			*(volatile u_int32_t *)0xb400000c &= ~0x200;
870 			break;
871 
872 		case MACH_SGI_IP22:
873 			*(volatile u_int32_t *)0xbfa00014 = 0;
874 			*(volatile u_int32_t *)0xbfa00004 &= ~0x100;
875 			break;
876 		}
877 		break;
878 
879 	case 0:		/* Exit from DDB, turn watchdog back on */
880 		switch (mach_type) {
881 		case MACH_SGI_IP32:
882 			*(volatile u_int32_t *)0xb400000c |= 0x200;
883 			*(volatile u_int32_t *)0xb4000034 = 0;
884 			break;
885 
886 		case MACH_SGI_IP22:
887 			*(volatile u_int32_t *)0xbfa00004 |= 0x100;
888 			*(volatile u_int32_t *)0xbfa00014 = 0;
889 
890 			break;
891 		}
892 		break;
893 	}
894 }
895 
896 #endif
897