]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/powerpc/powerpc/exec_machdep.c
Import tzdata 2018d
[FreeBSD/FreeBSD.git] / sys / powerpc / powerpc / exec_machdep.c
1 /*-
2  * SPDX-License-Identifier: BSD-4-Clause AND BSD-2-Clause-FreeBSD
3  *
4  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5  * Copyright (C) 1995, 1996 TooLs GmbH.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by TooLs GmbH.
19  * 4. The name of TooLs GmbH may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 /*-
34  * Copyright (C) 2001 Benno Rice
35  * All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  *
46  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
47  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
52  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
53  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
54  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
55  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56  *      $NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $
57  */
58
59 #include <sys/cdefs.h>
60 __FBSDID("$FreeBSD$");
61
62 #include "opt_compat.h"
63 #include "opt_fpu_emu.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/exec.h>
74 #include <sys/imgact.h>
75 #include <sys/kernel.h>
76 #include <sys/ktr.h>
77 #include <sys/lock.h>
78 #include <sys/malloc.h>
79 #include <sys/mutex.h>
80 #include <sys/signalvar.h>
81 #include <sys/syscallsubr.h>
82 #include <sys/syscall.h>
83 #include <sys/sysent.h>
84 #include <sys/sysproto.h>
85 #include <sys/ucontext.h>
86 #include <sys/uio.h>
87
88 #include <machine/altivec.h>
89 #include <machine/cpu.h>
90 #include <machine/elf.h>
91 #include <machine/fpu.h>
92 #include <machine/pcb.h>
93 #include <machine/reg.h>
94 #include <machine/sigframe.h>
95 #include <machine/trap.h>
96 #include <machine/vmparam.h>
97
98 #ifdef FPU_EMU
99 #include <powerpc/fpu/fpu_extern.h>
100 #endif
101
102 #ifdef COMPAT_FREEBSD32
103 #include <compat/freebsd32/freebsd32_signal.h>
104 #include <compat/freebsd32/freebsd32_util.h>
105 #include <compat/freebsd32/freebsd32_proto.h>
106
107 typedef struct __ucontext32 {
108         sigset_t                uc_sigmask;
109         mcontext32_t            uc_mcontext;
110         uint32_t                uc_link;
111         struct sigaltstack32    uc_stack;
112         uint32_t                uc_flags;
113         uint32_t                __spare__[4];
114 } ucontext32_t;
115
116 struct sigframe32 {
117         ucontext32_t            sf_uc;
118         struct siginfo32        sf_si;
119 };
120
121 static int      grab_mcontext32(struct thread *td, mcontext32_t *, int flags);
122 #endif
123
124 static int      grab_mcontext(struct thread *, mcontext_t *, int);
125
126 void
127 sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
128 {
129         struct trapframe *tf;
130         struct sigacts *psp;
131         struct sigframe sf;
132         struct thread *td;
133         struct proc *p;
134         #ifdef COMPAT_FREEBSD32
135         struct siginfo32 siginfo32;
136         struct sigframe32 sf32;
137         #endif
138         size_t sfpsize;
139         caddr_t sfp, usfp;
140         int oonstack, rndfsize;
141         int sig;
142         int code;
143
144         td = curthread;
145         p = td->td_proc;
146         PROC_LOCK_ASSERT(p, MA_OWNED);
147
148         psp = p->p_sigacts;
149         mtx_assert(&psp->ps_mtx, MA_OWNED);
150         tf = td->td_frame;
151         oonstack = sigonstack(tf->fixreg[1]);
152
153         /*
154          * Fill siginfo structure.
155          */
156         ksi->ksi_info.si_signo = ksi->ksi_signo;
157         ksi->ksi_info.si_addr =
158             (void *)((tf->exc == EXC_DSI || tf->exc == EXC_DSE) ? 
159             tf->dar : tf->srr0);
160
161         #ifdef COMPAT_FREEBSD32
162         if (SV_PROC_FLAG(p, SV_ILP32)) {
163                 siginfo_to_siginfo32(&ksi->ksi_info, &siginfo32);
164                 sig = siginfo32.si_signo;
165                 code = siginfo32.si_code;
166                 sfp = (caddr_t)&sf32;
167                 sfpsize = sizeof(sf32);
168                 rndfsize = roundup(sizeof(sf32), 16);
169
170                 /*
171                  * Save user context
172                  */
173
174                 memset(&sf32, 0, sizeof(sf32));
175                 grab_mcontext32(td, &sf32.sf_uc.uc_mcontext, 0);
176
177                 sf32.sf_uc.uc_sigmask = *mask;
178                 sf32.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
179                 sf32.sf_uc.uc_stack.ss_size = (uint32_t)td->td_sigstk.ss_size;
180                 sf32.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
181                     ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
182
183                 sf32.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
184         } else {
185         #endif
186                 sig = ksi->ksi_signo;
187                 code = ksi->ksi_code;
188                 sfp = (caddr_t)&sf;
189                 sfpsize = sizeof(sf);
190                 #ifdef __powerpc64__
191                 /*
192                  * 64-bit PPC defines a 288 byte scratch region
193                  * below the stack.
194                  */
195                 rndfsize = 288 + roundup(sizeof(sf), 48);
196                 #else
197                 rndfsize = roundup(sizeof(sf), 16);
198                 #endif
199
200                 /*
201                  * Save user context
202                  */
203
204                 memset(&sf, 0, sizeof(sf));
205                 grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0);
206
207                 sf.sf_uc.uc_sigmask = *mask;
208                 sf.sf_uc.uc_stack = td->td_sigstk;
209                 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
210                     ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
211
212                 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
213         #ifdef COMPAT_FREEBSD32
214         }
215         #endif
216
217         CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
218              catcher, sig);
219
220         /*
221          * Allocate and validate space for the signal handler context.
222          */
223         if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
224             SIGISMEMBER(psp->ps_sigonstack, sig)) {
225                 usfp = (void *)(((uintptr_t)td->td_sigstk.ss_sp +
226                    td->td_sigstk.ss_size - rndfsize) & ~0xFul);
227         } else {
228                 usfp = (void *)((tf->fixreg[1] - rndfsize) & ~0xFul);
229         }
230
231         /*
232          * Save the floating-point state, if necessary, then copy it.
233          */
234         /* XXX */
235
236         /*
237          * Set up the registers to return to sigcode.
238          *
239          *   r1/sp - sigframe ptr
240          *   lr    - sig function, dispatched to by blrl in trampoline
241          *   r3    - sig number
242          *   r4    - SIGINFO ? &siginfo : exception code
243          *   r5    - user context
244          *   srr0  - trampoline function addr
245          */
246         tf->lr = (register_t)catcher;
247         tf->fixreg[1] = (register_t)usfp;
248         tf->fixreg[FIRSTARG] = sig;
249         #ifdef COMPAT_FREEBSD32
250         tf->fixreg[FIRSTARG+2] = (register_t)usfp +
251             ((SV_PROC_FLAG(p, SV_ILP32)) ?
252             offsetof(struct sigframe32, sf_uc) :
253             offsetof(struct sigframe, sf_uc));
254         #else
255         tf->fixreg[FIRSTARG+2] = (register_t)usfp +
256             offsetof(struct sigframe, sf_uc);
257         #endif
258         if (SIGISMEMBER(psp->ps_siginfo, sig)) {
259                 /*
260                  * Signal handler installed with SA_SIGINFO.
261                  */
262                 #ifdef COMPAT_FREEBSD32
263                 if (SV_PROC_FLAG(p, SV_ILP32)) {
264                         sf32.sf_si = siginfo32;
265                         tf->fixreg[FIRSTARG+1] = (register_t)usfp +
266                             offsetof(struct sigframe32, sf_si);
267                         sf32.sf_si = siginfo32;
268                 } else  {
269                 #endif
270                         tf->fixreg[FIRSTARG+1] = (register_t)usfp +
271                             offsetof(struct sigframe, sf_si);
272                         sf.sf_si = ksi->ksi_info;
273                 #ifdef COMPAT_FREEBSD32
274                 }
275                 #endif
276         } else {
277                 /* Old FreeBSD-style arguments. */
278                 tf->fixreg[FIRSTARG+1] = code;
279                 tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? 
280                     tf->dar : tf->srr0;
281         }
282         mtx_unlock(&psp->ps_mtx);
283         PROC_UNLOCK(p);
284
285         tf->srr0 = (register_t)p->p_sysent->sv_sigcode_base;
286
287         /*
288          * copy the frame out to userland.
289          */
290         if (copyout(sfp, usfp, sfpsize) != 0) {
291                 /*
292                  * Process has trashed its stack. Kill it.
293                  */
294                 CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp);
295                 PROC_LOCK(p);
296                 sigexit(td, SIGILL);
297         }
298
299         CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td,
300              tf->srr0, tf->fixreg[1]);
301
302         PROC_LOCK(p);
303         mtx_lock(&psp->ps_mtx);
304 }
305
306 int
307 sys_sigreturn(struct thread *td, struct sigreturn_args *uap)
308 {
309         ucontext_t uc;
310         int error;
311
312         CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
313
314         if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
315                 CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
316                 return (EFAULT);
317         }
318
319         error = set_mcontext(td, &uc.uc_mcontext);
320         if (error != 0)
321                 return (error);
322
323         kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
324
325         CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
326              td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
327
328         return (EJUSTRETURN);
329 }
330
331 #ifdef COMPAT_FREEBSD4
332 int
333 freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
334 {
335
336         return sys_sigreturn(td, (struct sigreturn_args *)uap);
337 }
338 #endif
339
340 /*
341  * Construct a PCB from a trapframe. This is called from kdb_trap() where
342  * we want to start a backtrace from the function that caused us to enter
343  * the debugger. We have the context in the trapframe, but base the trace
344  * on the PCB. The PCB doesn't have to be perfect, as long as it contains
345  * enough for a backtrace.
346  */
347 void
348 makectx(struct trapframe *tf, struct pcb *pcb)
349 {
350
351         pcb->pcb_lr = tf->srr0;
352         pcb->pcb_sp = tf->fixreg[1];
353 }
354
355 /*
356  * get_mcontext/sendsig helper routine that doesn't touch the
357  * proc lock
358  */
359 static int
360 grab_mcontext(struct thread *td, mcontext_t *mcp, int flags)
361 {
362         struct pcb *pcb;
363         int i;
364
365         pcb = td->td_pcb;
366
367         memset(mcp, 0, sizeof(mcontext_t));
368
369         mcp->mc_vers = _MC_VERSION;
370         mcp->mc_flags = 0;
371         memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe));
372         if (flags & GET_MC_CLEAR_RET) {
373                 mcp->mc_gpr[3] = 0;
374                 mcp->mc_gpr[4] = 0;
375         }
376
377         /*
378          * This assumes that floating-point context is *not* lazy,
379          * so if the thread has used FP there would have been a
380          * FP-unavailable exception that would have set things up
381          * correctly.
382          */
383         if (pcb->pcb_flags & PCB_FPREGS) {
384                 if (pcb->pcb_flags & PCB_FPU) {
385                         KASSERT(td == curthread,
386                                 ("get_mcontext: fp save not curthread"));
387                         critical_enter();
388                         save_fpu(td);
389                         critical_exit();
390                 }
391                 mcp->mc_flags |= _MC_FP_VALID;
392                 memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
393                 for (i = 0; i < 32; i++)
394                         memcpy(&mcp->mc_fpreg[i], &pcb->pcb_fpu.fpr[i].fpr,
395                             sizeof(double));
396         }
397
398         if (pcb->pcb_flags & PCB_VSX) {
399                 for (i = 0; i < 32; i++)
400                         memcpy(&mcp->mc_vsxfpreg[i],
401                             &pcb->pcb_fpu.fpr[i].vsr[2], sizeof(double));
402         }
403
404         /*
405          * Repeat for Altivec context
406          */
407
408         if (pcb->pcb_flags & PCB_VEC) {
409                 KASSERT(td == curthread,
410                         ("get_mcontext: fp save not curthread"));
411                 critical_enter();
412                 save_vec(td);
413                 critical_exit();
414                 mcp->mc_flags |= _MC_AV_VALID;
415                 mcp->mc_vscr  = pcb->pcb_vec.vscr;
416                 mcp->mc_vrsave =  pcb->pcb_vec.vrsave;
417                 memcpy(mcp->mc_avec, pcb->pcb_vec.vr, sizeof(mcp->mc_avec));
418         }
419
420         mcp->mc_len = sizeof(*mcp);
421
422         return (0);
423 }
424
425 int
426 get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
427 {
428         int error;
429
430         error = grab_mcontext(td, mcp, flags);
431         if (error == 0) {
432                 PROC_LOCK(curthread->td_proc);
433                 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]);
434                 PROC_UNLOCK(curthread->td_proc);
435         }
436
437         return (error);
438 }
439
440 int
441 set_mcontext(struct thread *td, mcontext_t *mcp)
442 {
443         struct pcb *pcb;
444         struct trapframe *tf;
445         register_t tls;
446         int i;
447
448         pcb = td->td_pcb;
449         tf = td->td_frame;
450
451         if (mcp->mc_vers != _MC_VERSION || mcp->mc_len != sizeof(*mcp))
452                 return (EINVAL);
453
454         /*
455          * Don't let the user set privileged MSR bits
456          */
457         if ((mcp->mc_srr1 & psl_userstatic) != (tf->srr1 & psl_userstatic)) {
458                 return (EINVAL);
459         }
460
461         /* Copy trapframe, preserving TLS pointer across context change */
462         if (SV_PROC_FLAG(td->td_proc, SV_LP64))
463                 tls = tf->fixreg[13];
464         else
465                 tls = tf->fixreg[2];
466         memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame));
467         if (SV_PROC_FLAG(td->td_proc, SV_LP64))
468                 tf->fixreg[13] = tls;
469         else
470                 tf->fixreg[2] = tls;
471
472         if (mcp->mc_flags & _MC_FP_VALID) {
473                 /* enable_fpu() will happen lazily on a fault */
474                 pcb->pcb_flags |= PCB_FPREGS;
475                 memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double));
476                 bzero(pcb->pcb_fpu.fpr, sizeof(pcb->pcb_fpu.fpr));
477                 for (i = 0; i < 32; i++) {
478                         memcpy(&pcb->pcb_fpu.fpr[i].fpr, &mcp->mc_fpreg[i],
479                             sizeof(double));
480                         memcpy(&pcb->pcb_fpu.fpr[i].vsr[2],
481                             &mcp->mc_vsxfpreg[i], sizeof(double));
482                 }
483         }
484
485         if (mcp->mc_flags & _MC_AV_VALID) {
486                 if ((pcb->pcb_flags & PCB_VEC) != PCB_VEC) {
487                         critical_enter();
488                         enable_vec(td);
489                         critical_exit();
490                 }
491                 pcb->pcb_vec.vscr = mcp->mc_vscr;
492                 pcb->pcb_vec.vrsave = mcp->mc_vrsave;
493                 memcpy(pcb->pcb_vec.vr, mcp->mc_avec, sizeof(mcp->mc_avec));
494         }
495
496         return (0);
497 }
498
499 /*
500  * Set set up registers on exec.
501  */
502 void
503 exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
504 {
505         struct trapframe        *tf;
506         register_t              argc;
507
508         tf = trapframe(td);
509         bzero(tf, sizeof *tf);
510         #ifdef __powerpc64__
511         tf->fixreg[1] = -roundup(-stack + 48, 16);
512         #else
513         tf->fixreg[1] = -roundup(-stack + 8, 16);
514         #endif
515
516         /*
517          * Set up arguments for _start():
518          *      _start(argc, argv, envp, obj, cleanup, ps_strings);
519          *
520          * Notes:
521          *      - obj and cleanup are the auxilliary and termination
522          *        vectors.  They are fixed up by ld.elf_so.
523          *      - ps_strings is a NetBSD extention, and will be
524          *        ignored by executables which are strictly
525          *        compliant with the SVR4 ABI.
526          */
527
528         /* Collect argc from the user stack */
529         argc = fuword((void *)stack);
530
531         tf->fixreg[3] = argc;
532         tf->fixreg[4] = stack + sizeof(register_t);
533         tf->fixreg[5] = stack + (2 + argc)*sizeof(register_t);
534         tf->fixreg[6] = 0;                              /* auxillary vector */
535         tf->fixreg[7] = 0;                              /* termination vector */
536         tf->fixreg[8] = (register_t)imgp->ps_strings;   /* NetBSD extension */
537
538         tf->srr0 = imgp->entry_addr;
539         #ifdef __powerpc64__
540         tf->fixreg[12] = imgp->entry_addr;
541         #endif
542         tf->srr1 = psl_userset | PSL_FE_DFLT;
543         td->td_pcb->pcb_flags = 0;
544 }
545
546 #ifdef COMPAT_FREEBSD32
547 void
548 ppc32_setregs(struct thread *td, struct image_params *imgp, u_long stack)
549 {
550         struct trapframe        *tf;
551         uint32_t                argc;
552
553         tf = trapframe(td);
554         bzero(tf, sizeof *tf);
555         tf->fixreg[1] = -roundup(-stack + 8, 16);
556
557         argc = fuword32((void *)stack);
558
559         tf->fixreg[3] = argc;
560         tf->fixreg[4] = stack + sizeof(uint32_t);
561         tf->fixreg[5] = stack + (2 + argc)*sizeof(uint32_t);
562         tf->fixreg[6] = 0;                              /* auxillary vector */
563         tf->fixreg[7] = 0;                              /* termination vector */
564         tf->fixreg[8] = (register_t)imgp->ps_strings;   /* NetBSD extension */
565
566         tf->srr0 = imgp->entry_addr;
567         tf->srr1 = psl_userset32 | PSL_FE_DFLT;
568         td->td_pcb->pcb_flags = 0;
569 }
570 #endif
571
572 int
573 fill_regs(struct thread *td, struct reg *regs)
574 {
575         struct trapframe *tf;
576
577         tf = td->td_frame;
578         memcpy(regs, tf, sizeof(struct reg));
579
580         return (0);
581 }
582
583 int
584 fill_dbregs(struct thread *td, struct dbreg *dbregs)
585 {
586         /* No debug registers on PowerPC */
587         return (ENOSYS);
588 }
589
590 int
591 fill_fpregs(struct thread *td, struct fpreg *fpregs)
592 {
593         struct pcb *pcb;
594         int i;
595
596         pcb = td->td_pcb;
597
598         if ((pcb->pcb_flags & PCB_FPREGS) == 0)
599                 memset(fpregs, 0, sizeof(struct fpreg));
600         else {
601                 memcpy(&fpregs->fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
602                 for (i = 0; i < 32; i++)
603                         memcpy(&fpregs->fpreg[i], &pcb->pcb_fpu.fpr[i].fpr,
604                             sizeof(double));
605         }
606
607         return (0);
608 }
609
610 int
611 set_regs(struct thread *td, struct reg *regs)
612 {
613         struct trapframe *tf;
614
615         tf = td->td_frame;
616         memcpy(tf, regs, sizeof(struct reg));
617         
618         return (0);
619 }
620
621 int
622 set_dbregs(struct thread *td, struct dbreg *dbregs)
623 {
624         /* No debug registers on PowerPC */
625         return (ENOSYS);
626 }
627
628 int
629 set_fpregs(struct thread *td, struct fpreg *fpregs)
630 {
631         struct pcb *pcb;
632         int i;
633
634         pcb = td->td_pcb;
635         pcb->pcb_flags |= PCB_FPREGS;
636         memcpy(&pcb->pcb_fpu.fpscr, &fpregs->fpscr, sizeof(double));
637         for (i = 0; i < 32; i++) {
638                 memcpy(&pcb->pcb_fpu.fpr[i].fpr, &fpregs->fpreg[i],
639                     sizeof(double));
640         }
641
642         return (0);
643 }
644
645 #ifdef COMPAT_FREEBSD32
646 int
647 set_regs32(struct thread *td, struct reg32 *regs)
648 {
649         struct trapframe *tf;
650         int i;
651
652         tf = td->td_frame;
653         for (i = 0; i < 32; i++)
654                 tf->fixreg[i] = regs->fixreg[i];
655         tf->lr = regs->lr;
656         tf->cr = regs->cr;
657         tf->xer = regs->xer;
658         tf->ctr = regs->ctr;
659         tf->srr0 = regs->pc;
660
661         return (0);
662 }
663
664 int
665 fill_regs32(struct thread *td, struct reg32 *regs)
666 {
667         struct trapframe *tf;
668         int i;
669
670         tf = td->td_frame;
671         for (i = 0; i < 32; i++)
672                 regs->fixreg[i] = tf->fixreg[i];
673         regs->lr = tf->lr;
674         regs->cr = tf->cr;
675         regs->xer = tf->xer;
676         regs->ctr = tf->ctr;
677         regs->pc = tf->srr0;
678
679         return (0);
680 }
681
682 static int
683 grab_mcontext32(struct thread *td, mcontext32_t *mcp, int flags)
684 {
685         mcontext_t mcp64;
686         int i, error;
687
688         error = grab_mcontext(td, &mcp64, flags);
689         if (error != 0)
690                 return (error);
691         
692         mcp->mc_vers = mcp64.mc_vers;
693         mcp->mc_flags = mcp64.mc_flags;
694         mcp->mc_onstack = mcp64.mc_onstack;
695         mcp->mc_len = mcp64.mc_len;
696         memcpy(mcp->mc_avec,mcp64.mc_avec,sizeof(mcp64.mc_avec));
697         memcpy(mcp->mc_av,mcp64.mc_av,sizeof(mcp64.mc_av));
698         for (i = 0; i < 42; i++)
699                 mcp->mc_frame[i] = mcp64.mc_frame[i];
700         memcpy(mcp->mc_fpreg,mcp64.mc_fpreg,sizeof(mcp64.mc_fpreg));
701         memcpy(mcp->mc_vsxfpreg,mcp64.mc_vsxfpreg,sizeof(mcp64.mc_vsxfpreg));
702
703         return (0);
704 }
705
706 static int
707 get_mcontext32(struct thread *td, mcontext32_t *mcp, int flags)
708 {
709         int error;
710
711         error = grab_mcontext32(td, mcp, flags);
712         if (error == 0) {
713                 PROC_LOCK(curthread->td_proc);
714                 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]);
715                 PROC_UNLOCK(curthread->td_proc);
716         }
717
718         return (error);
719 }
720
721 static int
722 set_mcontext32(struct thread *td, mcontext32_t *mcp)
723 {
724         mcontext_t mcp64;
725         int i, error;
726
727         mcp64.mc_vers = mcp->mc_vers;
728         mcp64.mc_flags = mcp->mc_flags;
729         mcp64.mc_onstack = mcp->mc_onstack;
730         mcp64.mc_len = mcp->mc_len;
731         memcpy(mcp64.mc_avec,mcp->mc_avec,sizeof(mcp64.mc_avec));
732         memcpy(mcp64.mc_av,mcp->mc_av,sizeof(mcp64.mc_av));
733         for (i = 0; i < 42; i++)
734                 mcp64.mc_frame[i] = mcp->mc_frame[i];
735         mcp64.mc_srr1 |= (td->td_frame->srr1 & 0xFFFFFFFF00000000ULL);
736         memcpy(mcp64.mc_fpreg,mcp->mc_fpreg,sizeof(mcp64.mc_fpreg));
737         memcpy(mcp64.mc_vsxfpreg,mcp->mc_vsxfpreg,sizeof(mcp64.mc_vsxfpreg));
738
739         error = set_mcontext(td, &mcp64);
740
741         return (error);
742 }
743 #endif
744
745 #ifdef COMPAT_FREEBSD32
746 int
747 freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap)
748 {
749         ucontext32_t uc;
750         int error;
751
752         CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
753
754         if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
755                 CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
756                 return (EFAULT);
757         }
758
759         error = set_mcontext32(td, &uc.uc_mcontext);
760         if (error != 0)
761                 return (error);
762
763         kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
764
765         CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
766              td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
767
768         return (EJUSTRETURN);
769 }
770
771 /*
772  * The first two fields of a ucontext_t are the signal mask and the machine
773  * context.  The next field is uc_link; we want to avoid destroying the link
774  * when copying out contexts.
775  */
776 #define UC32_COPY_SIZE  offsetof(ucontext32_t, uc_link)
777
778 int
779 freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap)
780 {
781         ucontext32_t uc;
782         int ret;
783
784         if (uap->ucp == NULL)
785                 ret = EINVAL;
786         else {
787                 get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
788                 PROC_LOCK(td->td_proc);
789                 uc.uc_sigmask = td->td_sigmask;
790                 PROC_UNLOCK(td->td_proc);
791                 ret = copyout(&uc, uap->ucp, UC32_COPY_SIZE);
792         }
793         return (ret);
794 }
795
796 int
797 freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap)
798 {
799         ucontext32_t uc;
800         int ret;        
801
802         if (uap->ucp == NULL)
803                 ret = EINVAL;
804         else {
805                 ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE);
806                 if (ret == 0) {
807                         ret = set_mcontext32(td, &uc.uc_mcontext);
808                         if (ret == 0) {
809                                 kern_sigprocmask(td, SIG_SETMASK,
810                                     &uc.uc_sigmask, NULL, 0);
811                         }
812                 }
813         }
814         return (ret == 0 ? EJUSTRETURN : ret);
815 }
816
817 int
818 freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
819 {
820         ucontext32_t uc;
821         int ret;
822
823         if (uap->oucp == NULL || uap->ucp == NULL)
824                 ret = EINVAL;
825         else {
826                 get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
827                 PROC_LOCK(td->td_proc);
828                 uc.uc_sigmask = td->td_sigmask;
829                 PROC_UNLOCK(td->td_proc);
830                 ret = copyout(&uc, uap->oucp, UC32_COPY_SIZE);
831                 if (ret == 0) {
832                         ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE);
833                         if (ret == 0) {
834                                 ret = set_mcontext32(td, &uc.uc_mcontext);
835                                 if (ret == 0) {
836                                         kern_sigprocmask(td, SIG_SETMASK,
837                                             &uc.uc_sigmask, NULL, 0);
838                                 }
839                         }
840                 }
841         }
842         return (ret == 0 ? EJUSTRETURN : ret);
843 }
844
845 #endif
846
847 void
848 cpu_set_syscall_retval(struct thread *td, int error)
849 {
850         struct proc *p;
851         struct trapframe *tf;
852         int fixup;
853
854         if (error == EJUSTRETURN)
855                 return;
856
857         p = td->td_proc;
858         tf = td->td_frame;
859
860         if (tf->fixreg[0] == SYS___syscall &&
861             (SV_PROC_FLAG(p, SV_ILP32))) {
862                 int code = tf->fixreg[FIRSTARG + 1];
863                 if (p->p_sysent->sv_mask)
864                         code &= p->p_sysent->sv_mask;
865                 fixup = (
866 #if defined(COMPAT_FREEBSD6) && defined(SYS_freebsd6_lseek)
867                     code != SYS_freebsd6_lseek &&
868 #endif
869                     code != SYS_lseek) ?  1 : 0;
870         } else
871                 fixup = 0;
872
873         switch (error) {
874         case 0:
875                 if (fixup) {
876                         /*
877                          * 64-bit return, 32-bit syscall. Fixup byte order
878                          */
879                         tf->fixreg[FIRSTARG] = 0;
880                         tf->fixreg[FIRSTARG + 1] = td->td_retval[0];
881                 } else {
882                         tf->fixreg[FIRSTARG] = td->td_retval[0];
883                         tf->fixreg[FIRSTARG + 1] = td->td_retval[1];
884                 }
885                 tf->cr &= ~0x10000000;          /* Unset summary overflow */
886                 break;
887         case ERESTART:
888                 /*
889                  * Set user's pc back to redo the system call.
890                  */
891                 tf->srr0 -= 4;
892                 break;
893         default:
894                 tf->fixreg[FIRSTARG] = SV_ABI_ERRNO(p, error);
895                 tf->cr |= 0x10000000;           /* Set summary overflow */
896                 break;
897         }
898 }
899
900 /*
901  * Threading functions
902  */
903 void
904 cpu_thread_exit(struct thread *td)
905 {
906 }
907
908 void
909 cpu_thread_clean(struct thread *td)
910 {
911 }
912
913 void
914 cpu_thread_alloc(struct thread *td)
915 {
916         struct pcb *pcb;
917
918         pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE -
919             sizeof(struct pcb)) & ~0x2fUL);
920         td->td_pcb = pcb;
921         td->td_frame = (struct trapframe *)pcb - 1;
922 }
923
924 void
925 cpu_thread_free(struct thread *td)
926 {
927 }
928
929 int
930 cpu_set_user_tls(struct thread *td, void *tls_base)
931 {
932
933         if (SV_PROC_FLAG(td->td_proc, SV_LP64))
934                 td->td_frame->fixreg[13] = (register_t)tls_base + 0x7010;
935         else
936                 td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008;
937         return (0);
938 }
939
940 void
941 cpu_copy_thread(struct thread *td, struct thread *td0)
942 {
943         struct pcb *pcb2;
944         struct trapframe *tf;
945         struct callframe *cf;
946
947         pcb2 = td->td_pcb;
948
949         /* Copy the upcall pcb */
950         bcopy(td0->td_pcb, pcb2, sizeof(*pcb2));
951
952         /* Create a stack for the new thread */
953         tf = td->td_frame;
954         bcopy(td0->td_frame, tf, sizeof(struct trapframe));
955         tf->fixreg[FIRSTARG] = 0;
956         tf->fixreg[FIRSTARG + 1] = 0;
957         tf->cr &= ~0x10000000;
958
959         /* Set registers for trampoline to user mode. */
960         cf = (struct callframe *)tf - 1;
961         memset(cf, 0, sizeof(struct callframe));
962         cf->cf_func = (register_t)fork_return;
963         cf->cf_arg0 = (register_t)td;
964         cf->cf_arg1 = (register_t)tf;
965
966         pcb2->pcb_sp = (register_t)cf;
967         #if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1)
968         pcb2->pcb_lr = ((register_t *)fork_trampoline)[0];
969         pcb2->pcb_toc = ((register_t *)fork_trampoline)[1];
970         #else
971         pcb2->pcb_lr = (register_t)fork_trampoline;
972         pcb2->pcb_context[0] = pcb2->pcb_lr;
973         #endif
974         pcb2->pcb_cpu.aim.usr_vsid = 0;
975
976         /* Setup to release spin count in fork_exit(). */
977         td->td_md.md_spinlock_count = 1;
978         td->td_md.md_saved_msr = psl_kernset;
979 }
980
981 void
982 cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg,
983     stack_t *stack)
984 {
985         struct trapframe *tf;
986         uintptr_t sp;
987
988         tf = td->td_frame;
989         /* align stack and alloc space for frame ptr and saved LR */
990         #ifdef __powerpc64__
991         sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 48) &
992             ~0x1f;
993         #else
994         sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 8) &
995             ~0x1f;
996         #endif
997         bzero(tf, sizeof(struct trapframe));
998
999         tf->fixreg[1] = (register_t)sp;
1000         tf->fixreg[3] = (register_t)arg;
1001         if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
1002                 tf->srr0 = (register_t)entry;
1003                 #ifdef __powerpc64__
1004                 tf->srr1 = psl_userset32 | PSL_FE_DFLT;
1005                 #else
1006                 tf->srr1 = psl_userset | PSL_FE_DFLT;
1007                 #endif
1008         } else {
1009             #ifdef __powerpc64__
1010                 register_t entry_desc[3];
1011                 (void)copyin((void *)entry, entry_desc, sizeof(entry_desc));
1012                 tf->srr0 = entry_desc[0];
1013                 tf->fixreg[2] = entry_desc[1];
1014                 tf->fixreg[11] = entry_desc[2];
1015                 tf->srr1 = psl_userset | PSL_FE_DFLT;
1016             #endif
1017         }
1018
1019         td->td_pcb->pcb_flags = 0;
1020
1021         td->td_retval[0] = (register_t)entry;
1022         td->td_retval[1] = 0;
1023 }
1024
1025 int
1026 ppc_instr_emulate(struct trapframe *frame, struct pcb *pcb)
1027 {
1028         uint32_t instr;
1029         int reg, sig;
1030
1031         instr = fuword32((void *)frame->srr0);
1032         sig = SIGILL;
1033
1034         if ((instr & 0xfc1fffff) == 0x7c1f42a6) {       /* mfpvr */
1035                 reg = (instr & ~0xfc1fffff) >> 21;
1036                 frame->fixreg[reg] = mfpvr();
1037                 frame->srr0 += 4;
1038                 return (0);
1039         }
1040
1041         if ((instr & 0xfc000ffe) == 0x7c0004ac) {       /* various sync */
1042                 powerpc_sync(); /* Do a heavy-weight sync */
1043                 frame->srr0 += 4;
1044                 return (0);
1045         }
1046
1047 #ifdef FPU_EMU
1048         if (!(pcb->pcb_flags & PCB_FPREGS)) {
1049                 bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu));
1050                 pcb->pcb_flags |= PCB_FPREGS;
1051         }
1052         sig = fpu_emulate(frame, &pcb->pcb_fpu);
1053 #endif
1054
1055         return (sig);
1056 }
1057