xref: /freebsd/sys/powerpc/powerpc/machdep.c (revision 09e8dea79366f1e5b3a73e8a271b26e4b6bf2e6a)
1 /*
2  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
3  * Copyright (C) 1995, 1996 TooLs GmbH.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by TooLs GmbH.
17  * 4. The name of TooLs GmbH may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 /*
32  * Copyright (C) 2001 Benno Rice
33  * All rights reserved.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  * 1. Redistributions of source code must retain the above copyright
39  *    notice, this list of conditions and the following disclaimer.
40  * 2. Redistributions in binary form must reproduce the above copyright
41  *    notice, this list of conditions and the following disclaimer in the
42  *    documentation and/or other materials provided with the distribution.
43  *
44  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
45  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
46  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
49  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
50  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
52  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
53  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54  *	$NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $
55  */
56 
57 #ifndef lint
58 static const char rcsid[] =
59   "$FreeBSD$";
60 #endif /* not lint */
61 
62 #include "opt_ddb.h"
63 #include "opt_compat.h"
64 #include "opt_msgbuf.h"
65 
66 #include <sys/param.h>
67 #include <sys/systm.h>
68 #include <sys/eventhandler.h>
69 #include <sys/sysproto.h>
70 #include <sys/lock.h>
71 #include <sys/mutex.h>
72 #include <sys/ktr.h>
73 #include <sys/signalvar.h>
74 #include <sys/kernel.h>
75 #include <sys/proc.h>
76 #include <sys/malloc.h>
77 #include <sys/reboot.h>
78 #include <sys/bio.h>
79 #include <sys/buf.h>
80 #include <sys/bus.h>
81 #include <sys/mbuf.h>
82 #include <sys/vmmeter.h>
83 #include <sys/msgbuf.h>
84 #include <sys/exec.h>
85 #include <sys/sysctl.h>
86 #include <sys/uio.h>
87 #include <sys/linker.h>
88 #include <sys/cons.h>
89 #include <sys/ucontext.h>
90 #include <net/netisr.h>
91 #include <vm/vm.h>
92 #include <vm/vm_kern.h>
93 #include <vm/vm_page.h>
94 #include <vm/vm_map.h>
95 #include <vm/vm_extern.h>
96 #include <vm/vm_object.h>
97 #include <vm/vm_pager.h>
98 #include <sys/user.h>
99 #include <sys/ptrace.h>
100 #include <machine/bat.h>
101 #include <machine/clock.h>
102 #include <machine/md_var.h>
103 #include <machine/reg.h>
104 #include <machine/fpu.h>
105 #include <machine/vmparam.h>
106 #include <machine/elf.h>
107 #include <machine/trap.h>
108 #include <machine/powerpc.h>
109 #include <dev/ofw/openfirm.h>
110 #include <ddb/ddb.h>
111 #include <sys/vnode.h>
112 #include <machine/sigframe.h>
113 
114 int physmem = 0;
115 int cold = 1;
116 
117 char		pcpu0[PAGE_SIZE];
118 char		uarea0[UAREA_PAGES * PAGE_SIZE];
119 struct		trapframe frame0;
120 
121 vm_offset_t	kstack0;
122 vm_offset_t	kstack0_phys;
123 
124 char		machine[] = "powerpc";
125 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
126 
127 static char	model[128];
128 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, "");
129 
130 char		bootpath[256];
131 
132 #ifdef DDB
133 /* start and end of kernel symbol table */
134 void		*ksym_start, *ksym_end;
135 #endif /* DDB */
136 
137 static void	cpu_startup(void *);
138 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
139 
140 void		powerpc_init(u_int, u_int, u_int, char *);
141 
142 int		save_ofw_mapping(void);
143 int		restore_ofw_mapping(void);
144 
145 void		install_extint(void (*)(void));
146 
147 #ifdef COMPAT_43
148 void		osendsig(sig_t, int, sigset_t *, u_long);
149 #endif
150 
151 static int
152 sysctl_hw_physmem(SYSCTL_HANDLER_ARGS)
153 {
154 	int error = sysctl_handle_int(oidp, 0, ctob(physmem), req);
155 	return (error);
156 }
157 
158 SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_INT|CTLFLAG_RD,
159 	0, 0, sysctl_hw_physmem, "IU", "");
160 
161 int		Maxmem = 0;
162 
163 static int	chosen;
164 
165 struct pmap	ofw_pmap;
166 extern int	ofmsr;
167 
168 struct bat	battable[16];
169 
170 static void	identifycpu(void);
171 
172 struct kva_md_info kmi;
173 
174 static void
175 powerpc_ofw_shutdown(void *junk, int howto)
176 {
177 	if (howto & RB_HALT) {
178 		OF_exit();
179 	}
180 }
181 
182 static void
183 cpu_startup(void *dummy)
184 {
185 
186 	/*
187 	 * Good {morning,afternoon,evening,night}.
188 	 */
189 	identifycpu();
190 
191 	/* startrtclock(); */
192 #ifdef PERFMON
193 	perfmon_init();
194 #endif
195 	printf("real memory  = %ld (%ldK bytes)\n", ptoa(Maxmem),
196 	    ptoa(Maxmem) / 1024);
197 
198 	/*
199 	 * Display any holes after the first chunk of extended memory.
200 	 */
201 	if (bootverbose) {
202 		int indx;
203 
204 		printf("Physical memory chunk(s):\n");
205 		for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
206 			int size1 = phys_avail[indx + 1] - phys_avail[indx];
207 
208 			printf("0x%08x - 0x%08x, %d bytes (%d pages)\n",
209 			    phys_avail[indx], phys_avail[indx + 1] - 1, size1,
210 			    size1 / PAGE_SIZE);
211 		}
212 	}
213 
214 	vm_ksubmap_init(&kmi);
215 
216 	printf("avail memory = %ld (%ldK bytes)\n", ptoa(cnt.v_free_count),
217 	    ptoa(cnt.v_free_count) / 1024);
218 
219 	/*
220 	 * Set up buffers, so they can be used to read disk labels.
221 	 */
222 	bufinit();
223 	vm_pager_bufferinit();
224 	EVENTHANDLER_REGISTER(shutdown_final, powerpc_ofw_shutdown, 0,
225 	    SHUTDOWN_PRI_LAST);
226 
227 #ifdef SMP
228 	/*
229 	 * OK, enough kmem_alloc/malloc state should be up, lets get on with it!
230 	 */
231 	mp_start();			/* fire up the secondaries */
232 	mp_announce();
233 #endif  /* SMP */
234 }
235 
236 void
237 identifycpu()
238 {
239 	unsigned int pvr, version, revision;
240 
241 	/*
242 	 * Find cpu type (Do it by OpenFirmware?)
243 	 */
244 	__asm ("mfpvr %0" : "=r"(pvr));
245 	version = pvr >> 16;
246 	revision = pvr & 0xffff;
247 	switch (version) {
248 	case 0x0000:
249 		sprintf(model, "Simulator (psim)");
250 		break;
251 	case 0x0001:
252 		sprintf(model, "601");
253 		break;
254 	case 0x0003:
255 		sprintf(model, "603 (Wart)");
256 		break;
257 	case 0x0004:
258 		sprintf(model, "604 (Zephyr)");
259 		break;
260 	case 0x0005:
261 		sprintf(model, "602 (Galahad)");
262 		break;
263 	case 0x0006:
264 		sprintf(model, "603e (Stretch)");
265 		break;
266 	case 0x0007:
267 		if ((revision && 0xf000) == 0x0000)
268 			sprintf(model, "603ev (Valiant)");
269 		else
270 			sprintf(model, "603r (Goldeneye)");
271 		break;
272 	case 0x0008:
273 		if ((revision && 0xf000) == 0x0000)
274 			sprintf(model, "G3 / 750 (Arthur)");
275 		else
276 			sprintf(model, "G3 / 755 (Goldfinger)");
277 		break;
278 	case 0x0009:
279 		if ((revision && 0xf000) == 0x0000)
280 			sprintf(model, "604e (Sirocco)");
281 		else
282 			sprintf(model, "604r (Mach V)");
283 		break;
284 	case 0x000a:
285 		sprintf(model, "604r (Mach V)");
286 		break;
287 	case 0x000c:
288 		sprintf(model, "G4 / 7400 (Max)");
289 		break;
290 	case 0x0014:
291 		sprintf(model, "620 (Red October)");
292 		break;
293 	case 0x0081:
294 		sprintf(model, "8240 (Kahlua)");
295 		break;
296 	case 0x8000:
297 		sprintf(model, "G4 / 7450 (V'ger)");
298 		break;
299 	case 0x800c:
300 		sprintf(model, "G4 / 7410 (Nitro)");
301 		break;
302 	case 0x8081:
303 		sprintf(model, "8245 (Kahlua II)");
304 		break;
305 	default:
306 		sprintf(model, "Version %x", version);
307 		break;
308 	}
309 	sprintf(model + strlen(model), " (Revision %x)", revision);
310 	printf("CPU: PowerPC %s\n", model);
311 }
312 
313 extern char	kernel_text[], _end[];
314 
315 extern void	*trapcode, *trapsize;
316 extern void	*alitrap, *alisize;
317 extern void	*dsitrap, *dsisize;
318 extern void	*isitrap, *isisize;
319 extern void	*decrint, *decrsize;
320 extern void	*tlbimiss, *tlbimsize;
321 extern void	*tlbdlmiss, *tlbdlmsize;
322 extern void	*tlbdsmiss, *tlbdsmsize;
323 
324 #if 0 /* XXX: interrupt handler.  We'll get to this later */
325 extern void	ext_intr(void);
326 #endif
327 
328 #ifdef DDB
329 extern		ddblow, ddbsize;
330 #endif
331 #ifdef IPKDB
332 extern		ipkdblow, ipkdbsize;
333 #endif
334 
335 void
336 powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args)
337 {
338 	struct		pcpu *pc;
339 	vm_offset_t	off;
340 
341 	/*
342 	 * Initialize the console before printing anything.
343 	 */
344 	cninit();
345 
346 	/*
347 	 * XXX: Initialize the interrupt tables.
348 	 */
349 	bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize);
350 	bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
351 	bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize);
352 	bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize);
353 	bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize);
354 
355 	/*
356 	 * Start initializing proc0 and thread0.
357 	 */
358 	proc_linkup(&proc0, &proc0.p_ksegrp, &proc0.p_kse, &thread0);
359 	proc0.p_uarea = (struct user *)uarea0;
360 	proc0.p_stats = &proc0.p_uarea->u_stats;
361 	thread0.td_frame = &frame0;
362 
363 	/*
364 	 * Set up per-cpu data.
365 	 */
366 	pc = (struct pcpu *)(pcpu0 + PAGE_SIZE) - 1;
367 	pcpu_init(pc, 0, sizeof(struct pcpu));
368 	pc->pc_curthread = &thread0;
369 	pc->pc_curpcb = thread0.td_pcb;
370 	pc->pc_cpuid = 0;
371 	/* pc->pc_mid = mid; */
372 
373 	__asm __volatile("mtsprg 0, %0" :: "r"(pc));
374 
375 	mutex_init();
376 
377 	/*
378 	 * Initialise virtual memory.
379 	 */
380 	ofmsr |= PSL_IR | PSL_DR;
381 	pmap_bootstrap(startkernel, endkernel);
382 
383 	/*
384 	 * Initialize tunables.
385 	 */
386 	init_param1();
387 	init_param2(physmem);
388 
389 	/*
390 	 * Finish setting up thread0.
391 	 */
392 	thread0.td_kstack = kstack0;
393 	thread0.td_pcb = (struct pcb *)
394 	    (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
395 
396 	/*
397 	 * Map and initialise the message buffer.
398 	 */
399 	for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
400 		pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off);
401 	msgbufinit(msgbufp, MSGBUF_SIZE);
402 }
403 
404 #if 0 /* XXX: Old powerpc_init */
405 void
406 powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args)
407 {
408 	unsigned int		exc, scratch;
409 	struct mem_region	*allmem, *availmem, *mp;
410 	struct pcpu	*pcpup;
411 
412 	/*
413 	 * Set up BAT0 to only map the lowest 256 MB area
414 	 */
415 	battable[0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW);
416 	battable[0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs);
417 
418 	/*
419 	 * Map PCI memory space.
420 	 */
421 	battable[0x8].batl = BATL(0x80000000, BAT_I, BAT_PP_RW);
422 	battable[0x8].batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs);
423 
424 	battable[0x9].batl = BATL(0x90000000, BAT_I, BAT_PP_RW);
425 	battable[0x9].batu = BATU(0x90000000, BAT_BL_256M, BAT_Vs);
426 
427 	battable[0xa].batl = BATL(0xa0000000, BAT_I, BAT_PP_RW);
428 	battable[0xa].batu = BATU(0xa0000000, BAT_BL_256M, BAT_Vs);
429 
430 	/*
431 	 * Map obio devices.
432 	 */
433 	battable[0xf].batl = BATL(0xf0000000, BAT_I, BAT_PP_RW);
434 	battable[0xf].batu = BATU(0xf0000000, BAT_BL_256M, BAT_Vs);
435 
436 	/*
437 	 * Now setup fixed bat registers
438 	 *
439 	 * Note that we still run in real mode, and the BAT
440 	 * registers were cleared above.
441 	 */
442 	/* BAT0 used for initial 256 MB segment */
443 	__asm __volatile ("mtibatl 0,%0; mtibatu 0,%1;"
444 		          "mtdbatl 0,%0; mtdbatu 0,%1;"
445 		          :: "r"(battable[0].batl), "r"(battable[0].batu));
446 	/*
447 	 * Set up battable to map all RAM regions.
448 	 * This is here because mem_regions() call needs bat0 set up.
449 	 */
450 	mem_regions(&allmem, &availmem);
451 
452 	/* Calculate the physical memory in the machine */
453 	for (mp = allmem; mp->size; mp++)
454 		physmem += btoc(mp->size);
455 
456 	for (mp = allmem; mp->size; mp++) {
457 		vm_offset_t	pa = mp->start & 0xf0000000;
458 		vm_offset_t	end = mp->start + mp->size;
459 
460 		do {
461 			u_int n = pa >> 28;
462 
463 			battable[n].batl = BATL(pa, BAT_M, BAT_PP_RW);
464 			battable[n].batu = BATU(pa, BAT_BL_256M, BAT_Vs);
465 			pa += 0x10000000;
466 		} while (pa < end);
467 	}
468 
469 	chosen = OF_finddevice("/chosen");
470 	save_ofw_mapping();
471 
472 	pmap_setavailmem(startkernel, endkernel);
473 
474 	proc_linkup(&proc0, &proc0.p_ksegrp, &proc0.p_kse, &thread0);
475 
476 	proc0uarea = (struct user *)pmap_steal_memory(UAREA_PAGES * PAGE_SIZE);
477 	proc0kstack = pmap_steal_memory(KSTACK_PAGES * PAGE_SIZE);
478 	proc0.p_uarea = proc0uarea;
479 	thread0.td_kstack = proc0kstack;
480 	thread0.td_pcb = (struct pcb *)
481 	    (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
482 
483 	pcpup = pmap_steal_memory(round_page(sizeof(struct pcpu)));
484 
485 	/*
486 	 * XXX: Pass 0 as CPU id.  This is bad.  We need to work out
487 	 * XXX: which CPU we are somehow.
488 	 */
489 	pcpu_init(pcpup, 0, sizeof(struct pcpu));
490 	__asm ("mtsprg 0, %0" :: "r"(pcpup));
491 
492 	/* Init basic tunables, hz etc */
493 	init_param1();
494 	init_param2(physmem);
495 
496 	PCPU_SET(curthread, &thread0);
497 
498 /* XXX: NetBSDism I _think_.  Not sure yet. */
499 #if 0
500 	curpm = PCPU_GET(curpcb)->pcb_pmreal = PCPU_GET(curpcb)->pcb_pm = kernel_pmap;
501 #endif
502 
503 	mutex_init();
504 
505 	/*
506 	 * Initialise console.
507 	 */
508 	cninit();
509 
510 #ifdef	__notyet__		/* Needs some rethinking regarding real/virtual OFW */
511 	OF_set_callback(callback);
512 #endif
513 
514 	/*
515 	 * Set up trap vectors
516 	 */
517 	for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100) {
518 		switch (exc) {
519 		default:
520 			bcopy(&trapcode, (void *)exc, (size_t)&trapsize);
521 			break;
522 		case EXC_DECR:
523 			bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize);
524 			break;
525 #if 0 /* XXX: Not enabling these traps yet. */
526 		case EXC_EXI:
527 			/*
528 			 * This one is (potentially) installed during autoconf
529 			 */
530 			break;
531 		case EXC_ALI:
532 			bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize);
533 			break;
534 		case EXC_DSI:
535 			bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
536 			break;
537 		case EXC_ISI:
538 			bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize);
539 			break;
540 		case EXC_IMISS:
541 			bcopy(&tlbimiss, (void *)EXC_IMISS, (size_t)&tlbimsize);
542 			break;
543 		case EXC_DLMISS:
544 			bcopy(&tlbdlmiss, (void *)EXC_DLMISS, (size_t)&tlbdlmsize);
545 			break;
546 		case EXC_DSMISS:
547 			bcopy(&tlbdsmiss, (void *)EXC_DSMISS, (size_t)&tlbdsmsize);
548 			break;
549 #if defined(DDB) || defined(IPKDB)
550 		case EXC_TRC:
551 		case EXC_PGM:
552 		case EXC_BPT:
553 #if defined(DDB)
554 			bcopy(&ddblow, (void *)exc, (size_t)&ddbsize);
555 #else
556 			bcopy(&ipkdblow, (void *)exc, (size_t)&ipkdbsize);
557 #endif
558 			break;
559 #endif /* DDB || IPKDB */
560 #endif
561 		}
562 	}
563 
564 #if 0 /* XXX: coming soon... */
565 	/*
566 	 * external interrupt handler install
567 	 */
568 	install_extint(ext_intr);
569 #endif
570 
571 	__syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100);
572 
573 	/*
574 	 * Now enable translation (and machine checks/recoverable interrupts).
575 	 */
576 	__asm ("mfmsr %0" : "=r"(scratch));
577 	scratch |= PSL_IR | PSL_DR | PSL_ME | PSL_RI;
578 	__asm ("mtmsr %0" :: "r"(scratch));
579 
580 	ofmsr &= ~PSL_IP;
581 
582 	/*
583 	 * Parse arg string.
584 	 */
585 #ifdef DDB
586 	bcopy(args + strlen(args) + 1, &startsym, sizeof(startsym));
587 	bcopy(args + strlen(args) + 5, &endsym, sizeof(endsym));
588 	if (startsym == NULL || endsym == NULL)
589 		startsym = endsym = NULL;
590 #endif
591 
592 	strcpy(bootpath, args);
593 	args = bootpath;
594 	while (*++args && *args != ' ');
595 	if (*args) {
596 		*args++ = 0;
597 		while (*args) {
598 			switch (*args++) {
599 			case 'a':
600 				boothowto |= RB_ASKNAME;
601 				break;
602 			case 's':
603 				boothowto |= RB_SINGLE;
604 				break;
605 			case 'd':
606 				boothowto |= RB_KDB;
607 				break;
608 			case 'v':
609 				boothowto |= RB_VERBOSE;
610 				break;
611 			}
612 		}
613 	}
614 
615 #ifdef DDB
616 	ddb_init((int)((u_int)endsym - (u_int)startsym), startsym, endsym);
617 #endif
618 #ifdef IPKDB
619 	/*
620 	 * Now trap to IPKDB
621 	 */
622 	ipkdb_init();
623 	if (boothowto & RB_KDB)
624 		ipkdb_connect(0);
625 #endif
626 
627 	/*
628 	 * Set the page size.
629 	 */
630 #if 0
631 	vm_set_page_size();
632 #endif
633 
634 	/*
635 	 * Initialize pmap module.
636 	 */
637 	pmap_bootstrap();
638 
639 	restore_ofw_mapping();
640 
641 	PCPU_GET(next_asn) = 1;	/* 0 used for proc0 pmap */
642 
643 	/* setup proc 0's pcb */
644 	thread0.td_pcb->pcb_flags = 0; /* XXXKSE */
645 	thread0.td_frame = &proc0_tf;
646 }
647 #endif
648 
649 static int N_mapping;
650 static struct {
651 	vm_offset_t	va;
652 	int		len;
653 	vm_offset_t	pa;
654 	int		mode;
655 } ofw_mapping[256];
656 
657 int
658 save_ofw_mapping()
659 {
660 	int	mmui, mmu;
661 
662 	OF_getprop(chosen, "mmu", &mmui, 4);
663 	mmu = OF_instance_to_package(mmui);
664 
665 	bzero(ofw_mapping, sizeof(ofw_mapping));
666 
667 	N_mapping =
668 	    OF_getprop(mmu, "translations", ofw_mapping, sizeof(ofw_mapping));
669 	N_mapping /= sizeof(ofw_mapping[0]);
670 
671 	return 0;
672 }
673 
674 int
675 restore_ofw_mapping()
676 {
677 	int		i;
678 	struct vm_page	pg;
679 
680 	pmap_pinit(&ofw_pmap);
681 
682 	ofw_pmap.pm_sr[KERNEL_SR] = KERNEL_SEGMENT;
683 
684 	for (i = 0; i < N_mapping; i++) {
685 		vm_offset_t	pa = ofw_mapping[i].pa;
686 		vm_offset_t	va = ofw_mapping[i].va;
687 		int		size = ofw_mapping[i].len;
688 
689 		if (va < 0x80000000)			/* XXX */
690 			continue;
691 
692 		while (size > 0) {
693 			pg.phys_addr = pa;
694 			pmap_enter(&ofw_pmap, va, &pg, VM_PROT_ALL,
695 			    VM_PROT_ALL);
696 			pa += PAGE_SIZE;
697 			va += PAGE_SIZE;
698 			size -= PAGE_SIZE;
699 		}
700 	}
701 
702 	return 0;
703 }
704 
705 void
706 bzero(void *buf, size_t len)
707 {
708 	caddr_t	p;
709 
710 	p = buf;
711 
712 	while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) {
713 		*p++ = 0;
714 		len--;
715 	}
716 
717 	while (len >= sizeof(u_long) * 8) {
718 		*(u_long*) p = 0;
719 		*((u_long*) p + 1) = 0;
720 		*((u_long*) p + 2) = 0;
721 		*((u_long*) p + 3) = 0;
722 		len -= sizeof(u_long) * 8;
723 		*((u_long*) p + 4) = 0;
724 		*((u_long*) p + 5) = 0;
725 		*((u_long*) p + 6) = 0;
726 		*((u_long*) p + 7) = 0;
727 		p += sizeof(u_long) * 8;
728 	}
729 
730 	while (len >= sizeof(u_long)) {
731 		*(u_long*) p = 0;
732 		len -= sizeof(u_long);
733 		p += sizeof(u_long);
734 	}
735 
736 	while (len) {
737 		*p++ = 0;
738 		len--;
739 	}
740 }
741 
742 #if 0
743 void
744 delay(unsigned n)
745 {
746 	u_long tb;
747 
748 	do {
749 		__asm __volatile("mftb %0" : "=r" (tb));
750 	} while (n > (int)(tb & 0xffffffff));
751 }
752 #endif
753 
754 #ifdef COMPAT_43
755 void
756 osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
757 {
758 
759 	/* XXX: To be done */
760 	return;
761 }
762 #endif
763 
764 void
765 sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
766 {
767 
768 	/* XXX: To be done */
769 	return;
770 }
771 
772 /*
773  * Stub to satisfy the reference to osigreturn in the syscall table.  This
774  * is needed even for newer arches that don't support old signals because
775  * the syscall table is machine-independent.
776  */
777 int
778 osigreturn(struct thread *td, struct osigreturn_args *uap)
779 {
780 
781 	return (nosys(td, (struct nosys_args *)uap));
782 }
783 
784 int
785 sigreturn(struct thread *td, struct sigreturn_args *uap)
786 {
787 
788 	/* XXX: To be done */
789 	return(ENOSYS);
790 }
791 
792 void
793 cpu_boot(int howto)
794 {
795 }
796 
797 /*
798  * Shutdown the CPU as much as possible.
799  */
800 void
801 cpu_halt(void)
802 {
803 
804 	OF_exit();
805 }
806 
807 /*
808  * Set set up registers on exec.
809  */
810 void
811 setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
812 {
813 	struct trapframe	*tf;
814 	struct ps_strings	arginfo;
815 
816 	tf = trapframe(td);
817 	bzero(tf, sizeof *tf);
818 	tf->fixreg[1] = -roundup(-stack + 8, 16);
819 
820 	/*
821 	 * XXX Machine-independent code has already copied arguments and
822 	 * XXX environment to userland.  Get them back here.
823 	 */
824 	(void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo));
825 
826 	/*
827 	 * Set up arguments for _start():
828 	 *	_start(argc, argv, envp, obj, cleanup, ps_strings);
829 	 *
830 	 * Notes:
831 	 *	- obj and cleanup are the auxilliary and termination
832 	 *	  vectors.  They are fixed up by ld.elf_so.
833 	 *	- ps_strings is a NetBSD extention, and will be
834 	 * 	  ignored by executables which are strictly
835 	 *	  compliant with the SVR4 ABI.
836 	 *
837 	 * XXX We have to set both regs and retval here due to different
838 	 * XXX calling convention in trap.c and init_main.c.
839 	 */
840 	tf->fixreg[3] = arginfo.ps_nargvstr;
841 	tf->fixreg[4] = (register_t)arginfo.ps_argvstr;
842 	tf->fixreg[5] = (register_t)arginfo.ps_envstr;
843 	tf->fixreg[6] = 0;			/* auxillary vector */
844 	tf->fixreg[7] = 0;			/* termination vector */
845 	tf->fixreg[8] = (register_t)PS_STRINGS;	/* NetBSD extension */
846 
847 	tf->srr0 = entry;
848 	tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
849 	td->td_pcb->pcb_flags = 0;
850 }
851 
852 extern void	*extint, *extsize;
853 extern u_long	extint_call;
854 
855 void
856 install_extint(void (*handler)(void))
857 {
858 	u_long	offset;
859 	int	omsr, msr;
860 
861 	offset = (u_long)handler - (u_long)&extint_call;
862 
863 #ifdef	DIAGNOSTIC
864 	if (offset > 0x1ffffff)
865 		panic("install_extint: too far away");
866 #endif
867 
868 	msr = mfmsr();
869 	mtmsr(msr & ~(PSL_EE|PSL_RI));
870 
871 	extint_call = (extint_call & 0xfc000003) | offset;
872 	bcopy(&extint, (void *)EXC_EXI, (size_t)&extsize);
873 	__syncicache((void *)&extint_call, sizeof extint_call);
874 	__syncicache((void *)EXC_EXI, (int)&extsize);
875 
876 	mtmsr(msr);
877 }
878 
879 #if !defined(DDB)
880 void
881 Debugger(const char *msg)
882 {
883 
884 	printf("Debugger(\"%s\") called.\n", msg);
885 }
886 #endif /* !defined(DDB) */
887 
888 /* XXX: dummy {fill,set}_[fp]regs */
889 int
890 fill_regs(struct thread *td, struct reg *regs)
891 {
892 
893 	return (ENOSYS);
894 }
895 
896 int
897 fill_dbregs(struct thread *td, struct dbreg *dbregs)
898 {
899 
900 	return (ENOSYS);
901 }
902 
903 int
904 fill_fpregs(struct thread *td, struct fpreg *fpregs)
905 {
906 
907 	return (ENOSYS);
908 }
909 
910 int
911 set_regs(struct thread *td, struct reg *regs)
912 {
913 
914 	return (ENOSYS);
915 }
916 
917 int
918 set_dbregs(struct thread *td, struct dbreg *dbregs)
919 {
920 
921 	return (ENOSYS);
922 }
923 
924 int
925 set_fpregs(struct thread *td, struct fpreg *fpregs)
926 {
927 
928 	return (ENOSYS);
929 }
930 
931 int
932 ptrace_set_pc(struct thread *td, unsigned long addr)
933 {
934 
935 	/* XXX: coming soon... */
936 	return (ENOSYS);
937 }
938 
939 int
940 ptrace_single_step(struct thread *td)
941 {
942 
943 	/* XXX: coming soon... */
944 	return (ENOSYS);
945 }
946 
947 int
948 ptrace_clear_single_step(struct thread *td)
949 {
950 
951 	/* XXX: coming soon... */
952 	return (ENOSYS);
953 }
954 
955 /*
956  * Initialise a struct pcpu.
957  */
958 void
959 cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
960 {
961 
962 	pcpu->pc_current_asngen = 1;
963 }
964 
965 /*
966  * kcopy(const void *src, void *dst, size_t len);
967  *
968  * Copy len bytes from src to dst, aborting if we encounter a fatal
969  * page fault.
970  *
971  * kcopy() _must_ save and restore the old fault handler since it is
972  * called by uiomove(), which may be in the path of servicing a non-fatal
973  * page fault.
974  */
975 int
976 kcopy(const void *src, void *dst, size_t len)
977 {
978 	struct thread	*td;
979 	faultbuf	env, *oldfault;
980 	int		rv;
981 
982 	td = PCPU_GET(curthread);
983 	oldfault = td->td_pcb->pcb_onfault;
984 	if ((rv = setfault(env)) != 0) {
985 		td->td_pcb->pcb_onfault = oldfault;
986 		return rv;
987 	}
988 
989 	memcpy(dst, src, len);
990 
991 	td->td_pcb->pcb_onfault = oldfault;
992 	return (0);
993 }
994