machdep.c revision 173584
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 173584 2007-11-13 15:47:55Z grehan $");
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("Boot flags requested debugger");
402#endif
403}
404
405void
406bzero(void *buf, size_t len)
407{
408	caddr_t	p;
409
410	p = buf;
411
412	while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) {
413		*p++ = 0;
414		len--;
415	}
416
417	while (len >= sizeof(u_long) * 8) {
418		*(u_long*) p = 0;
419		*((u_long*) p + 1) = 0;
420		*((u_long*) p + 2) = 0;
421		*((u_long*) p + 3) = 0;
422		len -= sizeof(u_long) * 8;
423		*((u_long*) p + 4) = 0;
424		*((u_long*) p + 5) = 0;
425		*((u_long*) p + 6) = 0;
426		*((u_long*) p + 7) = 0;
427		p += sizeof(u_long) * 8;
428	}
429
430	while (len >= sizeof(u_long)) {
431		*(u_long*) p = 0;
432		len -= sizeof(u_long);
433		p += sizeof(u_long);
434	}
435
436	while (len) {
437		*p++ = 0;
438		len--;
439	}
440}
441
442void
443sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
444{
445	struct trapframe *tf;
446	struct sigframe *sfp;
447	struct sigacts *psp;
448	struct sigframe sf;
449	struct thread *td;
450	struct proc *p;
451	int oonstack, rndfsize;
452	int sig;
453	int code;
454
455	td = curthread;
456	p = td->td_proc;
457	PROC_LOCK_ASSERT(p, MA_OWNED);
458	sig = ksi->ksi_signo;
459	code = ksi->ksi_code;
460	psp = p->p_sigacts;
461	mtx_assert(&psp->ps_mtx, MA_OWNED);
462	tf = td->td_frame;
463	oonstack = sigonstack(tf->fixreg[1]);
464
465	rndfsize = ((sizeof(sf) + 15) / 16) * 16;
466
467	CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
468	     catcher, sig);
469
470	/*
471	 * Save user context
472	 */
473	memset(&sf, 0, sizeof(sf));
474	grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0);
475	sf.sf_uc.uc_sigmask = *mask;
476	sf.sf_uc.uc_stack = td->td_sigstk;
477	sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
478	    ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
479
480	sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
481
482	/*
483	 * Allocate and validate space for the signal handler context.
484	 */
485	if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
486	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
487		sfp = (struct sigframe *)(td->td_sigstk.ss_sp +
488		   td->td_sigstk.ss_size - rndfsize);
489	} else {
490		sfp = (struct sigframe *)(tf->fixreg[1] - rndfsize);
491	}
492
493	/*
494	 * Translate the signal if appropriate (Linux emu ?)
495	 */
496	if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
497		sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
498
499	/*
500	 * Save the floating-point state, if necessary, then copy it.
501	 */
502	/* XXX */
503
504	/*
505	 * Set up the registers to return to sigcode.
506	 *
507	 *   r1/sp - sigframe ptr
508	 *   lr    - sig function, dispatched to by blrl in trampoline
509	 *   r3    - sig number
510	 *   r4    - SIGINFO ? &siginfo : exception code
511	 *   r5    - user context
512	 *   srr0  - trampoline function addr
513	 */
514	tf->lr = (register_t)catcher;
515	tf->fixreg[1] = (register_t)sfp;
516	tf->fixreg[FIRSTARG] = sig;
517	tf->fixreg[FIRSTARG+2] = (register_t)&sfp->sf_uc;
518	if (SIGISMEMBER(psp->ps_siginfo, sig)) {
519		/*
520		 * Signal handler installed with SA_SIGINFO.
521		 */
522		tf->fixreg[FIRSTARG+1] = (register_t)&sfp->sf_si;
523
524		/*
525		 * Fill siginfo structure.
526		 */
527		sf.sf_si = ksi->ksi_info;
528		sf.sf_si.si_signo = sig;
529		sf.sf_si.si_addr = (void *) ((tf->exc == EXC_DSI) ?
530		                             tf->dar : tf->srr0);
531	} else {
532		/* Old FreeBSD-style arguments. */
533		tf->fixreg[FIRSTARG+1] = code;
534		tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ?
535		                             tf->dar : tf->srr0;
536	}
537	mtx_unlock(&psp->ps_mtx);
538	PROC_UNLOCK(p);
539
540	tf->srr0 = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode));
541
542	/*
543	 * copy the frame out to userland.
544	 */
545	if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
546		/*
547		 * Process has trashed its stack. Kill it.
548		 */
549		CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp);
550		PROC_LOCK(p);
551		sigexit(td, SIGILL);
552	}
553
554	CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td,
555	     tf->srr0, tf->fixreg[1]);
556
557	PROC_LOCK(p);
558	mtx_lock(&psp->ps_mtx);
559}
560
561int
562sigreturn(struct thread *td, struct sigreturn_args *uap)
563{
564	struct proc *p;
565	ucontext_t uc;
566	int error;
567
568	CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
569
570	if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
571		CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
572		return (EFAULT);
573	}
574
575	error = set_mcontext(td, &uc.uc_mcontext);
576	if (error != 0)
577		return (error);
578
579	p = td->td_proc;
580	PROC_LOCK(p);
581	td->td_sigmask = uc.uc_sigmask;
582	SIG_CANTMASK(td->td_sigmask);
583	signotify(td);
584	PROC_UNLOCK(p);
585
586	CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
587	     td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
588
589	return (EJUSTRETURN);
590}
591
592#ifdef COMPAT_FREEBSD4
593int
594freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
595{
596
597	return sigreturn(td, (struct sigreturn_args *)uap);
598}
599#endif
600
601/*
602 * Construct a PCB from a trapframe. This is called from kdb_trap() where
603 * we want to start a backtrace from the function that caused us to enter
604 * the debugger. We have the context in the trapframe, but base the trace
605 * on the PCB. The PCB doesn't have to be perfect, as long as it contains
606 * enough for a backtrace.
607 */
608void
609makectx(struct trapframe *tf, struct pcb *pcb)
610{
611
612	pcb->pcb_lr = tf->srr0;
613	pcb->pcb_sp = tf->fixreg[1];
614}
615
616/*
617 * get_mcontext/sendsig helper routine that doesn't touch the
618 * proc lock
619 */
620static int
621grab_mcontext(struct thread *td, mcontext_t *mcp, int flags)
622{
623	struct pcb *pcb;
624
625	pcb = td->td_pcb;
626
627	memset(mcp, 0, sizeof(mcontext_t));
628
629	mcp->mc_vers = _MC_VERSION;
630	mcp->mc_flags = 0;
631	memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe));
632	if (flags & GET_MC_CLEAR_RET) {
633		mcp->mc_gpr[3] = 0;
634		mcp->mc_gpr[4] = 0;
635	}
636
637	/*
638	 * This assumes that floating-point context is *not* lazy,
639	 * so if the thread has used FP there would have been a
640	 * FP-unavailable exception that would have set things up
641	 * correctly.
642	 */
643	if (pcb->pcb_flags & PCB_FPU) {
644		KASSERT(td == curthread,
645			("get_mcontext: fp save not curthread"));
646		critical_enter();
647		save_fpu(td);
648		critical_exit();
649		mcp->mc_flags |= _MC_FP_VALID;
650		memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
651		memcpy(mcp->mc_fpreg, pcb->pcb_fpu.fpr, 32*sizeof(double));
652	}
653
654	/* XXX Altivec context ? */
655
656	mcp->mc_len = sizeof(*mcp);
657
658	return (0);
659}
660
661int
662get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
663{
664	int error;
665
666	error = grab_mcontext(td, mcp, flags);
667	if (error == 0) {
668		PROC_LOCK(curthread->td_proc);
669		mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]);
670		PROC_UNLOCK(curthread->td_proc);
671	}
672
673	return (error);
674}
675
676int
677set_mcontext(struct thread *td, const mcontext_t *mcp)
678{
679	struct pcb *pcb;
680	struct trapframe *tf;
681
682	pcb = td->td_pcb;
683	tf = td->td_frame;
684
685	if (mcp->mc_vers != _MC_VERSION ||
686	    mcp->mc_len != sizeof(*mcp))
687		return (EINVAL);
688
689	/*
690	 * Don't let the user set privileged MSR bits
691	 */
692	if ((mcp->mc_srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) {
693		return (EINVAL);
694	}
695
696	memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame));
697
698	if (mcp->mc_flags & _MC_FP_VALID) {
699		if ((pcb->pcb_flags & PCB_FPU) != PCB_FPU) {
700			critical_enter();
701			enable_fpu(td);
702			critical_exit();
703		}
704		memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double));
705		memcpy(pcb->pcb_fpu.fpr, mcp->mc_fpreg, 32*sizeof(double));
706	}
707
708	/* XXX Altivec context? */
709
710	return (0);
711}
712
713void
714cpu_boot(int howto)
715{
716}
717
718void
719cpu_initclocks(void)
720{
721
722	decr_tc_init();
723}
724
725/* Get current clock frequency for the given cpu id. */
726int
727cpu_est_clockrate(int cpu_id, uint64_t *rate)
728{
729
730	return (ENXIO);
731}
732
733/*
734 * Shutdown the CPU as much as possible.
735 */
736void
737cpu_halt(void)
738{
739
740	OF_exit();
741}
742
743void
744cpu_idle(void)
745{
746	/* TODO: Insert code to halt (until next interrupt) */
747
748#ifdef INVARIANTS
749	if ((mfmsr() & PSL_EE) != PSL_EE) {
750		struct thread *td = curthread;
751		printf("td msr %x\n", td->td_md.md_saved_msr);
752		panic("ints disabled in idleproc!");
753	}
754#endif
755}
756
757/*
758 * Set set up registers on exec.
759 */
760void
761exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
762{
763	struct trapframe	*tf;
764	struct ps_strings	arginfo;
765
766	tf = trapframe(td);
767	bzero(tf, sizeof *tf);
768	tf->fixreg[1] = -roundup(-stack + 8, 16);
769
770	/*
771	 * XXX Machine-independent code has already copied arguments and
772	 * XXX environment to userland.  Get them back here.
773	 */
774	(void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo));
775
776	/*
777	 * Set up arguments for _start():
778	 *	_start(argc, argv, envp, obj, cleanup, ps_strings);
779	 *
780	 * Notes:
781	 *	- obj and cleanup are the auxilliary and termination
782	 *	  vectors.  They are fixed up by ld.elf_so.
783	 *	- ps_strings is a NetBSD extention, and will be
784	 * 	  ignored by executables which are strictly
785	 *	  compliant with the SVR4 ABI.
786	 *
787	 * XXX We have to set both regs and retval here due to different
788	 * XXX calling convention in trap.c and init_main.c.
789	 */
790        /*
791         * XXX PG: these get overwritten in the syscall return code.
792         * execve() should return EJUSTRETURN, like it does on NetBSD.
793         * Emulate by setting the syscall return value cells. The
794         * registers still have to be set for init's fork trampoline.
795         */
796        td->td_retval[0] = arginfo.ps_nargvstr;
797        td->td_retval[1] = (register_t)arginfo.ps_argvstr;
798	tf->fixreg[3] = arginfo.ps_nargvstr;
799	tf->fixreg[4] = (register_t)arginfo.ps_argvstr;
800	tf->fixreg[5] = (register_t)arginfo.ps_envstr;
801	tf->fixreg[6] = 0;			/* auxillary vector */
802	tf->fixreg[7] = 0;			/* termination vector */
803	tf->fixreg[8] = (register_t)PS_STRINGS;	/* NetBSD extension */
804
805	tf->srr0 = entry;
806	tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
807	td->td_pcb->pcb_flags = 0;
808}
809
810int
811fill_regs(struct thread *td, struct reg *regs)
812{
813	struct trapframe *tf;
814
815	tf = td->td_frame;
816	memcpy(regs, tf, sizeof(struct reg));
817
818	return (0);
819}
820
821int
822fill_dbregs(struct thread *td, struct dbreg *dbregs)
823{
824	/* No debug registers on PowerPC */
825	return (ENOSYS);
826}
827
828int
829fill_fpregs(struct thread *td, struct fpreg *fpregs)
830{
831	struct pcb *pcb;
832
833	pcb = td->td_pcb;
834
835	if ((pcb->pcb_flags & PCB_FPU) == 0)
836		memset(fpregs, 0, sizeof(struct fpreg));
837	else
838		memcpy(fpregs, &pcb->pcb_fpu, sizeof(struct fpreg));
839
840	return (0);
841}
842
843int
844set_regs(struct thread *td, struct reg *regs)
845{
846	struct trapframe *tf;
847
848	tf = td->td_frame;
849	memcpy(tf, regs, sizeof(struct reg));
850
851	return (0);
852}
853
854int
855set_dbregs(struct thread *td, struct dbreg *dbregs)
856{
857	/* No debug registers on PowerPC */
858	return (ENOSYS);
859}
860
861int
862set_fpregs(struct thread *td, struct fpreg *fpregs)
863{
864	struct pcb *pcb;
865
866	pcb = td->td_pcb;
867	if ((pcb->pcb_flags & PCB_FPU) == 0)
868		enable_fpu(td);
869	memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg));
870
871	return (0);
872}
873
874int
875ptrace_set_pc(struct thread *td, unsigned long addr)
876{
877	struct trapframe *tf;
878
879	tf = td->td_frame;
880	tf->srr0 = (register_t)addr;
881
882	return (0);
883}
884
885int
886ptrace_single_step(struct thread *td)
887{
888	struct trapframe *tf;
889
890	tf = td->td_frame;
891	tf->srr1 |= PSL_SE;
892
893	return (0);
894}
895
896int
897ptrace_clear_single_step(struct thread *td)
898{
899	struct trapframe *tf;
900
901	tf = td->td_frame;
902	tf->srr1 &= ~PSL_SE;
903
904	return (0);
905}
906
907/*
908 * Initialise a struct pcpu.
909 */
910void
911cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
912{
913
914}
915
916void
917spinlock_enter(void)
918{
919	struct thread *td;
920
921	td = curthread;
922	if (td->td_md.md_spinlock_count == 0)
923		td->td_md.md_saved_msr = intr_disable();
924	td->td_md.md_spinlock_count++;
925	critical_enter();
926}
927
928void
929spinlock_exit(void)
930{
931	struct thread *td;
932
933	td = curthread;
934	critical_exit();
935	td->td_md.md_spinlock_count--;
936	if (td->td_md.md_spinlock_count == 0)
937		intr_restore(td->td_md.md_saved_msr);
938}
939
940/*
941 * kcopy(const void *src, void *dst, size_t len);
942 *
943 * Copy len bytes from src to dst, aborting if we encounter a fatal
944 * page fault.
945 *
946 * kcopy() _must_ save and restore the old fault handler since it is
947 * called by uiomove(), which may be in the path of servicing a non-fatal
948 * page fault.
949 */
950int
951kcopy(const void *src, void *dst, size_t len)
952{
953	struct thread	*td;
954	faultbuf	env, *oldfault;
955	int		rv;
956
957	td = PCPU_GET(curthread);
958	oldfault = td->td_pcb->pcb_onfault;
959	if ((rv = setfault(env)) != 0) {
960		td->td_pcb->pcb_onfault = oldfault;
961		return rv;
962	}
963
964	memcpy(dst, src, len);
965
966	td->td_pcb->pcb_onfault = oldfault;
967	return (0);
968}
969
970void
971asm_panic(char *pstr)
972{
973	panic(pstr);
974}
975
976int db_trap_glue(struct trapframe *);		/* Called from trap_subr.S */
977
978int
979db_trap_glue(struct trapframe *frame)
980{
981	if (!(frame->srr1 & PSL_PR)
982	    && (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC
983		|| (frame->exc == EXC_PGM
984		    && (frame->srr1 & 0x20000))
985		|| frame->exc == EXC_BPT
986		|| frame->exc == EXC_DSI)) {
987		int type = frame->exc;
988		if (type == EXC_PGM && (frame->srr1 & 0x20000)) {
989			type = T_BREAKPOINT;
990		}
991		return (kdb_trap(type, 0, frame));
992	}
993
994	return (0);
995}
996