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