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