xref: /freebsd/sys/powerpc/powerpc/machdep.c (revision c17d43407fe04133a94055b0dbc7ea8965654a9f)
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 struct mtx	sched_lock;
118 struct mtx	Giant;
119 
120 char		pcpu0[PAGE_SIZE];
121 char		uarea0[UAREA_PAGES * PAGE_SIZE];
122 struct		trapframe frame0;
123 
124 vm_offset_t	kstack0;
125 vm_offset_t	kstack0_phys;
126 
127 char		machine[] = "powerpc";
128 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
129 
130 static char	model[128];
131 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, "");
132 
133 char		bootpath[256];
134 
135 #ifdef DDB
136 /* start and end of kernel symbol table */
137 void		*ksym_start, *ksym_end;
138 #endif /* DDB */
139 
140 static void	cpu_startup(void *);
141 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
142 
143 void		powerpc_init(u_int, u_int, u_int, char *);
144 
145 int		save_ofw_mapping(void);
146 int		restore_ofw_mapping(void);
147 
148 void		install_extint(void (*)(void));
149 
150 #ifdef COMPAT_43
151 void		osendsig(sig_t, int, sigset_t *, u_long);
152 #endif
153 
154 static int
155 sysctl_hw_physmem(SYSCTL_HANDLER_ARGS)
156 {
157 	int error = sysctl_handle_int(oidp, 0, ctob(physmem), req);
158 	return (error);
159 }
160 
161 SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_INT|CTLFLAG_RD,
162 	0, 0, sysctl_hw_physmem, "IU", "");
163 
164 int		Maxmem = 0;
165 long		dumplo;
166 
167 static int	chosen;
168 
169 struct pmap	ofw_pmap;
170 extern int	ofmsr;
171 
172 struct bat	battable[16];
173 
174 static void	identifycpu(void);
175 
176 struct kva_md_info kmi;
177 
178 static void
179 powerpc_ofw_shutdown(void *junk, int howto)
180 {
181 	if (howto & RB_HALT) {
182 		OF_exit();
183 	}
184 }
185 
186 static void
187 cpu_startup(void *dummy)
188 {
189 
190 	/*
191 	 * Good {morning,afternoon,evening,night}.
192 	 */
193 	identifycpu();
194 
195 	/* startrtclock(); */
196 #ifdef PERFMON
197 	perfmon_init();
198 #endif
199 	printf("real memory  = %ld (%ldK bytes)\n", ptoa(Maxmem),
200 	    ptoa(Maxmem) / 1024);
201 
202 	/*
203 	 * Display any holes after the first chunk of extended memory.
204 	 */
205 	if (bootverbose) {
206 		int indx;
207 
208 		printf("Physical memory chunk(s):\n");
209 		for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
210 			int size1 = phys_avail[indx + 1] - phys_avail[indx];
211 
212 			printf("0x%08x - 0x%08x, %d bytes (%d pages)\n",
213 			    phys_avail[indx], phys_avail[indx + 1] - 1, size1,
214 			    size1 / PAGE_SIZE);
215 		}
216 	}
217 
218 	vm_ksubmap_init(&kmi);
219 
220 #if defined(USERCONFIG)
221 #if defined(USERCONFIG_BOOT)
222 	if (1)
223 #else
224         if (boothowto & RB_CONFIG)
225 #endif
226 	{
227 		userconfig();
228 		cninit();	/* the preferred console may have changed */
229 	}
230 #endif
231 
232 	printf("avail memory = %ld (%ldK bytes)\n", ptoa(cnt.v_free_count),
233 	    ptoa(cnt.v_free_count) / 1024);
234 
235 	/*
236 	 * Set up buffers, so they can be used to read disk labels.
237 	 */
238 	bufinit();
239 	vm_pager_bufferinit();
240 	EVENTHANDLER_REGISTER(shutdown_final, powerpc_ofw_shutdown, 0,
241 	    SHUTDOWN_PRI_LAST);
242 
243 #ifdef SMP
244 	/*
245 	 * OK, enough kmem_alloc/malloc state should be up, lets get on with it!
246 	 */
247 	mp_start();			/* fire up the secondaries */
248 	mp_announce();
249 #endif  /* SMP */
250 }
251 
252 void
253 identifycpu()
254 {
255 	unsigned int pvr, version, revision;
256 
257 	/*
258 	 * Find cpu type (Do it by OpenFirmware?)
259 	 */
260 	__asm ("mfpvr %0" : "=r"(pvr));
261 	version = pvr >> 16;
262 	revision = pvr & 0xffff;
263 	switch (version) {
264 	case 0x0000:
265 		sprintf(model, "Simulator (psim)");
266 		break;
267 	case 0x0001:
268 		sprintf(model, "601");
269 		break;
270 	case 0x0003:
271 		sprintf(model, "603 (Wart)");
272 		break;
273 	case 0x0004:
274 		sprintf(model, "604 (Zephyr)");
275 		break;
276 	case 0x0005:
277 		sprintf(model, "602 (Galahad)");
278 		break;
279 	case 0x0006:
280 		sprintf(model, "603e (Stretch)");
281 		break;
282 	case 0x0007:
283 		if ((revision && 0xf000) == 0x0000)
284 			sprintf(model, "603ev (Valiant)");
285 		else
286 			sprintf(model, "603r (Goldeneye)");
287 		break;
288 	case 0x0008:
289 		if ((revision && 0xf000) == 0x0000)
290 			sprintf(model, "G3 / 750 (Arthur)");
291 		else
292 			sprintf(model, "G3 / 755 (Goldfinger)");
293 		break;
294 	case 0x0009:
295 		if ((revision && 0xf000) == 0x0000)
296 			sprintf(model, "604e (Sirocco)");
297 		else
298 			sprintf(model, "604r (Mach V)");
299 		break;
300 	case 0x000a:
301 		sprintf(model, "604r (Mach V)");
302 		break;
303 	case 0x000c:
304 		sprintf(model, "G4 / 7400 (Max)");
305 		break;
306 	case 0x0014:
307 		sprintf(model, "620 (Red October)");
308 		break;
309 	case 0x0081:
310 		sprintf(model, "8240 (Kahlua)");
311 		break;
312 	case 0x8000:
313 		sprintf(model, "G4 / 7450 (V'ger)");
314 		break;
315 	case 0x800c:
316 		sprintf(model, "G4 / 7410 (Nitro)");
317 		break;
318 	case 0x8081:
319 		sprintf(model, "8245 (Kahlua II)");
320 		break;
321 	default:
322 		sprintf(model, "Version %x", version);
323 		break;
324 	}
325 	sprintf(model + strlen(model), " (Revision %x)", revision);
326 	printf("CPU: PowerPC %s\n", model);
327 }
328 
329 extern char	kernel_text[], _end[];
330 
331 extern void	*trapcode, *trapsize;
332 extern void	*alitrap, *alisize;
333 extern void	*dsitrap, *dsisize;
334 extern void	*isitrap, *isisize;
335 extern void	*decrint, *decrsize;
336 extern void	*tlbimiss, *tlbimsize;
337 extern void	*tlbdlmiss, *tlbdlmsize;
338 extern void	*tlbdsmiss, *tlbdsmsize;
339 
340 #if 0 /* XXX: interrupt handler.  We'll get to this later */
341 extern void	ext_intr(void);
342 #endif
343 
344 #ifdef DDB
345 extern		ddblow, ddbsize;
346 #endif
347 #ifdef IPKDB
348 extern		ipkdblow, ipkdbsize;
349 #endif
350 
351 void
352 powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args)
353 {
354 	struct		pcpu *pc;
355 	vm_offset_t	off;
356 
357 	/*
358 	 * Initialize the console before printing anything.
359 	 */
360 	cninit();
361 
362 	/*
363 	 * XXX: Initialize the interrupt tables.
364 	 */
365 	bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize);
366 	bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
367 	bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize);
368 
369 	/*
370 	 * Start initializing proc0 and thread0.
371 	 */
372 	proc_linkup(&proc0, &proc0.p_ksegrp, &proc0.p_kse, &thread0);
373 	proc0.p_uarea = (struct user *)uarea0;
374 	proc0.p_stats = &proc0.p_uarea->u_stats;
375 	thread0.td_frame = &frame0;
376 	LIST_INIT(&thread0.td_contested);
377 
378 	/*
379 	 * Set up per-cpu data.
380 	 */
381 	pc = (struct pcpu *)(pcpu0 + PAGE_SIZE) - 1;
382 	pcpu_init(pc, 0, sizeof(struct pcpu));
383 	pc->pc_curthread = &thread0;
384 	pc->pc_curpcb = thread0.td_pcb;
385 	pc->pc_cpuid = 0;
386 	/* pc->pc_mid = mid; */
387 
388 	__asm __volatile("mtsprg 0, %0" :: "r"(pc));
389 
390 	/*
391 	 * Initialize mutexes.
392 	 */
393 	mtx_init(&sched_lock, "sched lock", MTX_SPIN | MTX_RECURSE);
394 	mtx_init(&Giant, "Giant", MTX_DEF | MTX_RECURSE);
395 	mtx_init(&proc0.p_mtx, "process lock", MTX_DEF);
396 	mtx_lock(&Giant);
397 
398 	/*
399 	 * Initialise virtual memory.
400 	 */
401 	ofmsr |= PSL_IR | PSL_DR;
402 	pmap_bootstrap(startkernel, endkernel);
403 
404 	/*
405 	 * Initialize tunables.
406 	 */
407 	init_param1();
408 	init_param2(physmem);
409 
410 	/*
411 	 * Finish setting up thread0.
412 	 */
413 	thread0.td_kstack = kstack0;
414 	thread0.td_pcb = (struct pcb *)
415 	    (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
416 
417 	/*
418 	 * Map and initialise the message buffer.
419 	 */
420 	for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
421 		pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off);
422 	msgbufinit(msgbufp, MSGBUF_SIZE);
423 }
424 
425 #if 0 /* XXX: Old powerpc_init */
426 void
427 powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args)
428 {
429 	unsigned int		exc, scratch;
430 	struct mem_region	*allmem, *availmem, *mp;
431 	struct pcpu	*pcpup;
432 
433 	/*
434 	 * Set up BAT0 to only map the lowest 256 MB area
435 	 */
436 	battable[0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW);
437 	battable[0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs);
438 
439 	/*
440 	 * Map PCI memory space.
441 	 */
442 	battable[0x8].batl = BATL(0x80000000, BAT_I, BAT_PP_RW);
443 	battable[0x8].batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs);
444 
445 	battable[0x9].batl = BATL(0x90000000, BAT_I, BAT_PP_RW);
446 	battable[0x9].batu = BATU(0x90000000, BAT_BL_256M, BAT_Vs);
447 
448 	battable[0xa].batl = BATL(0xa0000000, BAT_I, BAT_PP_RW);
449 	battable[0xa].batu = BATU(0xa0000000, BAT_BL_256M, BAT_Vs);
450 
451 	/*
452 	 * Map obio devices.
453 	 */
454 	battable[0xf].batl = BATL(0xf0000000, BAT_I, BAT_PP_RW);
455 	battable[0xf].batu = BATU(0xf0000000, BAT_BL_256M, BAT_Vs);
456 
457 	/*
458 	 * Now setup fixed bat registers
459 	 *
460 	 * Note that we still run in real mode, and the BAT
461 	 * registers were cleared above.
462 	 */
463 	/* BAT0 used for initial 256 MB segment */
464 	__asm __volatile ("mtibatl 0,%0; mtibatu 0,%1;"
465 		          "mtdbatl 0,%0; mtdbatu 0,%1;"
466 		          :: "r"(battable[0].batl), "r"(battable[0].batu));
467 	/*
468 	 * Set up battable to map all RAM regions.
469 	 * This is here because mem_regions() call needs bat0 set up.
470 	 */
471 	mem_regions(&allmem, &availmem);
472 
473 	/* Calculate the physical memory in the machine */
474 	for (mp = allmem; mp->size; mp++)
475 		physmem += btoc(mp->size);
476 
477 	for (mp = allmem; mp->size; mp++) {
478 		vm_offset_t	pa = mp->start & 0xf0000000;
479 		vm_offset_t	end = mp->start + mp->size;
480 
481 		do {
482 			u_int n = pa >> 28;
483 
484 			battable[n].batl = BATL(pa, BAT_M, BAT_PP_RW);
485 			battable[n].batu = BATU(pa, BAT_BL_256M, BAT_Vs);
486 			pa += 0x10000000;
487 		} while (pa < end);
488 	}
489 
490 	chosen = OF_finddevice("/chosen");
491 	save_ofw_mapping();
492 
493 	pmap_setavailmem(startkernel, endkernel);
494 
495 	proc_linkup(&proc0, &proc0.p_ksegrp, &proc0.p_kse, &thread0);
496 
497 	proc0uarea = (struct user *)pmap_steal_memory(UAREA_PAGES * PAGE_SIZE);
498 	proc0kstack = pmap_steal_memory(KSTACK_PAGES * PAGE_SIZE);
499 	proc0.p_uarea = proc0uarea;
500 	thread0.td_kstack = proc0kstack;
501 	thread0.td_pcb = (struct pcb *)
502 	    (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
503 
504 	pcpup = pmap_steal_memory(round_page(sizeof(struct pcpu)));
505 
506 	/*
507 	 * XXX: Pass 0 as CPU id.  This is bad.  We need to work out
508 	 * XXX: which CPU we are somehow.
509 	 */
510 	pcpu_init(pcpup, 0, sizeof(struct pcpu));
511 	__asm ("mtsprg 0, %0" :: "r"(pcpup));
512 
513 	/* Init basic tunables, hz etc */
514 	init_param1();
515 	init_param2(physmem);
516 
517 	/* setup curproc so the mutexes work */
518 
519 	PCPU_SET(curthread, &thread0);
520 
521 	LIST_INIT(&thread0.td_contested);
522 
523 /* XXX: NetBSDism I _think_.  Not sure yet. */
524 #if 0
525 	curpm = PCPU_GET(curpcb)->pcb_pmreal = PCPU_GET(curpcb)->pcb_pm = kernel_pmap;
526 #endif
527 
528 	/*
529 	 * Initialise some mutexes.
530 	 */
531 	mtx_init(&Giant, "Giant", MTX_DEF | MTX_RECURSE);
532 	mtx_init(&sched_lock, "sched lock", MTX_SPIN | MTX_RECURSE);
533 	mtx_init(&proc0.p_mtx, "process lock", MTX_DEF);
534 	mtx_lock(&Giant);
535 
536 	/*
537 	 * Initialise console.
538 	 */
539 	cninit();
540 
541 #ifdef	__notyet__		/* Needs some rethinking regarding real/virtual OFW */
542 	OF_set_callback(callback);
543 #endif
544 
545 	/*
546 	 * Set up trap vectors
547 	 */
548 	for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100) {
549 		switch (exc) {
550 		default:
551 			bcopy(&trapcode, (void *)exc, (size_t)&trapsize);
552 			break;
553 		case EXC_DECR:
554 			bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize);
555 			break;
556 #if 0 /* XXX: Not enabling these traps yet. */
557 		case EXC_EXI:
558 			/*
559 			 * This one is (potentially) installed during autoconf
560 			 */
561 			break;
562 		case EXC_ALI:
563 			bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize);
564 			break;
565 		case EXC_DSI:
566 			bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
567 			break;
568 		case EXC_ISI:
569 			bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize);
570 			break;
571 		case EXC_IMISS:
572 			bcopy(&tlbimiss, (void *)EXC_IMISS, (size_t)&tlbimsize);
573 			break;
574 		case EXC_DLMISS:
575 			bcopy(&tlbdlmiss, (void *)EXC_DLMISS, (size_t)&tlbdlmsize);
576 			break;
577 		case EXC_DSMISS:
578 			bcopy(&tlbdsmiss, (void *)EXC_DSMISS, (size_t)&tlbdsmsize);
579 			break;
580 #if defined(DDB) || defined(IPKDB)
581 		case EXC_TRC:
582 		case EXC_PGM:
583 		case EXC_BPT:
584 #if defined(DDB)
585 			bcopy(&ddblow, (void *)exc, (size_t)&ddbsize);
586 #else
587 			bcopy(&ipkdblow, (void *)exc, (size_t)&ipkdbsize);
588 #endif
589 			break;
590 #endif /* DDB || IPKDB */
591 #endif
592 		}
593 	}
594 
595 #if 0 /* XXX: coming soon... */
596 	/*
597 	 * external interrupt handler install
598 	 */
599 	install_extint(ext_intr);
600 #endif
601 
602 	__syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100);
603 
604 	/*
605 	 * Now enable translation (and machine checks/recoverable interrupts).
606 	 */
607 	__asm ("mfmsr %0" : "=r"(scratch));
608 	scratch |= PSL_IR | PSL_DR | PSL_ME | PSL_RI;
609 	__asm ("mtmsr %0" :: "r"(scratch));
610 
611 	ofmsr &= ~PSL_IP;
612 
613 	/*
614 	 * Parse arg string.
615 	 */
616 #ifdef DDB
617 	bcopy(args + strlen(args) + 1, &startsym, sizeof(startsym));
618 	bcopy(args + strlen(args) + 5, &endsym, sizeof(endsym));
619 	if (startsym == NULL || endsym == NULL)
620 		startsym = endsym = NULL;
621 #endif
622 
623 	strcpy(bootpath, args);
624 	args = bootpath;
625 	while (*++args && *args != ' ');
626 	if (*args) {
627 		*args++ = 0;
628 		while (*args) {
629 			switch (*args++) {
630 			case 'a':
631 				boothowto |= RB_ASKNAME;
632 				break;
633 			case 's':
634 				boothowto |= RB_SINGLE;
635 				break;
636 			case 'd':
637 				boothowto |= RB_KDB;
638 				break;
639 			case 'v':
640 				boothowto |= RB_VERBOSE;
641 				break;
642 			}
643 		}
644 	}
645 
646 #ifdef DDB
647 	ddb_init((int)((u_int)endsym - (u_int)startsym), startsym, endsym);
648 #endif
649 #ifdef IPKDB
650 	/*
651 	 * Now trap to IPKDB
652 	 */
653 	ipkdb_init();
654 	if (boothowto & RB_KDB)
655 		ipkdb_connect(0);
656 #endif
657 
658 	/*
659 	 * Set the page size.
660 	 */
661 #if 0
662 	vm_set_page_size();
663 #endif
664 
665 	/*
666 	 * Initialize pmap module.
667 	 */
668 	pmap_bootstrap();
669 
670 	restore_ofw_mapping();
671 
672 	PCPU_GET(next_asn) = 1;	/* 0 used for proc0 pmap */
673 
674 	/* setup proc 0's pcb */
675 	thread0.td_pcb->pcb_flags = 0; /* XXXKSE */
676 	thread0.td_frame = &proc0_tf;
677 }
678 #endif
679 
680 static int N_mapping;
681 static struct {
682 	vm_offset_t	va;
683 	int		len;
684 	vm_offset_t	pa;
685 	int		mode;
686 } ofw_mapping[256];
687 
688 int
689 save_ofw_mapping()
690 {
691 	int	mmui, mmu;
692 
693 	OF_getprop(chosen, "mmu", &mmui, 4);
694 	mmu = OF_instance_to_package(mmui);
695 
696 	bzero(ofw_mapping, sizeof(ofw_mapping));
697 
698 	N_mapping =
699 	    OF_getprop(mmu, "translations", ofw_mapping, sizeof(ofw_mapping));
700 	N_mapping /= sizeof(ofw_mapping[0]);
701 
702 	return 0;
703 }
704 
705 int
706 restore_ofw_mapping()
707 {
708 	int		i;
709 	struct vm_page	pg;
710 
711 	pmap_pinit(&ofw_pmap);
712 
713 	ofw_pmap.pm_sr[KERNEL_SR] = KERNEL_SEGMENT;
714 
715 	for (i = 0; i < N_mapping; i++) {
716 		vm_offset_t	pa = ofw_mapping[i].pa;
717 		vm_offset_t	va = ofw_mapping[i].va;
718 		int		size = ofw_mapping[i].len;
719 
720 		if (va < 0x80000000)			/* XXX */
721 			continue;
722 
723 		while (size > 0) {
724 			pg.phys_addr = pa;
725 			pmap_enter(&ofw_pmap, va, &pg, VM_PROT_ALL,
726 			    VM_PROT_ALL);
727 			pa += PAGE_SIZE;
728 			va += PAGE_SIZE;
729 			size -= PAGE_SIZE;
730 		}
731 	}
732 
733 	return 0;
734 }
735 
736 void
737 bzero(void *buf, size_t len)
738 {
739 	caddr_t	p;
740 
741 	p = buf;
742 
743 	while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) {
744 		*p++ = 0;
745 		len--;
746 	}
747 
748 	while (len >= sizeof(u_long) * 8) {
749 		*(u_long*) p = 0;
750 		*((u_long*) p + 1) = 0;
751 		*((u_long*) p + 2) = 0;
752 		*((u_long*) p + 3) = 0;
753 		len -= sizeof(u_long) * 8;
754 		*((u_long*) p + 4) = 0;
755 		*((u_long*) p + 5) = 0;
756 		*((u_long*) p + 6) = 0;
757 		*((u_long*) p + 7) = 0;
758 		p += sizeof(u_long) * 8;
759 	}
760 
761 	while (len >= sizeof(u_long)) {
762 		*(u_long*) p = 0;
763 		len -= sizeof(u_long);
764 		p += sizeof(u_long);
765 	}
766 
767 	while (len) {
768 		*p++ = 0;
769 		len--;
770 	}
771 }
772 
773 #if 0
774 void
775 delay(unsigned n)
776 {
777 	u_long tb;
778 
779 	do {
780 		__asm __volatile("mftb %0" : "=r" (tb));
781 	} while (n > (int)(tb & 0xffffffff));
782 }
783 #endif
784 
785 #ifdef COMPAT_43
786 void
787 osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
788 {
789 
790 	/* XXX: To be done */
791 	return;
792 }
793 #endif
794 
795 void
796 sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
797 {
798 
799 	/* XXX: To be done */
800 	return;
801 }
802 
803 /*
804  * Stub to satisfy the reference to osigreturn in the syscall table.  This
805  * is needed even for newer arches that don't support old signals because
806  * the syscall table is machine-independent.
807  */
808 int
809 osigreturn(struct thread *td, struct osigreturn_args *uap)
810 {
811 
812 	return (nosys(td, (struct nosys_args *)uap));
813 }
814 
815 int
816 sigreturn(struct thread *td, struct sigreturn_args *uap)
817 {
818 
819 	/* XXX: To be done */
820 	return(ENOSYS);
821 }
822 
823 void
824 cpu_boot(int howto)
825 {
826 }
827 
828 /*
829  * Shutdown the CPU as much as possible.
830  */
831 void
832 cpu_halt(void)
833 {
834 
835 	OF_exit();
836 }
837 
838 /*
839  * Set set up registers on exec.
840  */
841 void
842 setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
843 {
844 	struct trapframe	*tf;
845 	struct ps_strings	arginfo;
846 
847 	tf = trapframe(td);
848 	bzero(tf, sizeof *tf);
849 	tf->fixreg[1] = -roundup(-stack + 8, 16);
850 
851 	/*
852 	 * XXX Machine-independent code has already copied arguments and
853 	 * XXX environment to userland.  Get them back here.
854 	 */
855 	(void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo));
856 
857 	/*
858 	 * Set up arguments for _start():
859 	 *	_start(argc, argv, envp, obj, cleanup, ps_strings);
860 	 *
861 	 * Notes:
862 	 *	- obj and cleanup are the auxilliary and termination
863 	 *	  vectors.  They are fixed up by ld.elf_so.
864 	 *	- ps_strings is a NetBSD extention, and will be
865 	 * 	  ignored by executables which are strictly
866 	 *	  compliant with the SVR4 ABI.
867 	 *
868 	 * XXX We have to set both regs and retval here due to different
869 	 * XXX calling convention in trap.c and init_main.c.
870 	 */
871 	tf->fixreg[3] = arginfo.ps_nargvstr;
872 	tf->fixreg[4] = (register_t)arginfo.ps_argvstr;
873 	tf->fixreg[5] = (register_t)arginfo.ps_envstr;
874 	tf->fixreg[6] = 0;			/* auxillary vector */
875 	tf->fixreg[7] = 0;			/* termination vector */
876 	tf->fixreg[8] = (register_t)PS_STRINGS;	/* NetBSD extension */
877 
878 	tf->srr0 = entry;
879 	tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
880 	td->td_pcb->pcb_flags = 0;
881 }
882 
883 extern void	*extint, *extsize;
884 extern u_long	extint_call;
885 
886 void
887 install_extint(void (*handler)(void))
888 {
889 	u_long	offset;
890 	int	omsr, msr;
891 
892 	offset = (u_long)handler - (u_long)&extint_call;
893 
894 #ifdef	DIAGNOSTIC
895 	if (offset > 0x1ffffff)
896 		panic("install_extint: too far away");
897 #endif
898 
899 	msr = mfmsr();
900 	mtmsr(msr & ~(PSL_EE|PSL_RI));
901 
902 	extint_call = (extint_call & 0xfc000003) | offset;
903 	bcopy(&extint, (void *)EXC_EXI, (size_t)&extsize);
904 	__syncicache((void *)&extint_call, sizeof extint_call);
905 	__syncicache((void *)EXC_EXI, (int)&extsize);
906 
907 	mtmsr(msr);
908 }
909 
910 #if !defined(DDB)
911 void
912 Debugger(const char *msg)
913 {
914 
915 	printf("Debugger(\"%s\") called.\n", msg);
916 }
917 #endif /* !defined(DDB) */
918 
919 /* XXX: dummy {fill,set}_[fp]regs */
920 int
921 fill_regs(struct thread *td, struct reg *regs)
922 {
923 
924 	return (ENOSYS);
925 }
926 
927 int
928 fill_dbregs(struct thread *td, struct dbreg *dbregs)
929 {
930 
931 	return (ENOSYS);
932 }
933 
934 int
935 fill_fpregs(struct thread *td, struct fpreg *fpregs)
936 {
937 
938 	return (ENOSYS);
939 }
940 
941 int
942 set_regs(struct thread *td, struct reg *regs)
943 {
944 
945 	return (ENOSYS);
946 }
947 
948 int
949 set_dbregs(struct thread *td, struct dbreg *dbregs)
950 {
951 
952 	return (ENOSYS);
953 }
954 
955 int
956 set_fpregs(struct thread *td, struct fpreg *fpregs)
957 {
958 
959 	return (ENOSYS);
960 }
961 
962 int
963 ptrace_set_pc(struct thread *td, unsigned long addr)
964 {
965 
966 	/* XXX: coming soon... */
967 	return (ENOSYS);
968 }
969 
970 int
971 ptrace_single_step(struct thread *td)
972 {
973 
974 	/* XXX: coming soon... */
975 	return (ENOSYS);
976 }
977 
978 int
979 ptrace_clear_single_step(struct thread *td)
980 {
981 
982 	/* XXX: coming soon... */
983 	return (ENOSYS);
984 }
985 
986 /*
987  * Initialise a struct pcpu.
988  */
989 void
990 cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
991 {
992 
993 	pcpu->pc_current_asngen = 1;
994 }
995 
996 void
997 enable_fpu(struct pcb *pcb)
998 {
999 	int msr, scratch;
1000 
1001 	if (!(pcb->pcb_flags & PCB_FPU)) {
1002 		bzero(&pcb->pcb_fpu, sizeof pcb->pcb_fpu);
1003 		pcb->pcb_flags |= PCB_FPU;
1004 	}
1005 	__asm volatile ("mfmsr %0; ori %1,%0,%2; mtmsr %1; isync"
1006 		      : "=r"(msr), "=r"(scratch) : "K"(PSL_FP));
1007 	__asm volatile ("lfd 0,0(%0); mtfsf 0xff,0" :: "b"(&pcb->pcb_fpu.fpscr));
1008 	__asm ("lfd 0,0(%0);"
1009 	     "lfd 1,8(%0);"
1010 	     "lfd 2,16(%0);"
1011 	     "lfd 3,24(%0);"
1012 	     "lfd 4,32(%0);"
1013 	     "lfd 5,40(%0);"
1014 	     "lfd 6,48(%0);"
1015 	     "lfd 7,56(%0);"
1016 	     "lfd 8,64(%0);"
1017 	     "lfd 9,72(%0);"
1018 	     "lfd 10,80(%0);"
1019 	     "lfd 11,88(%0);"
1020 	     "lfd 12,96(%0);"
1021 	     "lfd 13,104(%0);"
1022 	     "lfd 14,112(%0);"
1023 	     "lfd 15,120(%0);"
1024 	     "lfd 16,128(%0);"
1025 	     "lfd 17,136(%0);"
1026 	     "lfd 18,144(%0);"
1027 	     "lfd 19,152(%0);"
1028 	     "lfd 20,160(%0);"
1029 	     "lfd 21,168(%0);"
1030 	     "lfd 22,176(%0);"
1031 	     "lfd 23,184(%0);"
1032 	     "lfd 24,192(%0);"
1033 	     "lfd 25,200(%0);"
1034 	     "lfd 26,208(%0);"
1035 	     "lfd 27,216(%0);"
1036 	     "lfd 28,224(%0);"
1037 	     "lfd 29,232(%0);"
1038 	     "lfd 30,240(%0);"
1039 	     "lfd 31,248(%0)" :: "b"(&pcb->pcb_fpu.fpr[0]));
1040 	__asm volatile ("mtmsr %0; isync" :: "r"(msr));
1041 }
1042 
1043 void
1044 save_fpu(struct pcb *pcb)
1045 {
1046 	int msr, scratch;
1047 
1048 	__asm volatile ("mfmsr %0; ori %1,%0,%2; mtmsr %1; isync"
1049 		      : "=r"(msr), "=r"(scratch) : "K"(PSL_FP));
1050 	__asm ("stfd 0,0(%0);"
1051 	     "stfd 1,8(%0);"
1052 	     "stfd 2,16(%0);"
1053 	     "stfd 3,24(%0);"
1054 	     "stfd 4,32(%0);"
1055 	     "stfd 5,40(%0);"
1056 	     "stfd 6,48(%0);"
1057 	     "stfd 7,56(%0);"
1058 	     "stfd 8,64(%0);"
1059 	     "stfd 9,72(%0);"
1060 	     "stfd 10,80(%0);"
1061 	     "stfd 11,88(%0);"
1062 	     "stfd 12,96(%0);"
1063 	     "stfd 13,104(%0);"
1064 	     "stfd 14,112(%0);"
1065 	     "stfd 15,120(%0);"
1066 	     "stfd 16,128(%0);"
1067 	     "stfd 17,136(%0);"
1068 	     "stfd 18,144(%0);"
1069 	     "stfd 19,152(%0);"
1070 	     "stfd 20,160(%0);"
1071 	     "stfd 21,168(%0);"
1072 	     "stfd 22,176(%0);"
1073 	     "stfd 23,184(%0);"
1074 	     "stfd 24,192(%0);"
1075 	     "stfd 25,200(%0);"
1076 	     "stfd 26,208(%0);"
1077 	     "stfd 27,216(%0);"
1078 	     "stfd 28,224(%0);"
1079 	     "stfd 29,232(%0);"
1080 	     "stfd 30,240(%0);"
1081 	     "stfd 31,248(%0)" :: "b"(&pcb->pcb_fpu.fpr[0]));
1082 	__asm volatile ("mffs 0; stfd 0,0(%0)" :: "b"(&pcb->pcb_fpu.fpscr));
1083 	__asm volatile ("mtmsr %0; isync" :: "r"(msr));
1084 }
1085