machdep.c revision 77957
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
58static const char rcsid[] =
59  "$FreeBSD: head/sys/powerpc/aim/machdep.c 77957 2001-06-10 02:39:37Z benno $";
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/mutex.h>
71#include <sys/ktr.h>
72#include <sys/signalvar.h>
73#include <sys/kernel.h>
74#include <sys/proc.h>
75#include <sys/lock.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 <fs/procfs/procfs.h>
113#include <machine/sigframe.h>
114
115int cold = 1;
116
117struct mtx	sched_lock;
118struct mtx	Giant;
119
120struct user	*proc0paddr;
121
122char		machine[] = "powerpc";
123SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
124
125static char	model[128];
126SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, "");
127
128char		bootpath[256];
129
130#ifdef DDB
131/* start and end of kernel symbol table */
132void		*ksym_start, *ksym_end;
133#endif /* DDB */
134
135static void	cpu_startup(void *);
136SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
137
138void		powerpc_init(u_int, u_int, u_int, char *);
139
140int		save_ofw_mapping(void);
141int		restore_ofw_mapping(void);
142
143void		install_extint(void (*)(void));
144
145void		osendsig(sig_t, int, sigset_t *, u_long);
146
147struct msgbuf	*msgbufp = 0;
148
149int		bootverbose = 0, Maxmem = 0;
150long		dumplo;
151
152vm_offset_t	phys_avail[10];
153
154static int	chosen;
155
156struct pmap	ofw_pmap;
157extern int	ofmsr;
158
159struct bat	battable[16];
160
161static void	identifycpu(void);
162
163static vm_offset_t	buffer_sva, buffer_eva;
164vm_offset_t		clean_sva, clean_eva;
165static vm_offset_t	pager_sva, pager_eva;
166
167static void
168powerpc_ofw_shutdown(void *junk, int howto)
169{
170	if (howto & RB_HALT) {
171		OF_exit();
172	}
173}
174
175static void
176cpu_startup(void *dummy)
177{
178	unsigned int	i;
179	caddr_t		v;
180	vm_offset_t	maxaddr;
181	vm_size_t	size;
182	vm_offset_t	firstaddr;
183	vm_offset_t	minaddr;
184
185	size = 0;
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	/*
216	 * Calculate callout wheel size
217	 */
218	for (callwheelsize = 1, callwheelbits = 0;
219	     callwheelsize < ncallout;
220	     callwheelsize <<= 1, ++callwheelbits)
221		;
222	callwheelmask = callwheelsize - 1;
223
224	/*
225	 * Allocate space for system data structures.
226	 * The first available kernel virtual address is in "v".
227	 * As pages of kernel virtual memory are allocated, "v" is incremented.
228	 * As pages of memory are allocated and cleared,
229	 * "firstaddr" is incremented.
230	 * An index into the kernel page table corresponding to the
231	 * virtual memory address maintained in "v" is kept in "mapaddr".
232	 */
233
234	/*
235	 * Make two passes.  The first pass calculates how much memory is
236	 * needed and allocates it.  The second pass assigns virtual
237	 * addresses to the various data structures.
238	 */
239	firstaddr = 0;
240again:
241	v = (caddr_t)firstaddr;
242
243#define	valloc(name, type, num) \
244	    (name) = (type *)v; v = (caddr_t)((name)+(num))
245#define	valloclim(name, type, num, lim) \
246	    (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
247
248	valloc(callout, struct callout, ncallout);
249	valloc(callwheel, struct callout_tailq, callwheelsize);
250
251	/*
252	 * The nominal buffer size (and minimum KVA allocation) is BKVASIZE.
253	 * For the first 64MB of ram nominally allocate sufficient buffers to
254	 * cover 1/4 of our ram.  Beyond the first 64MB allocate additional
255	 * buffers to cover 1/20 of our ram over 64MB.
256	 */
257
258	if (nbuf == 0) {
259		int factor;
260
261		factor = 4 * BKVASIZE / PAGE_SIZE;
262		nbuf = 50;
263		if (Maxmem > 1024)
264			nbuf += min((Maxmem - 1024) / factor, 16384 / factor);
265		if (Maxmem > 16384)
266			nbuf += (Maxmem - 16384) * 2 / (factor * 5);
267	}
268	nswbuf = max(min(nbuf/4, 64), 16);
269
270	valloc(swbuf, struct buf, nswbuf);
271	valloc(buf, struct buf, nbuf);
272	v = bufhashinit(v);
273
274	/*
275	 * End of first pass, size has been calculated so allocate memory
276	 */
277	if (firstaddr == 0) {
278		size = (vm_size_t)(v - firstaddr);
279		firstaddr = (vm_offset_t)kmem_alloc(kernel_map,
280		    round_page(size));
281		if (firstaddr == 0)
282			panic("startup: no room for tables");
283		goto again;
284	}
285
286	/*
287	 * End of second pass, addresses have been assigned
288	 */
289	if ((vm_size_t)(v - firstaddr) != size)
290		panic("startup: table size inconsistency");
291
292	clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva,
293	    (nbuf*BKVASIZE) + (nswbuf*MAXPHYS) + pager_map_size);
294	buffer_map = kmem_suballoc(clean_map, &buffer_sva, &buffer_eva,
295	    (nbuf*BKVASIZE));
296	pager_map = kmem_suballoc(clean_map, &pager_sva, &pager_eva,
297	    (nswbuf*MAXPHYS) + pager_map_size);
298	pager_map->system_map = 1;
299	exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
300	    (16*(ARG_MAX+(PAGE_SIZE*3))));
301
302	/*
303	 * XXX: Mbuf system machine-specific initializations should
304	 *      go here, if anywhere.
305	 */
306
307	/*
308	 * Initialize callouts
309	 */
310	SLIST_INIT(&callfree);
311	for (i = 0; i < ncallout; i++) {
312		callout_init(&callout[i], 0);
313		callout[i].c_flags = CALLOUT_LOCAL_ALLOC;
314		SLIST_INSERT_HEAD(&callfree, &callout[i], c_links.sle);
315	}
316
317	for (i = 0; i < callwheelsize; i++) {
318		TAILQ_INIT(&callwheel[i]);
319	}
320
321	mtx_init(&callout_lock, "callout", MTX_SPIN);
322
323#if defined(USERCONFIG)
324#if defined(USERCONFIG_BOOT)
325	if (1)
326#else
327        if (boothowto & RB_CONFIG)
328#endif
329	{
330		userconfig();
331		cninit();	/* the preferred console may have changed */
332	}
333#endif
334
335	printf("avail memory = %ld (%ldK bytes)\n", ptoa(cnt.v_free_count),
336	    ptoa(cnt.v_free_count) / 1024);
337
338	/*
339	 * Set up buffers, so they can be used to read disk labels.
340	 */
341	bufinit();
342	vm_pager_bufferinit();
343	EVENTHANDLER_REGISTER(shutdown_final, powerpc_ofw_shutdown, 0,
344	    SHUTDOWN_PRI_LAST);
345
346#ifdef SMP
347	/*
348	 * OK, enough kmem_alloc/malloc state should be up, lets get on with it!
349	 */
350	mp_start();			/* fire up the secondaries */
351	mp_announce();
352#endif  /* SMP */
353}
354
355void
356identifycpu()
357{
358	int pvr, cpu;
359
360	/*
361	 * Find cpu type (Do it by OpenFirmware?)
362	 */
363	__asm ("mfpvr %0" : "=r"(pvr));
364	cpu = pvr >> 16;
365	switch (cpu) {
366	case 1:
367		sprintf(model, "601");
368		break;
369	case 3:
370		sprintf(model, "603");
371		break;
372	case 4:
373		sprintf(model, "604");
374		break;
375	case 5:
376		sprintf(model, "602");
377		break;
378	case 6:
379		sprintf(model, "603e");
380		break;
381	case 7:
382		sprintf(model, "603ev");
383		break;
384	case 8:
385		sprintf(model, "750 (G3)");
386		break;
387	case 9:
388		sprintf(model, "604ev");
389		break;
390	case 12:
391		sprintf(model, "7400 (G4)");
392		break;
393	case 20:
394		sprintf(model, "620");
395		break;
396	default:
397		sprintf(model, "Version %x", cpu);
398		break;
399	}
400	sprintf(model + strlen(model), " (Revision %x)", pvr & 0xffff);
401	printf("CPU: PowerPC %s\n", model);
402}
403
404extern char	kernel_text[], _end[];
405
406extern void	*trapcode, *trapsize;
407extern void	*alitrap, *alisize;
408extern void	*dsitrap, *dsisize;
409extern void	*isitrap, *isisize;
410extern void	*decrint, *decrsize;
411extern void	*tlbimiss, *tlbimsize;
412extern void	*tlbdlmiss, *tlbdlmsize;
413extern void	*tlbdsmiss, *tlbdsmsize;
414
415#if 0 /* XXX: interrupt handler.  We'll get to this later */
416extern void	ext_intr(void);
417#endif
418
419#ifdef DDB
420extern		ddblow, ddbsize;
421#endif
422#ifdef IPKDB
423extern		ipkdblow, ipkdbsize;
424#endif
425
426static struct globaldata	tmpglobal;
427
428void
429powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args)
430{
431	int			exc, scratch;
432	struct mem_region	*allmem, *availmem, *mp;
433	struct globaldata	*globalp;
434
435	/*
436	 * Set up BAT0 to only map the lowest 256 MB area
437	 */
438	battable[0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW);
439	battable[0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs);
440
441	/*
442	 * Map PCI memory space.
443	 */
444	battable[0x8].batl = BATL(0x80000000, BAT_I, BAT_PP_RW);
445	battable[0x8].batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs);
446
447	battable[0x9].batl = BATL(0x90000000, BAT_I, BAT_PP_RW);
448	battable[0x9].batu = BATU(0x90000000, BAT_BL_256M, BAT_Vs);
449
450	battable[0xa].batl = BATL(0xa0000000, BAT_I, BAT_PP_RW);
451	battable[0xa].batu = BATU(0xa0000000, BAT_BL_256M, BAT_Vs);
452
453	/*
454	 * Map obio devices.
455	 */
456	battable[0xf].batl = BATL(0xf0000000, BAT_I, BAT_PP_RW);
457	battable[0xf].batu = BATU(0xf0000000, BAT_BL_256M, BAT_Vs);
458
459	/*
460	 * Now setup fixed bat registers
461	 *
462	 * Note that we still run in real mode, and the BAT
463	 * registers were cleared above.
464	 */
465	/* BAT0 used for initial 256 MB segment */
466	__asm __volatile ("mtibatl 0,%0; mtibatu 0,%1;"
467		          "mtdbatl 0,%0; mtdbatu 0,%1;"
468		          :: "r"(battable[0].batl), "r"(battable[0].batu));
469	/*
470	 * Set up battable to map all RAM regions.
471	 * This is here because mem_regions() call needs bat0 set up.
472	 */
473	mem_regions(&allmem, &availmem);
474	for (mp = allmem; mp->size; mp++) {
475		vm_offset_t	pa = mp->start & 0xf0000000;
476		vm_offset_t	end = mp->start + mp->size;
477
478		do {
479			u_int n = pa >> 28;
480
481			battable[n].batl = BATL(pa, BAT_M, BAT_PP_RW);
482			battable[n].batu = BATU(pa, BAT_BL_256M, BAT_Vs);
483			pa += 0x10000000;
484		} while (pa < end);
485	}
486
487	chosen = OF_finddevice("/chosen");
488	save_ofw_mapping();
489
490	proc0.p_addr = proc0paddr;
491	bzero(proc0.p_addr, sizeof *proc0.p_addr);
492
493	LIST_INIT(&proc0.p_contested);
494
495/* XXX: NetBSDism I _think_.  Not sure yet. */
496#if 0
497	curpm = curpcb->pcb_pmreal = curpcb->pcb_pm = kernel_pmap;
498#endif
499
500	/*
501	 * Initialise some mutexes.
502	 */
503	mtx_init(&Giant, "Giant", MTX_DEF | MTX_RECURSE);
504	mtx_init(&sched_lock, "sched lock", MTX_SPIN | MTX_RECURSE);
505	mtx_init(&proc0.p_mtx, "process lock", MTX_DEF);
506	mtx_lock(&Giant);
507
508	/*
509	 * Initialise console.
510	 */
511	cninit();
512
513#ifdef	__notyet__		/* Needs some rethinking regarding real/virtual OFW */
514	OF_set_callback(callback);
515#endif
516
517	/*
518	 * Set up trap vectors
519	 */
520	for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100) {
521		switch (exc) {
522		default:
523			bcopy(&trapcode, (void *)exc, (size_t)&trapsize);
524			break;
525		case EXC_EXI:
526			/*
527			 * This one is (potentially) installed during autoconf
528			 */
529			break;
530		case EXC_ALI:
531			bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize);
532			break;
533		case EXC_DSI:
534			bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
535			break;
536		case EXC_ISI:
537			bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize);
538			break;
539		case EXC_DECR:
540			bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize);
541			break;
542		case EXC_IMISS:
543			bcopy(&tlbimiss, (void *)EXC_IMISS, (size_t)&tlbimsize);
544			break;
545		case EXC_DLMISS:
546			bcopy(&tlbdlmiss, (void *)EXC_DLMISS, (size_t)&tlbdlmsize);
547			break;
548		case EXC_DSMISS:
549			bcopy(&tlbdsmiss, (void *)EXC_DSMISS, (size_t)&tlbdsmsize);
550			break;
551#if defined(DDB) || defined(IPKDB)
552		case EXC_TRC:
553		case EXC_PGM:
554		case EXC_BPT:
555#if defined(DDB)
556			bcopy(&ddblow, (void *)exc, (size_t)&ddbsize);
557#else
558			bcopy(&ipkdblow, (void *)exc, (size_t)&ipkdbsize);
559#endif
560			break;
561#endif /* DDB || IPKDB */
562		}
563	}
564
565#if 0 /* XXX: coming soon... */
566	/*
567	 * external interrupt handler install
568	 */
569	install_extint(ext_intr);
570
571	__syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100);
572#endif
573
574	/*
575	 * Now enable translation (and machine checks/recoverable interrupts).
576	 */
577	__asm __volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0; isync"
578		          : "=r"(scratch) : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI));
579
580
581	ofmsr &= ~PSL_IP;
582
583	/*
584	 * Parse arg string.
585	 */
586#ifdef DDB
587	bcopy(args + strlen(args) + 1, &startsym, sizeof(startsym));
588	bcopy(args + strlen(args) + 5, &endsym, sizeof(endsym));
589	if (startsym == NULL || endsym == NULL)
590		startsym = endsym = NULL;
591#endif
592
593	strcpy(bootpath, args);
594	args = bootpath;
595	while (*++args && *args != ' ');
596	if (*args) {
597		*args++ = 0;
598		while (*args) {
599			switch (*args++) {
600			case 'a':
601				boothowto |= RB_ASKNAME;
602				break;
603			case 's':
604				boothowto |= RB_SINGLE;
605				break;
606			case 'd':
607				boothowto |= RB_KDB;
608				break;
609			case 'v':
610				boothowto |= RB_VERBOSE;
611				break;
612			}
613		}
614	}
615
616#ifdef DDB
617	ddb_init((int)((u_int)endsym - (u_int)startsym), startsym, endsym);
618#endif
619#ifdef IPKDB
620	/*
621	 * Now trap to IPKDB
622	 */
623	ipkdb_init();
624	if (boothowto & RB_KDB)
625		ipkdb_connect(0);
626#endif
627
628	/*
629	 * Set the page size.
630	 */
631#if 0
632	vm_set_page_size();
633#endif
634
635	/*
636	 * Initialize pmap module.
637	 */
638	pmap_bootstrap(startkernel, endkernel);
639
640	restore_ofw_mapping();
641
642	/*
643	 * Setup the global data for the bootstrap cpu.
644	 */
645	globalp = (struct globaldata *) &tmpglobal;
646
647	/*
648	 * XXX: Pass 0 as CPU id.  This is bad.  We need to work out
649	 * XXX: which CPU we are somehow.
650	 */
651	globaldata_init(globalp, 0, sizeof(struct globaldata));
652	__asm("mtsprg 0,%0\n" :: "r" (globalp));
653
654	PCPU_GET(next_asn) = 1;	/* 0 used for proc0 pmap */
655	PCPU_SET(curproc, &proc0);
656	PCPU_SET(spinlocks, NULL);
657}
658
659static int N_mapping;
660static struct {
661	vm_offset_t	va;
662	int		len;
663	vm_offset_t	pa;
664	int		mode;
665} ofw_mapping[256];
666
667int
668save_ofw_mapping()
669{
670	int	mmui, mmu;
671
672	OF_getprop(chosen, "mmu", &mmui, 4);
673	mmu = OF_instance_to_package(mmui);
674
675	bzero(ofw_mapping, sizeof(ofw_mapping));
676
677	N_mapping =
678	    OF_getprop(mmu, "translations", ofw_mapping, sizeof(ofw_mapping));
679	N_mapping /= sizeof(ofw_mapping[0]);
680
681	return 0;
682}
683
684int
685restore_ofw_mapping()
686{
687	int		i;
688	struct vm_page	pg;
689
690	pmap_pinit(&ofw_pmap);
691
692	ofw_pmap.pm_sr[KERNEL_SR] = KERNEL_SEGMENT;
693
694	for (i = 0; i < N_mapping; i++) {
695		vm_offset_t	pa = ofw_mapping[i].pa;
696		vm_offset_t	va = ofw_mapping[i].va;
697		int		size = ofw_mapping[i].len;
698
699		if (va < 0x90000000)			/* XXX */
700			continue;
701
702		while (size > 0) {
703			pg.phys_addr = pa;
704			pmap_enter(&ofw_pmap, va, &pg, VM_PROT_ALL,
705			    VM_PROT_ALL);
706			pa += PAGE_SIZE;
707			va += PAGE_SIZE;
708			size -= PAGE_SIZE;
709		}
710	}
711
712	return 0;
713}
714
715void
716bzero(void *buf, size_t len)
717{
718	caddr_t	p;
719
720	p = buf;
721
722	while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) {
723		*p++ = 0;
724		len--;
725	}
726
727	while (len >= sizeof(u_long) * 8) {
728		*(u_long*) p = 0;
729		*((u_long*) p + 1) = 0;
730		*((u_long*) p + 2) = 0;
731		*((u_long*) p + 3) = 0;
732		len -= sizeof(u_long) * 8;
733		*((u_long*) p + 4) = 0;
734		*((u_long*) p + 5) = 0;
735		*((u_long*) p + 6) = 0;
736		*((u_long*) p + 7) = 0;
737		p += sizeof(u_long) * 8;
738	}
739
740	while (len >= sizeof(u_long)) {
741		*(u_long*) p = 0;
742		len -= sizeof(u_long);
743		p += sizeof(u_long);
744	}
745
746	while (len) {
747		*p++ = 0;
748		len--;
749	}
750}
751
752#if 0
753void
754delay(unsigned n)
755{
756	u_long tb;
757
758	do {
759		__asm __volatile("mftb %0" : "=r" (tb));
760	} while (n > (int)(tb & 0xffffffff));
761}
762#endif
763
764void
765osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
766{
767
768	/* XXX: To be done */
769	return;
770}
771
772void
773sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
774{
775
776	/* XXX: To be done */
777	return;
778}
779
780int
781osigreturn(struct proc *p, struct osigreturn_args *uap)
782{
783
784	/* XXX: To be done */
785	return(ENOSYS);
786}
787
788int
789sigreturn(struct proc *p, struct sigreturn_args *uap)
790{
791
792	/* XXX: To be done */
793	return(ENOSYS);
794}
795
796void
797cpu_boot(int howto)
798{
799}
800
801/*
802 * Shutdown the CPU as much as possible.
803 */
804void
805cpu_halt(void)
806{
807
808	OF_exit();
809}
810
811/*
812 * Set set up registers on exec.
813 */
814void
815setregs(struct proc *p, u_long entry, u_long stack, u_long ps_strings)
816{
817	struct trapframe	*tf;
818	struct ps_strings	arginfo;
819
820	tf = trapframe(p);
821
822	bzero(tf, sizeof *tf);
823	tf->fixreg[1] = -roundup(-stack + 8, 16);
824
825	/*
826	 * XXX Machine-independent code has already copied arguments and
827	 * XXX environment to userland.  Get them back here.
828	 */
829	(void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo));
830
831	/*
832	 * Set up arguments for _start():
833	 *	_start(argc, argv, envp, obj, cleanup, ps_strings);
834	 *
835	 * Notes:
836	 *	- obj and cleanup are the auxilliary and termination
837	 *	  vectors.  They are fixed up by ld.elf_so.
838	 *	- ps_strings is a NetBSD extention, and will be
839	 * 	  ignored by executables which are strictly
840	 *	  compliant with the SVR4 ABI.
841	 *
842	 * XXX We have to set both regs and retval here due to different
843	 * XXX calling convention in trap.c and init_main.c.
844	 */
845	tf->fixreg[3] = arginfo.ps_nargvstr;
846	tf->fixreg[4] = (register_t)arginfo.ps_argvstr;
847	tf->fixreg[5] = (register_t)arginfo.ps_envstr;
848	tf->fixreg[6] = 0;			/* auxillary vector */
849	tf->fixreg[7] = 0;			/* termination vector */
850	tf->fixreg[8] = (register_t)PS_STRINGS;	/* NetBSD extension */
851
852	tf->srr0 = entry;
853	tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
854	p->p_addr->u_pcb.pcb_flags = 0;
855}
856
857extern void	*extint, *extsize;
858extern u_long	extint_call;
859
860#if 0
861void
862install_extint(void (*handler)(void))
863{
864	u_long	offset;
865	int	omsr, msr;
866
867	offset = (u_long)handler - (u_long)&extint_call;
868
869#ifdef	DIAGNOSTIC
870	if (offset > 0x1ffffff)
871		panic("install_extint: too far away");
872#endif
873	__asm __volatile ("mfmsr %0; andi. %1,%0,%2; mtmsr %1"
874		          : "=r"(omsr), "=r"(msr) : "K"((u_short)~PSL_EE));
875	extint_call = (extint_call & 0xfc000003) | offset;
876	bcopy(&extint, (void *)EXC_EXI, (size_t)&extsize);
877	__syncicache((void *)&extint_call, sizeof extint_call);
878	__syncicache((void *)EXC_EXI, (int)&extsize);
879	__asm __volatile ("mtmsr %0" :: "r"(omsr));
880}
881#endif
882
883#if !defined(DDB)
884void
885Debugger(const char *msg)
886{
887
888	printf("Debugger(\"%s\") called.\n", msg);
889}
890#endif /* !defined(DDB) */
891
892/* XXX: dummy {fill,set}_[fp]regs */
893int
894fill_regs(struct proc *p, struct reg *regs)
895{
896
897	return (ENOSYS);
898}
899
900int
901fill_fpregs(struct proc *p, struct fpreg *fpregs)
902{
903
904	return (ENOSYS);
905}
906
907int
908set_regs(struct proc *p, struct reg *regs)
909{
910
911	return (ENOSYS);
912}
913
914int
915set_fpregs(struct proc *p, struct fpreg *fpregs)
916{
917
918	return (ENOSYS);
919}
920
921int
922ptrace_set_pc(struct proc *p, unsigned long addr)
923{
924
925	/* XXX: coming soon... */
926	return (ENOSYS);
927}
928
929int
930ptrace_single_step(struct proc *p)
931{
932
933	/* XXX: coming soon... */
934	return (ENOSYS);
935}
936
937int
938ptrace_write_u(struct proc *p, vm_offset_t off, long data)
939{
940
941	/* XXX: coming soon... */
942	return (ENOSYS);
943}
944
945int
946ptrace_read_u_check(struct proc *p, vm_offset_t addr, size_t len)
947{
948
949	/* XXX: coming soon... */
950	return (ENOSYS);
951}
952
953int
954ptrace_clear_single_step(struct proc *p)
955{
956
957	/* XXX: coming soon... */
958	return (ENOSYS);
959}
960
961/*
962 * Initialise a struct globaldata.
963 */
964void
965globaldata_init(struct globaldata *globaldata, int cpuid, size_t sz)
966{
967
968        bzero(globaldata, sz);
969        globaldata->gd_cpuid = cpuid;
970        globaldata->gd_next_asn = 0;
971        globaldata->gd_current_asngen = 1;
972}
973