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