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