xref: /freebsd/sys/powerpc/powerpc/machdep.c (revision d37ea99837e6ad50837fd9fe1771ddf1c3ba6002)
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 #include <sys/cdefs.h>
58 __FBSDID("$FreeBSD$");
59 
60 #include "opt_ddb.h"
61 #include "opt_compat.h"
62 #include "opt_kstack_pages.h"
63 #include "opt_msgbuf.h"
64 
65 #include <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/eventhandler.h>
68 #include <sys/imgact.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 <sys/sysent.h>
91 #include <net/netisr.h>
92 #include <vm/vm.h>
93 #include <vm/vm_kern.h>
94 #include <vm/vm_page.h>
95 #include <vm/vm_map.h>
96 #include <vm/vm_extern.h>
97 #include <vm/vm_object.h>
98 #include <vm/vm_pager.h>
99 #include <sys/user.h>
100 #include <sys/ptrace.h>
101 #include <machine/bat.h>
102 #include <machine/clock.h>
103 #include <machine/cpu.h>
104 #include <machine/md_var.h>
105 #include <machine/metadata.h>
106 #include <machine/reg.h>
107 #include <machine/fpu.h>
108 #include <machine/vmparam.h>
109 #include <machine/elf.h>
110 #include <machine/trap.h>
111 #include <machine/powerpc.h>
112 #include <dev/ofw/openfirm.h>
113 #include <ddb/ddb.h>
114 #include <sys/vnode.h>
115 #include <machine/sigframe.h>
116 
117 int cold = 1;
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 static int cacheline_size = CACHELINESIZE;
133 SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size,
134 	   CTLFLAG_RD, &cacheline_size, 0, "");
135 
136 #ifdef DDB
137 /* start and end of kernel symbol table */
138 void		*ksym_start, *ksym_end;
139 #endif /* DDB */
140 
141 static void	cpu_startup(void *);
142 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
143 
144 void		powerpc_init(u_int, u_int, u_int, void *);
145 
146 int		save_ofw_mapping(void);
147 int		restore_ofw_mapping(void);
148 
149 void		install_extint(void (*)(void));
150 
151 int             setfault(faultbuf);             /* defined in locore.S */
152 
153 static int	grab_mcontext(struct thread *, mcontext_t *, int);
154 
155 void		asm_panic(char *);
156 
157 long		Maxmem = 0;
158 
159 struct pmap	ofw_pmap;
160 extern int	ofmsr;
161 
162 struct bat	battable[16];
163 
164 struct kva_md_info kmi;
165 
166 static void
167 powerpc_ofw_shutdown(void *junk, int howto)
168 {
169 	if (howto & RB_HALT) {
170 		OF_halt();
171 	}
172 	OF_reboot();
173 }
174 
175 static void
176 cpu_startup(void *dummy)
177 {
178 
179 	/*
180 	 * Initialise the decrementer-based clock.
181 	 */
182 	decr_init();
183 
184 	/*
185 	 * Good {morning,afternoon,evening,night}.
186 	 */
187 	cpu_setup(PCPU_GET(cpuid));
188 
189 	/* startrtclock(); */
190 #ifdef PERFMON
191 	perfmon_init();
192 #endif
193 	printf("real memory  = %ld (%ld MB)\n", ptoa(Maxmem),
194 	    ptoa(Maxmem) / 1048576);
195 
196 	/*
197 	 * Display any holes after the first chunk of extended memory.
198 	 */
199 	if (bootverbose) {
200 		int indx;
201 
202 		printf("Physical memory chunk(s):\n");
203 		for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
204 			int size1 = phys_avail[indx + 1] - phys_avail[indx];
205 
206 			printf("0x%08x - 0x%08x, %d bytes (%d pages)\n",
207 			    phys_avail[indx], phys_avail[indx + 1] - 1, size1,
208 			    size1 / PAGE_SIZE);
209 		}
210 	}
211 
212 	vm_ksubmap_init(&kmi);
213 
214 	printf("avail memory = %ld (%ld MB)\n", ptoa(cnt.v_free_count),
215 	    ptoa(cnt.v_free_count) / 1048576);
216 
217 	/*
218 	 * Set up buffers, so they can be used to read disk labels.
219 	 */
220 	bufinit();
221 	vm_pager_bufferinit();
222 
223 	EVENTHANDLER_REGISTER(shutdown_final, powerpc_ofw_shutdown, 0,
224 	    SHUTDOWN_PRI_LAST);
225 
226 #ifdef SMP
227 	/*
228 	 * OK, enough kmem_alloc/malloc state should be up, lets get on with it!
229 	 */
230 	mp_start();			/* fire up the secondaries */
231 	mp_announce();
232 #endif  /* SMP */
233 }
234 
235 extern char	kernel_text[], _end[];
236 
237 extern void	*trapcode, *trapsize;
238 extern void	*alitrap, *alisize;
239 extern void	*dsitrap, *dsisize;
240 extern void	*decrint, *decrsize;
241 extern void     *extint, *extsize;
242 extern void	*ddblow, *ddbsize;
243 
244 void
245 powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
246 {
247 	struct		pcpu *pc;
248 	vm_offset_t	end, off;
249 	void		*kmdp;
250 
251 	end = 0;
252 	kmdp = NULL;
253 
254 	/*
255 	 * Parse metadata if present and fetch parameters.  Must be done
256 	 * before console is inited so cninit gets the right value of
257 	 * boothowto.
258 	 */
259 	if (mdp != NULL) {
260 		preload_metadata = mdp;
261 		kmdp = preload_search_by_type("elf kernel");
262 		if (kmdp != NULL) {
263 			boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
264 			kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
265 			end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
266 		}
267 	}
268 
269 	/*
270 	 * Init params/tunables that can be overridden by the loader
271 	 */
272 	init_param1();
273 
274 	/*
275 	 * Start initializing proc0 and thread0.
276 	 */
277 	proc_linkup(&proc0, &ksegrp0, &kse0, &thread0);
278 	proc0.p_uarea = (struct user *)uarea0;
279 	proc0.p_stats = &proc0.p_uarea->u_stats;
280 	thread0.td_frame = &frame0;
281 
282 	/*
283 	 * Set up per-cpu data.
284 	 */
285 	pc = (struct pcpu *)(pcpu0 + PAGE_SIZE) - 1;
286 	pcpu_init(pc, 0, sizeof(struct pcpu));
287 	pc->pc_curthread = &thread0;
288 	pc->pc_curpcb = thread0.td_pcb;
289 	pc->pc_cpuid = 0;
290 	/* pc->pc_mid = mid; */
291 
292 	__asm __volatile("mtsprg 0, %0" :: "r"(pc));
293 
294 	mutex_init();
295 
296 	/*
297 	 * Initialize the console before printing anything.
298 	 */
299 	cninit();
300 
301 	/*
302 	 * Complain if there is no metadata.
303 	 */
304 	if (mdp == NULL || kmdp == NULL) {
305 		printf("powerpc_init: no loader metadata.\n");
306 	}
307 
308 #ifdef DDB
309 	kdb_init();
310 #endif
311 	/*
312 	 * XXX: Initialize the interrupt tables.
313 	 */
314 	bcopy(&trapcode, (void *)EXC_RST,  (size_t)&trapsize);
315 	bcopy(&trapcode, (void *)EXC_MCHK, (size_t)&trapsize);
316 	bcopy(&dsitrap,  (void *)EXC_DSI,  (size_t)&dsisize);
317 	bcopy(&trapcode, (void *)EXC_ISI,  (size_t)&trapsize);
318 	bcopy(&trapcode, (void *)EXC_EXI,  (size_t)&trapsize);
319 	bcopy(&trapcode, (void *)EXC_ALI,  (size_t)&trapsize);
320 	bcopy(&trapcode, (void *)EXC_PGM,  (size_t)&trapsize);
321 	bcopy(&trapcode, (void *)EXC_FPU,  (size_t)&trapsize);
322 	bcopy(&trapcode, (void *)EXC_DECR, (size_t)&trapsize);
323 	bcopy(&trapcode, (void *)EXC_SC,   (size_t)&trapsize);
324 	bcopy(&trapcode, (void *)EXC_TRC,  (size_t)&trapsize);
325 	bcopy(&trapcode, (void *)EXC_FPA,  (size_t)&trapsize);
326 	bcopy(&trapcode, (void *)EXC_THRM, (size_t)&trapsize);
327 	bcopy(&trapcode, (void *)EXC_BPT,  (size_t)&trapsize);
328 #ifdef DDB
329 	bcopy(&ddblow,   (void *)EXC_PGM,  (size_t)&ddbsize);
330 	bcopy(&ddblow,   (void *)EXC_TRC,  (size_t)&ddbsize);
331 	bcopy(&ddblow,   (void *)EXC_BPT,  (size_t)&ddbsize);
332 #endif
333 	__syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD);
334 
335 	/*
336 	 * Make sure translation has been enabled
337 	 */
338 	mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI);
339 
340 	/*
341 	 * Initialise virtual memory.
342 	 */
343 	pmap_bootstrap(startkernel, endkernel);
344 
345 	/*
346 	 * Initialize params/tunables that are derived from memsize
347 	 */
348 	init_param2(physmem);
349 
350 	/*
351 	 * Finish setting up thread0.
352 	 */
353 	thread0.td_kstack = kstack0;
354 	thread0.td_pcb = (struct pcb *)
355 	    (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
356 
357 	/*
358 	 * Map and initialise the message buffer.
359 	 */
360 	for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
361 		pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off);
362 	msgbufinit(msgbufp, MSGBUF_SIZE);
363 }
364 
365 void
366 bzero(void *buf, size_t len)
367 {
368 	caddr_t	p;
369 
370 	p = buf;
371 
372 	while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) {
373 		*p++ = 0;
374 		len--;
375 	}
376 
377 	while (len >= sizeof(u_long) * 8) {
378 		*(u_long*) p = 0;
379 		*((u_long*) p + 1) = 0;
380 		*((u_long*) p + 2) = 0;
381 		*((u_long*) p + 3) = 0;
382 		len -= sizeof(u_long) * 8;
383 		*((u_long*) p + 4) = 0;
384 		*((u_long*) p + 5) = 0;
385 		*((u_long*) p + 6) = 0;
386 		*((u_long*) p + 7) = 0;
387 		p += sizeof(u_long) * 8;
388 	}
389 
390 	while (len >= sizeof(u_long)) {
391 		*(u_long*) p = 0;
392 		len -= sizeof(u_long);
393 		p += sizeof(u_long);
394 	}
395 
396 	while (len) {
397 		*p++ = 0;
398 		len--;
399 	}
400 }
401 
402 void
403 sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
404 {
405 	struct trapframe *tf;
406 	struct sigframe *sfp;
407 	struct sigacts *psp;
408 	struct sigframe sf;
409 	struct thread *td;
410 	struct proc *p;
411 	int oonstack, rndfsize;
412 
413 	td = curthread;
414 	p = td->td_proc;
415 	PROC_LOCK_ASSERT(p, MA_OWNED);
416 	psp = p->p_sigacts;
417 	mtx_assert(&psp->ps_mtx, MA_OWNED);
418 	tf = td->td_frame;
419 	oonstack = sigonstack(tf->fixreg[1]);
420 
421 	rndfsize = ((sizeof(sf) + 15) / 16) * 16;
422 
423 	CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
424 	     catcher, sig);
425 
426 	/*
427 	 * Save user context
428 	 */
429 	memset(&sf, 0, sizeof(sf));
430 	grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0);
431 	sf.sf_uc.uc_sigmask = *mask;
432 	sf.sf_uc.uc_stack = td->td_sigstk;
433 	sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
434 	    ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
435 
436 	sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
437 
438 	/*
439 	 * Allocate and validate space for the signal handler context.
440 	 */
441 	if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
442 	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
443 		sfp = (struct sigframe *)((caddr_t)td->td_sigstk.ss_sp +
444 		   td->td_sigstk.ss_size - rndfsize);
445 	} else {
446 		sfp = (struct sigframe *)(tf->fixreg[1] - rndfsize);
447 	}
448 
449 	/*
450 	 * Translate the signal if appropriate (Linux emu ?)
451 	 */
452 	if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
453 		sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
454 
455 	/*
456 	 * Save the floating-point state, if necessary, then copy it.
457 	 */
458 	/* XXX */
459 
460 	/*
461 	 * Set up the registers to return to sigcode.
462 	 *
463 	 *   r1/sp - sigframe ptr
464 	 *   lr    - sig function, dispatched to by blrl in trampoline
465 	 *   r3    - sig number
466 	 *   r4    - SIGINFO ? &siginfo : exception code
467 	 *   r5    - user context
468 	 *   srr0  - trampoline function addr
469 	 */
470 	tf->lr = (register_t)catcher;
471 	tf->fixreg[1] = (register_t)sfp;
472 	tf->fixreg[FIRSTARG] = sig;
473 	tf->fixreg[FIRSTARG+2] = (register_t)&sfp->sf_uc;
474 	if (SIGISMEMBER(psp->ps_siginfo, sig)) {
475 		/*
476 		 * Signal handler installed with SA_SIGINFO.
477 		 */
478 		tf->fixreg[FIRSTARG+1] = (register_t)&sfp->sf_si;
479 
480 		/*
481 		 * Fill siginfo structure.
482 		 */
483 		sf.sf_si.si_signo = sig;
484 		sf.sf_si.si_code = code;
485 		sf.sf_si.si_addr = (void *)tf->srr0;
486 	} else {
487 		/* Old FreeBSD-style arguments. */
488 		tf->fixreg[FIRSTARG+1] = code;
489 	}
490 	mtx_unlock(&psp->ps_mtx);
491 	PROC_UNLOCK(p);
492 
493 	tf->srr0 = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode));
494 
495 	/*
496 	 * copy the frame out to userland.
497 	 */
498 	if (copyout((caddr_t)&sf, (caddr_t)sfp, sizeof(sf)) != 0) {
499 		/*
500 		 * Process has trashed its stack. Kill it.
501 		 */
502 		CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp);
503 		PROC_LOCK(p);
504 		sigexit(td, SIGILL);
505 	}
506 
507 	CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td,
508 	     tf->srr0, tf->fixreg[1]);
509 
510 	PROC_LOCK(p);
511 	mtx_lock(&psp->ps_mtx);
512 }
513 
514 /*
515  * Build siginfo_t for SA thread
516  */
517 void
518 cpu_thread_siginfo(int sig, u_long code, siginfo_t *si)
519 {
520 	struct proc *p;
521 	struct thread *td;
522 
523 	td = curthread;
524 	p = td->td_proc;
525 	PROC_LOCK_ASSERT(p, MA_OWNED);
526 
527 	bzero(si, sizeof(*si));
528 	si->si_signo = sig;
529 	si->si_code = code;
530 	/* XXXKSE fill other fields */
531 }
532 
533 int
534 sigreturn(struct thread *td, struct sigreturn_args *uap)
535 {
536 	struct proc *p;
537 	ucontext_t uc;
538 	int error;
539 
540 	CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
541 
542 	if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
543 		CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
544 		return (EFAULT);
545 	}
546 
547 	error = set_mcontext(td, &uc.uc_mcontext);
548 	if (error != 0)
549 		return (error);
550 
551 	p = td->td_proc;
552 	PROC_LOCK(p);
553 	td->td_sigmask = uc.uc_sigmask;
554 	SIG_CANTMASK(td->td_sigmask);
555 	signotify(td);
556 	PROC_UNLOCK(p);
557 
558 	CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
559 	     td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
560 
561 	return (EJUSTRETURN);
562 }
563 
564 #ifdef COMPAT_FREEBSD4
565 int
566 freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
567 {
568 
569 	return sigreturn(td, (struct sigreturn_args *)uap);
570 }
571 #endif
572 
573 /*
574  * get_mcontext/sendsig helper routine that doesn't touch the
575  * proc lock
576  */
577 static int
578 grab_mcontext(struct thread *td, mcontext_t *mcp, int flags)
579 {
580 	struct pcb *pcb;
581 
582 	pcb = td->td_pcb;
583 
584 	memset(mcp, 0, sizeof(mcontext_t));
585 
586 	mcp->mc_vers = _MC_VERSION;
587 	mcp->mc_flags = 0;
588 	memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe));
589 	if (flags & GET_MC_CLEAR_RET) {
590 		mcp->mc_gpr[3] = 0;
591 		mcp->mc_gpr[4] = 0;
592 	}
593 
594 	/*
595 	 * This assumes that floating-point context is *not* lazy,
596 	 * so if the thread has used FP there would have been a
597 	 * FP-unavailable exception that would have set things up
598 	 * correctly.
599 	 */
600 	if (pcb->pcb_flags & PCB_FPU) {
601 		KASSERT(td == curthread,
602 			("get_mcontext: fp save not curthread"));
603 		critical_enter();
604 		save_fpu(td);
605 		critical_exit();
606 		mcp->mc_flags |= _MC_FP_VALID;
607 		memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
608 		memcpy(mcp->mc_fpreg, pcb->pcb_fpu.fpr, 32*sizeof(double));
609 	}
610 
611 	/* XXX Altivec context ? */
612 
613 	mcp->mc_len = sizeof(*mcp);
614 
615 	return (0);
616 }
617 
618 int
619 get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
620 {
621 	int error;
622 
623 	error = grab_mcontext(td, mcp, flags);
624 	if (error == 0) {
625 		PROC_LOCK(curthread->td_proc);
626 		mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]);
627 		PROC_UNLOCK(curthread->td_proc);
628 	}
629 
630 	return (error);
631 }
632 
633 int
634 set_mcontext(struct thread *td, const mcontext_t *mcp)
635 {
636 	struct pcb *pcb;
637 	struct trapframe *tf;
638 
639 	pcb = td->td_pcb;
640 	tf = td->td_frame;
641 
642 	if (mcp->mc_vers != _MC_VERSION ||
643 	    mcp->mc_len != sizeof(*mcp))
644 		return (EINVAL);
645 
646 	/*
647 	 * Don't let the user set privileged MSR bits
648 	 */
649 	if ((mcp->mc_srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) {
650 		return (EINVAL);
651 	}
652 
653 	memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame));
654 
655 	if (mcp->mc_flags & _MC_FP_VALID) {
656 		if ((pcb->pcb_flags & PCB_FPU) != PCB_FPU) {
657 			critical_enter();
658 			enable_fpu(td);
659 			critical_exit();
660 		}
661 		memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double));
662 		memcpy(pcb->pcb_fpu.fpr, mcp->mc_fpreg, 32*sizeof(double));
663 	}
664 
665 	/* XXX Altivec context? */
666 
667 	return (0);
668 }
669 
670 void
671 cpu_boot(int howto)
672 {
673 }
674 
675 /*
676  * Shutdown the CPU as much as possible.
677  */
678 void
679 cpu_halt(void)
680 {
681 
682 	OF_exit();
683 }
684 
685 void
686 cpu_idle(void)
687 {
688 	/* Insert code to halt (until next interrupt) for the idle loop */
689 }
690 
691 /*
692  * Set set up registers on exec.
693  */
694 void
695 exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
696 {
697 	struct trapframe	*tf;
698 	struct ps_strings	arginfo;
699 
700 	tf = trapframe(td);
701 	bzero(tf, sizeof *tf);
702 	tf->fixreg[1] = -roundup(-stack + 8, 16);
703 
704 	/*
705 	 * XXX Machine-independent code has already copied arguments and
706 	 * XXX environment to userland.  Get them back here.
707 	 */
708 	(void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo));
709 
710 	/*
711 	 * Set up arguments for _start():
712 	 *	_start(argc, argv, envp, obj, cleanup, ps_strings);
713 	 *
714 	 * Notes:
715 	 *	- obj and cleanup are the auxilliary and termination
716 	 *	  vectors.  They are fixed up by ld.elf_so.
717 	 *	- ps_strings is a NetBSD extention, and will be
718 	 * 	  ignored by executables which are strictly
719 	 *	  compliant with the SVR4 ABI.
720 	 *
721 	 * XXX We have to set both regs and retval here due to different
722 	 * XXX calling convention in trap.c and init_main.c.
723 	 */
724         /*
725          * XXX PG: these get overwritten in the syscall return code.
726          * execve() should return EJUSTRETURN, like it does on NetBSD.
727          * Emulate by setting the syscall return value cells. The
728          * registers still have to be set for init's fork trampoline.
729          */
730         td->td_retval[0] = arginfo.ps_nargvstr;
731         td->td_retval[1] = (register_t)arginfo.ps_argvstr;
732 	tf->fixreg[3] = arginfo.ps_nargvstr;
733 	tf->fixreg[4] = (register_t)arginfo.ps_argvstr;
734 	tf->fixreg[5] = (register_t)arginfo.ps_envstr;
735 	tf->fixreg[6] = 0;			/* auxillary vector */
736 	tf->fixreg[7] = 0;			/* termination vector */
737 	tf->fixreg[8] = (register_t)PS_STRINGS;	/* NetBSD extension */
738 
739 	tf->srr0 = entry;
740 	tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
741 	td->td_pcb->pcb_flags = 0;
742 }
743 
744 #if !defined(DDB)
745 void
746 Debugger(const char *msg)
747 {
748 
749 	printf("Debugger(\"%s\") called.\n", msg);
750 }
751 #endif /* !defined(DDB) */
752 
753 /* XXX: dummy {fill,set}_[fp]regs */
754 int
755 fill_regs(struct thread *td, struct reg *regs)
756 {
757 
758 	return (ENOSYS);
759 }
760 
761 int
762 fill_dbregs(struct thread *td, struct dbreg *dbregs)
763 {
764 
765 	return (ENOSYS);
766 }
767 
768 int
769 fill_fpregs(struct thread *td, struct fpreg *fpregs)
770 {
771 
772 	return (ENOSYS);
773 }
774 
775 int
776 set_regs(struct thread *td, struct reg *regs)
777 {
778 
779 	return (ENOSYS);
780 }
781 
782 int
783 set_dbregs(struct thread *td, struct dbreg *dbregs)
784 {
785 
786 	return (ENOSYS);
787 }
788 
789 int
790 set_fpregs(struct thread *td, struct fpreg *fpregs)
791 {
792 
793 	return (ENOSYS);
794 }
795 
796 int
797 ptrace_set_pc(struct thread *td, unsigned long addr)
798 {
799 
800 	/* XXX: coming soon... */
801 	return (ENOSYS);
802 }
803 
804 int
805 ptrace_single_step(struct thread *td)
806 {
807 
808 	/* XXX: coming soon... */
809 	return (ENOSYS);
810 }
811 
812 /*
813  * Initialise a struct pcpu.
814  */
815 void
816 cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
817 {
818 
819 }
820 
821 /*
822  * kcopy(const void *src, void *dst, size_t len);
823  *
824  * Copy len bytes from src to dst, aborting if we encounter a fatal
825  * page fault.
826  *
827  * kcopy() _must_ save and restore the old fault handler since it is
828  * called by uiomove(), which may be in the path of servicing a non-fatal
829  * page fault.
830  */
831 int
832 kcopy(const void *src, void *dst, size_t len)
833 {
834 	struct thread	*td;
835 	faultbuf	env, *oldfault;
836 	int		rv;
837 
838 	td = PCPU_GET(curthread);
839 	oldfault = td->td_pcb->pcb_onfault;
840 	if ((rv = setfault(env)) != 0) {
841 		td->td_pcb->pcb_onfault = oldfault;
842 		return rv;
843 	}
844 
845 	memcpy(dst, src, len);
846 
847 	td->td_pcb->pcb_onfault = oldfault;
848 	return (0);
849 }
850 
851 void
852 asm_panic(char *pstr)
853 {
854 	panic(pstr);
855 }
856