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