]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/powerpc/powerpc/exec_machdep.c
MFV r348551: 9862 fix typo in comment in vdev_impl.h
[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_fpu_emu.h"
63
64 #include <sys/param.h>
65 #include <sys/proc.h>
66 #include <sys/systm.h>
67 #include <sys/bio.h>
68 #include <sys/buf.h>
69 #include <sys/bus.h>
70 #include <sys/cons.h>
71 #include <sys/cpu.h>
72 #include <sys/exec.h>
73 #include <sys/imgact.h>
74 #include <sys/kernel.h>
75 #include <sys/ktr.h>
76 #include <sys/lock.h>
77 #include <sys/malloc.h>
78 #include <sys/mutex.h>
79 #include <sys/signalvar.h>
80 #include <sys/syscallsubr.h>
81 #include <sys/syscall.h>
82 #include <sys/sysent.h>
83 #include <sys/sysproto.h>
84 #include <sys/ucontext.h>
85 #include <sys/uio.h>
86
87 #include <machine/altivec.h>
88 #include <machine/cpu.h>
89 #include <machine/elf.h>
90 #include <machine/fpu.h>
91 #include <machine/pcb.h>
92 #include <machine/reg.h>
93 #include <machine/sigframe.h>
94 #include <machine/trap.h>
95 #include <machine/vmparam.h>
96
97 #include <vm/pmap.h>
98
99 #ifdef FPU_EMU
100 #include <powerpc/fpu/fpu_extern.h>
101 #endif
102
103 #ifdef COMPAT_FREEBSD32
104 #include <compat/freebsd32/freebsd32_signal.h>
105 #include <compat/freebsd32/freebsd32_util.h>
106 #include <compat/freebsd32/freebsd32_proto.h>
107
108 typedef struct __ucontext32 {
109         sigset_t                uc_sigmask;
110         mcontext32_t            uc_mcontext;
111         uint32_t                uc_link;
112         struct sigaltstack32    uc_stack;
113         uint32_t                uc_flags;
114         uint32_t                __spare__[4];
115 } ucontext32_t;
116
117 struct sigframe32 {
118         ucontext32_t            sf_uc;
119         struct siginfo32        sf_si;
120 };
121
122 static int      grab_mcontext32(struct thread *td, mcontext32_t *, int flags);
123 #endif
124
125 static int      grab_mcontext(struct thread *, mcontext_t *, int);
126
127 static void     cleanup_power_extras(struct thread *);
128
129 #ifdef __powerpc64__
130 extern struct sysentvec elf64_freebsd_sysvec_v2;
131 #endif
132
133 void
134 sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
135 {
136         struct trapframe *tf;
137         struct sigacts *psp;
138         struct sigframe sf;
139         struct thread *td;
140         struct proc *p;
141         #ifdef COMPAT_FREEBSD32
142         struct siginfo32 siginfo32;
143         struct sigframe32 sf32;
144         #endif
145         size_t sfpsize;
146         caddr_t sfp, usfp;
147         int oonstack, rndfsize;
148         int sig;
149         int code;
150
151         td = curthread;
152         p = td->td_proc;
153         PROC_LOCK_ASSERT(p, MA_OWNED);
154
155         psp = p->p_sigacts;
156         mtx_assert(&psp->ps_mtx, MA_OWNED);
157         tf = td->td_frame;
158         oonstack = sigonstack(tf->fixreg[1]);
159
160         /*
161          * Fill siginfo structure.
162          */
163         ksi->ksi_info.si_signo = ksi->ksi_signo;
164         ksi->ksi_info.si_addr =
165             (void *)((tf->exc == EXC_DSI || tf->exc == EXC_DSE) ? 
166             tf->dar : tf->srr0);
167
168         #ifdef COMPAT_FREEBSD32
169         if (SV_PROC_FLAG(p, SV_ILP32)) {
170                 siginfo_to_siginfo32(&ksi->ksi_info, &siginfo32);
171                 sig = siginfo32.si_signo;
172                 code = siginfo32.si_code;
173                 sfp = (caddr_t)&sf32;
174                 sfpsize = sizeof(sf32);
175                 rndfsize = roundup(sizeof(sf32), 16);
176
177                 /*
178                  * Save user context
179                  */
180
181                 memset(&sf32, 0, sizeof(sf32));
182                 grab_mcontext32(td, &sf32.sf_uc.uc_mcontext, 0);
183
184                 sf32.sf_uc.uc_sigmask = *mask;
185                 sf32.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
186                 sf32.sf_uc.uc_stack.ss_size = (uint32_t)td->td_sigstk.ss_size;
187                 sf32.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
188                     ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
189
190                 sf32.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
191         } else {
192         #endif
193                 sig = ksi->ksi_signo;
194                 code = ksi->ksi_code;
195                 sfp = (caddr_t)&sf;
196                 sfpsize = sizeof(sf);
197                 #ifdef __powerpc64__
198                 /*
199                  * 64-bit PPC defines a 288 byte scratch region
200                  * below the stack.
201                  */
202                 rndfsize = 288 + roundup(sizeof(sf), 48);
203                 #else
204                 rndfsize = roundup(sizeof(sf), 16);
205                 #endif
206
207                 /*
208                  * Save user context
209                  */
210
211                 memset(&sf, 0, sizeof(sf));
212                 grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0);
213
214                 sf.sf_uc.uc_sigmask = *mask;
215                 sf.sf_uc.uc_stack = td->td_sigstk;
216                 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
217                     ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
218
219                 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
220         #ifdef COMPAT_FREEBSD32
221         }
222         #endif
223
224         CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
225              catcher, sig);
226
227         /*
228          * Allocate and validate space for the signal handler context.
229          */
230         if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
231             SIGISMEMBER(psp->ps_sigonstack, sig)) {
232                 usfp = (void *)(((uintptr_t)td->td_sigstk.ss_sp +
233                    td->td_sigstk.ss_size - rndfsize) & ~0xFul);
234         } else {
235                 usfp = (void *)((tf->fixreg[1] - rndfsize) & ~0xFul);
236         }
237
238         /*
239          * Save the floating-point state, if necessary, then copy it.
240          */
241         /* XXX */
242
243         /*
244          * Set up the registers to return to sigcode.
245          *
246          *   r1/sp - sigframe ptr
247          *   lr    - sig function, dispatched to by blrl in trampoline
248          *   r3    - sig number
249          *   r4    - SIGINFO ? &siginfo : exception code
250          *   r5    - user context
251          *   srr0  - trampoline function addr
252          */
253         tf->lr = (register_t)catcher;
254         tf->fixreg[1] = (register_t)usfp;
255         tf->fixreg[FIRSTARG] = sig;
256         #ifdef COMPAT_FREEBSD32
257         tf->fixreg[FIRSTARG+2] = (register_t)usfp +
258             ((SV_PROC_FLAG(p, SV_ILP32)) ?
259             offsetof(struct sigframe32, sf_uc) :
260             offsetof(struct sigframe, sf_uc));
261         #else
262         tf->fixreg[FIRSTARG+2] = (register_t)usfp +
263             offsetof(struct sigframe, sf_uc);
264         #endif
265         if (SIGISMEMBER(psp->ps_siginfo, sig)) {
266                 /*
267                  * Signal handler installed with SA_SIGINFO.
268                  */
269                 #ifdef COMPAT_FREEBSD32
270                 if (SV_PROC_FLAG(p, SV_ILP32)) {
271                         sf32.sf_si = siginfo32;
272                         tf->fixreg[FIRSTARG+1] = (register_t)usfp +
273                             offsetof(struct sigframe32, sf_si);
274                         sf32.sf_si = siginfo32;
275                 } else  {
276                 #endif
277                         tf->fixreg[FIRSTARG+1] = (register_t)usfp +
278                             offsetof(struct sigframe, sf_si);
279                         sf.sf_si = ksi->ksi_info;
280                 #ifdef COMPAT_FREEBSD32
281                 }
282                 #endif
283         } else {
284                 /* Old FreeBSD-style arguments. */
285                 tf->fixreg[FIRSTARG+1] = code;
286                 tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? 
287                     tf->dar : tf->srr0;
288         }
289         mtx_unlock(&psp->ps_mtx);
290         PROC_UNLOCK(p);
291
292         tf->srr0 = (register_t)p->p_sysent->sv_sigcode_base;
293
294         /*
295          * copy the frame out to userland.
296          */
297         if (copyout(sfp, usfp, sfpsize) != 0) {
298                 /*
299                  * Process has trashed its stack. Kill it.
300                  */
301                 CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp);
302                 PROC_LOCK(p);
303                 sigexit(td, SIGILL);
304         }
305
306         CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td,
307              tf->srr0, tf->fixreg[1]);
308
309         PROC_LOCK(p);
310         mtx_lock(&psp->ps_mtx);
311 }
312
313 int
314 sys_sigreturn(struct thread *td, struct sigreturn_args *uap)
315 {
316         ucontext_t uc;
317         int error;
318
319         CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
320
321         if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
322                 CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
323                 return (EFAULT);
324         }
325
326         error = set_mcontext(td, &uc.uc_mcontext);
327         if (error != 0)
328                 return (error);
329
330         kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
331
332         CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
333              td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
334
335         return (EJUSTRETURN);
336 }
337
338 #ifdef COMPAT_FREEBSD4
339 int
340 freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
341 {
342
343         return sys_sigreturn(td, (struct sigreturn_args *)uap);
344 }
345 #endif
346
347 /*
348  * Construct a PCB from a trapframe. This is called from kdb_trap() where
349  * we want to start a backtrace from the function that caused us to enter
350  * the debugger. We have the context in the trapframe, but base the trace
351  * on the PCB. The PCB doesn't have to be perfect, as long as it contains
352  * enough for a backtrace.
353  */
354 void
355 makectx(struct trapframe *tf, struct pcb *pcb)
356 {
357
358         pcb->pcb_lr = tf->srr0;
359         pcb->pcb_sp = tf->fixreg[1];
360 }
361
362 /*
363  * get_mcontext/sendsig helper routine that doesn't touch the
364  * proc lock
365  */
366 static int
367 grab_mcontext(struct thread *td, mcontext_t *mcp, int flags)
368 {
369         struct pcb *pcb;
370         int i;
371
372         pcb = td->td_pcb;
373
374         memset(mcp, 0, sizeof(mcontext_t));
375
376         mcp->mc_vers = _MC_VERSION;
377         mcp->mc_flags = 0;
378         memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe));
379         if (flags & GET_MC_CLEAR_RET) {
380                 mcp->mc_gpr[3] = 0;
381                 mcp->mc_gpr[4] = 0;
382         }
383
384         /*
385          * This assumes that floating-point context is *not* lazy,
386          * so if the thread has used FP there would have been a
387          * FP-unavailable exception that would have set things up
388          * correctly.
389          */
390         if (pcb->pcb_flags & PCB_FPREGS) {
391                 if (pcb->pcb_flags & PCB_FPU) {
392                         KASSERT(td == curthread,
393                                 ("get_mcontext: fp save not curthread"));
394                         critical_enter();
395                         save_fpu(td);
396                         critical_exit();
397                 }
398                 mcp->mc_flags |= _MC_FP_VALID;
399                 memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
400                 for (i = 0; i < 32; i++)
401                         memcpy(&mcp->mc_fpreg[i], &pcb->pcb_fpu.fpr[i].fpr,
402                             sizeof(double));
403         }
404
405         if (pcb->pcb_flags & PCB_VSX) {
406                 for (i = 0; i < 32; i++)
407                         memcpy(&mcp->mc_vsxfpreg[i],
408                             &pcb->pcb_fpu.fpr[i].vsr[2], sizeof(double));
409         }
410
411         /*
412          * Repeat for Altivec context
413          */
414
415         if (pcb->pcb_flags & PCB_VEC) {
416                 KASSERT(td == curthread,
417                         ("get_mcontext: fp save not curthread"));
418                 critical_enter();
419                 save_vec(td);
420                 critical_exit();
421                 mcp->mc_flags |= _MC_AV_VALID;
422                 mcp->mc_vscr  = pcb->pcb_vec.vscr;
423                 mcp->mc_vrsave =  pcb->pcb_vec.vrsave;
424                 memcpy(mcp->mc_avec, pcb->pcb_vec.vr, sizeof(mcp->mc_avec));
425         }
426
427         mcp->mc_len = sizeof(*mcp);
428
429         return (0);
430 }
431
432 int
433 get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
434 {
435         int error;
436
437         error = grab_mcontext(td, mcp, flags);
438         if (error == 0) {
439                 PROC_LOCK(curthread->td_proc);
440                 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]);
441                 PROC_UNLOCK(curthread->td_proc);
442         }
443
444         return (error);
445 }
446
447 int
448 set_mcontext(struct thread *td, mcontext_t *mcp)
449 {
450         struct pcb *pcb;
451         struct trapframe *tf;
452         register_t tls;
453         int i;
454
455         pcb = td->td_pcb;
456         tf = td->td_frame;
457
458         if (mcp->mc_vers != _MC_VERSION || mcp->mc_len != sizeof(*mcp))
459                 return (EINVAL);
460
461         /*
462          * Don't let the user set privileged MSR bits
463          */
464         if ((mcp->mc_srr1 & psl_userstatic) != (tf->srr1 & psl_userstatic)) {
465                 return (EINVAL);
466         }
467
468         /* Copy trapframe, preserving TLS pointer across context change */
469         if (SV_PROC_FLAG(td->td_proc, SV_LP64))
470                 tls = tf->fixreg[13];
471         else
472                 tls = tf->fixreg[2];
473         memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame));
474         if (SV_PROC_FLAG(td->td_proc, SV_LP64))
475                 tf->fixreg[13] = tls;
476         else
477                 tf->fixreg[2] = tls;
478
479         /* Disable FPU */
480         tf->srr1 &= ~PSL_FP;
481         pcb->pcb_flags &= ~PCB_FPU;
482
483         if (mcp->mc_flags & _MC_FP_VALID) {
484                 /* enable_fpu() will happen lazily on a fault */
485                 pcb->pcb_flags |= PCB_FPREGS;
486                 memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double));
487                 bzero(pcb->pcb_fpu.fpr, sizeof(pcb->pcb_fpu.fpr));
488                 for (i = 0; i < 32; i++) {
489                         memcpy(&pcb->pcb_fpu.fpr[i].fpr, &mcp->mc_fpreg[i],
490                             sizeof(double));
491                         memcpy(&pcb->pcb_fpu.fpr[i].vsr[2],
492                             &mcp->mc_vsxfpreg[i], sizeof(double));
493                 }
494         }
495
496         if (mcp->mc_flags & _MC_AV_VALID) {
497                 if ((pcb->pcb_flags & PCB_VEC) != PCB_VEC) {
498                         critical_enter();
499                         enable_vec(td);
500                         critical_exit();
501                 }
502                 pcb->pcb_vec.vscr = mcp->mc_vscr;
503                 pcb->pcb_vec.vrsave = mcp->mc_vrsave;
504                 memcpy(pcb->pcb_vec.vr, mcp->mc_avec, sizeof(mcp->mc_avec));
505         }
506
507         return (0);
508 }
509
510 /*
511  * Clean up extra POWER state.  Some per-process registers and states are not
512  * managed by the MSR, so must be cleaned up explicitly on thread exit.
513  *
514  * Currently this includes:
515  * DSCR -- Data stream control register (PowerISA 2.06+)
516  * FSCR -- Facility Status and Control Register (PowerISA 2.07+)
517  */
518 static void
519 cleanup_power_extras(struct thread *td)
520 {
521         uint32_t pcb_flags;
522
523         if (td != curthread)
524                 return;
525
526         pcb_flags = td->td_pcb->pcb_flags;
527         /* Clean up registers not managed by MSR. */
528         if (pcb_flags & PCB_CFSCR)
529                 mtspr(SPR_FSCR, 0);
530         if (pcb_flags & PCB_CDSCR) 
531                 mtspr(SPR_DSCRP, 0);
532 }
533
534 /*
535  * Set set up registers on exec.
536  */
537 void
538 exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
539 {
540         struct trapframe        *tf;
541         register_t              argc;
542
543         tf = trapframe(td);
544         bzero(tf, sizeof *tf);
545         #ifdef __powerpc64__
546         tf->fixreg[1] = -roundup(-stack + 48, 16);
547         #else
548         tf->fixreg[1] = -roundup(-stack + 8, 16);
549         #endif
550
551         /*
552          * Set up arguments for _start():
553          *      _start(argc, argv, envp, obj, cleanup, ps_strings);
554          *
555          * Notes:
556          *      - obj and cleanup are the auxilliary and termination
557          *        vectors.  They are fixed up by ld.elf_so.
558          *      - ps_strings is a NetBSD extention, and will be
559          *        ignored by executables which are strictly
560          *        compliant with the SVR4 ABI.
561          */
562
563         /* Collect argc from the user stack */
564         argc = fuword((void *)stack);
565
566         tf->fixreg[3] = argc;
567         tf->fixreg[4] = stack + sizeof(register_t);
568         tf->fixreg[5] = stack + (2 + argc)*sizeof(register_t);
569         tf->fixreg[6] = 0;                              /* auxillary vector */
570         tf->fixreg[7] = 0;                              /* termination vector */
571         tf->fixreg[8] = (register_t)imgp->ps_strings;   /* NetBSD extension */
572
573         tf->srr0 = imgp->entry_addr;
574         #ifdef __powerpc64__
575         tf->fixreg[12] = imgp->entry_addr;
576         #endif
577         tf->srr1 = psl_userset | PSL_FE_DFLT;
578         cleanup_power_extras(td);
579         td->td_pcb->pcb_flags = 0;
580 }
581
582 #ifdef COMPAT_FREEBSD32
583 void
584 ppc32_setregs(struct thread *td, struct image_params *imgp, u_long stack)
585 {
586         struct trapframe        *tf;
587         uint32_t                argc;
588
589         tf = trapframe(td);
590         bzero(tf, sizeof *tf);
591         tf->fixreg[1] = -roundup(-stack + 8, 16);
592
593         argc = fuword32((void *)stack);
594
595         tf->fixreg[3] = argc;
596         tf->fixreg[4] = stack + sizeof(uint32_t);
597         tf->fixreg[5] = stack + (2 + argc)*sizeof(uint32_t);
598         tf->fixreg[6] = 0;                              /* auxillary vector */
599         tf->fixreg[7] = 0;                              /* termination vector */
600         tf->fixreg[8] = (register_t)imgp->ps_strings;   /* NetBSD extension */
601
602         tf->srr0 = imgp->entry_addr;
603         tf->srr1 = psl_userset32 | PSL_FE_DFLT;
604         cleanup_power_extras(td);
605         td->td_pcb->pcb_flags = 0;
606 }
607 #endif
608
609 int
610 fill_regs(struct thread *td, struct reg *regs)
611 {
612         struct trapframe *tf;
613
614         tf = td->td_frame;
615         memcpy(regs, tf, sizeof(struct reg));
616
617         return (0);
618 }
619
620 int
621 fill_dbregs(struct thread *td, struct dbreg *dbregs)
622 {
623         /* No debug registers on PowerPC */
624         return (ENOSYS);
625 }
626
627 int
628 fill_fpregs(struct thread *td, struct fpreg *fpregs)
629 {
630         struct pcb *pcb;
631         int i;
632
633         pcb = td->td_pcb;
634
635         if ((pcb->pcb_flags & PCB_FPREGS) == 0)
636                 memset(fpregs, 0, sizeof(struct fpreg));
637         else {
638                 memcpy(&fpregs->fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
639                 for (i = 0; i < 32; i++)
640                         memcpy(&fpregs->fpreg[i], &pcb->pcb_fpu.fpr[i].fpr,
641                             sizeof(double));
642         }
643
644         return (0);
645 }
646
647 int
648 set_regs(struct thread *td, struct reg *regs)
649 {
650         struct trapframe *tf;
651
652         tf = td->td_frame;
653         memcpy(tf, regs, sizeof(struct reg));
654         
655         return (0);
656 }
657
658 int
659 set_dbregs(struct thread *td, struct dbreg *dbregs)
660 {
661         /* No debug registers on PowerPC */
662         return (ENOSYS);
663 }
664
665 int
666 set_fpregs(struct thread *td, struct fpreg *fpregs)
667 {
668         struct pcb *pcb;
669         int i;
670
671         pcb = td->td_pcb;
672         pcb->pcb_flags |= PCB_FPREGS;
673         memcpy(&pcb->pcb_fpu.fpscr, &fpregs->fpscr, sizeof(double));
674         for (i = 0; i < 32; i++) {
675                 memcpy(&pcb->pcb_fpu.fpr[i].fpr, &fpregs->fpreg[i],
676                     sizeof(double));
677         }
678
679         return (0);
680 }
681
682 #ifdef COMPAT_FREEBSD32
683 int
684 set_regs32(struct thread *td, struct reg32 *regs)
685 {
686         struct trapframe *tf;
687         int i;
688
689         tf = td->td_frame;
690         for (i = 0; i < 32; i++)
691                 tf->fixreg[i] = regs->fixreg[i];
692         tf->lr = regs->lr;
693         tf->cr = regs->cr;
694         tf->xer = regs->xer;
695         tf->ctr = regs->ctr;
696         tf->srr0 = regs->pc;
697
698         return (0);
699 }
700
701 int
702 fill_regs32(struct thread *td, struct reg32 *regs)
703 {
704         struct trapframe *tf;
705         int i;
706
707         tf = td->td_frame;
708         for (i = 0; i < 32; i++)
709                 regs->fixreg[i] = tf->fixreg[i];
710         regs->lr = tf->lr;
711         regs->cr = tf->cr;
712         regs->xer = tf->xer;
713         regs->ctr = tf->ctr;
714         regs->pc = tf->srr0;
715
716         return (0);
717 }
718
719 static int
720 grab_mcontext32(struct thread *td, mcontext32_t *mcp, int flags)
721 {
722         mcontext_t mcp64;
723         int i, error;
724
725         error = grab_mcontext(td, &mcp64, flags);
726         if (error != 0)
727                 return (error);
728         
729         mcp->mc_vers = mcp64.mc_vers;
730         mcp->mc_flags = mcp64.mc_flags;
731         mcp->mc_onstack = mcp64.mc_onstack;
732         mcp->mc_len = mcp64.mc_len;
733         memcpy(mcp->mc_avec,mcp64.mc_avec,sizeof(mcp64.mc_avec));
734         memcpy(mcp->mc_av,mcp64.mc_av,sizeof(mcp64.mc_av));
735         for (i = 0; i < 42; i++)
736                 mcp->mc_frame[i] = mcp64.mc_frame[i];
737         memcpy(mcp->mc_fpreg,mcp64.mc_fpreg,sizeof(mcp64.mc_fpreg));
738         memcpy(mcp->mc_vsxfpreg,mcp64.mc_vsxfpreg,sizeof(mcp64.mc_vsxfpreg));
739
740         return (0);
741 }
742
743 static int
744 get_mcontext32(struct thread *td, mcontext32_t *mcp, int flags)
745 {
746         int error;
747
748         error = grab_mcontext32(td, mcp, flags);
749         if (error == 0) {
750                 PROC_LOCK(curthread->td_proc);
751                 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]);
752                 PROC_UNLOCK(curthread->td_proc);
753         }
754
755         return (error);
756 }
757
758 static int
759 set_mcontext32(struct thread *td, mcontext32_t *mcp)
760 {
761         mcontext_t mcp64;
762         int i, error;
763
764         mcp64.mc_vers = mcp->mc_vers;
765         mcp64.mc_flags = mcp->mc_flags;
766         mcp64.mc_onstack = mcp->mc_onstack;
767         mcp64.mc_len = mcp->mc_len;
768         memcpy(mcp64.mc_avec,mcp->mc_avec,sizeof(mcp64.mc_avec));
769         memcpy(mcp64.mc_av,mcp->mc_av,sizeof(mcp64.mc_av));
770         for (i = 0; i < 42; i++)
771                 mcp64.mc_frame[i] = mcp->mc_frame[i];
772         mcp64.mc_srr1 |= (td->td_frame->srr1 & 0xFFFFFFFF00000000ULL);
773         memcpy(mcp64.mc_fpreg,mcp->mc_fpreg,sizeof(mcp64.mc_fpreg));
774         memcpy(mcp64.mc_vsxfpreg,mcp->mc_vsxfpreg,sizeof(mcp64.mc_vsxfpreg));
775
776         error = set_mcontext(td, &mcp64);
777
778         return (error);
779 }
780 #endif
781
782 #ifdef COMPAT_FREEBSD32
783 int
784 freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap)
785 {
786         ucontext32_t uc;
787         int error;
788
789         CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
790
791         if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
792                 CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
793                 return (EFAULT);
794         }
795
796         error = set_mcontext32(td, &uc.uc_mcontext);
797         if (error != 0)
798                 return (error);
799
800         kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
801
802         CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
803              td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
804
805         return (EJUSTRETURN);
806 }
807
808 /*
809  * The first two fields of a ucontext_t are the signal mask and the machine
810  * context.  The next field is uc_link; we want to avoid destroying the link
811  * when copying out contexts.
812  */
813 #define UC32_COPY_SIZE  offsetof(ucontext32_t, uc_link)
814
815 int
816 freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap)
817 {
818         ucontext32_t uc;
819         int ret;
820
821         if (uap->ucp == NULL)
822                 ret = EINVAL;
823         else {
824                 bzero(&uc, sizeof(uc));
825                 get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
826                 PROC_LOCK(td->td_proc);
827                 uc.uc_sigmask = td->td_sigmask;
828                 PROC_UNLOCK(td->td_proc);
829                 ret = copyout(&uc, uap->ucp, UC32_COPY_SIZE);
830         }
831         return (ret);
832 }
833
834 int
835 freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap)
836 {
837         ucontext32_t uc;
838         int ret;        
839
840         if (uap->ucp == NULL)
841                 ret = EINVAL;
842         else {
843                 ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE);
844                 if (ret == 0) {
845                         ret = set_mcontext32(td, &uc.uc_mcontext);
846                         if (ret == 0) {
847                                 kern_sigprocmask(td, SIG_SETMASK,
848                                     &uc.uc_sigmask, NULL, 0);
849                         }
850                 }
851         }
852         return (ret == 0 ? EJUSTRETURN : ret);
853 }
854
855 int
856 freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
857 {
858         ucontext32_t uc;
859         int ret;
860
861         if (uap->oucp == NULL || uap->ucp == NULL)
862                 ret = EINVAL;
863         else {
864                 bzero(&uc, sizeof(uc));
865                 get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
866                 PROC_LOCK(td->td_proc);
867                 uc.uc_sigmask = td->td_sigmask;
868                 PROC_UNLOCK(td->td_proc);
869                 ret = copyout(&uc, uap->oucp, UC32_COPY_SIZE);
870                 if (ret == 0) {
871                         ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE);
872                         if (ret == 0) {
873                                 ret = set_mcontext32(td, &uc.uc_mcontext);
874                                 if (ret == 0) {
875                                         kern_sigprocmask(td, SIG_SETMASK,
876                                             &uc.uc_sigmask, NULL, 0);
877                                 }
878                         }
879                 }
880         }
881         return (ret == 0 ? EJUSTRETURN : ret);
882 }
883
884 #endif
885
886 void
887 cpu_set_syscall_retval(struct thread *td, int error)
888 {
889         struct proc *p;
890         struct trapframe *tf;
891         int fixup;
892
893         if (error == EJUSTRETURN)
894                 return;
895
896         p = td->td_proc;
897         tf = td->td_frame;
898
899         if (tf->fixreg[0] == SYS___syscall &&
900             (SV_PROC_FLAG(p, SV_ILP32))) {
901                 int code = tf->fixreg[FIRSTARG + 1];
902                 fixup = (
903 #if defined(COMPAT_FREEBSD6) && defined(SYS_freebsd6_lseek)
904                     code != SYS_freebsd6_lseek &&
905 #endif
906                     code != SYS_lseek) ?  1 : 0;
907         } else
908                 fixup = 0;
909
910         switch (error) {
911         case 0:
912                 if (fixup) {
913                         /*
914                          * 64-bit return, 32-bit syscall. Fixup byte order
915                          */
916                         tf->fixreg[FIRSTARG] = 0;
917                         tf->fixreg[FIRSTARG + 1] = td->td_retval[0];
918                 } else {
919                         tf->fixreg[FIRSTARG] = td->td_retval[0];
920                         tf->fixreg[FIRSTARG + 1] = td->td_retval[1];
921                 }
922                 tf->cr &= ~0x10000000;          /* Unset summary overflow */
923                 break;
924         case ERESTART:
925                 /*
926                  * Set user's pc back to redo the system call.
927                  */
928                 tf->srr0 -= 4;
929                 break;
930         default:
931                 tf->fixreg[FIRSTARG] = SV_ABI_ERRNO(p, error);
932                 tf->cr |= 0x10000000;           /* Set summary overflow */
933                 break;
934         }
935 }
936
937 /*
938  * Threading functions
939  */
940 void
941 cpu_thread_exit(struct thread *td)
942 {
943         cleanup_power_extras(td);
944 }
945
946 void
947 cpu_thread_clean(struct thread *td)
948 {
949 }
950
951 void
952 cpu_thread_alloc(struct thread *td)
953 {
954         struct pcb *pcb;
955
956         pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE -
957             sizeof(struct pcb)) & ~0x2fUL);
958         td->td_pcb = pcb;
959         td->td_frame = (struct trapframe *)pcb - 1;
960 }
961
962 void
963 cpu_thread_free(struct thread *td)
964 {
965 }
966
967 int
968 cpu_set_user_tls(struct thread *td, void *tls_base)
969 {
970
971         if (SV_PROC_FLAG(td->td_proc, SV_LP64))
972                 td->td_frame->fixreg[13] = (register_t)tls_base + 0x7010;
973         else
974                 td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008;
975         return (0);
976 }
977
978 void
979 cpu_copy_thread(struct thread *td, struct thread *td0)
980 {
981         struct pcb *pcb2;
982         struct trapframe *tf;
983         struct callframe *cf;
984
985         pcb2 = td->td_pcb;
986
987         /* Copy the upcall pcb */
988         bcopy(td0->td_pcb, pcb2, sizeof(*pcb2));
989
990         /* Create a stack for the new thread */
991         tf = td->td_frame;
992         bcopy(td0->td_frame, tf, sizeof(struct trapframe));
993         tf->fixreg[FIRSTARG] = 0;
994         tf->fixreg[FIRSTARG + 1] = 0;
995         tf->cr &= ~0x10000000;
996
997         /* Set registers for trampoline to user mode. */
998         cf = (struct callframe *)tf - 1;
999         memset(cf, 0, sizeof(struct callframe));
1000         cf->cf_func = (register_t)fork_return;
1001         cf->cf_arg0 = (register_t)td;
1002         cf->cf_arg1 = (register_t)tf;
1003
1004         pcb2->pcb_sp = (register_t)cf;
1005         #if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1)
1006         pcb2->pcb_lr = ((register_t *)fork_trampoline)[0];
1007         pcb2->pcb_toc = ((register_t *)fork_trampoline)[1];
1008         #else
1009         pcb2->pcb_lr = (register_t)fork_trampoline;
1010         pcb2->pcb_context[0] = pcb2->pcb_lr;
1011         #endif
1012         pcb2->pcb_cpu.aim.usr_vsid = 0;
1013 #ifdef __SPE__
1014         pcb2->pcb_vec.vscr = SPEFSCR_FINVE | SPEFSCR_FDBZE |
1015             SPEFSCR_FUNFE | SPEFSCR_FOVFE;
1016 #endif
1017
1018         /* Setup to release spin count in fork_exit(). */
1019         td->td_md.md_spinlock_count = 1;
1020         td->td_md.md_saved_msr = psl_kernset;
1021 }
1022
1023 void
1024 cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg,
1025     stack_t *stack)
1026 {
1027         struct trapframe *tf;
1028         uintptr_t sp;
1029
1030         tf = td->td_frame;
1031         /* align stack and alloc space for frame ptr and saved LR */
1032         #ifdef __powerpc64__
1033         sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 48) &
1034             ~0x1f;
1035         #else
1036         sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 8) &
1037             ~0x1f;
1038         #endif
1039         bzero(tf, sizeof(struct trapframe));
1040
1041         tf->fixreg[1] = (register_t)sp;
1042         tf->fixreg[3] = (register_t)arg;
1043         if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
1044                 tf->srr0 = (register_t)entry;
1045                 #ifdef __powerpc64__
1046                 tf->srr1 = psl_userset32 | PSL_FE_DFLT;
1047                 #else
1048                 tf->srr1 = psl_userset | PSL_FE_DFLT;
1049                 #endif
1050         } else {
1051             #ifdef __powerpc64__
1052                 if (td->td_proc->p_sysent == &elf64_freebsd_sysvec_v2) {
1053                         tf->srr0 = (register_t)entry;
1054                         /* ELFv2 ABI requires that the global entry point be in r12. */
1055                         tf->fixreg[12] = (register_t)entry;
1056                 }
1057                 else {
1058                         register_t entry_desc[3];
1059                         (void)copyin((void *)entry, entry_desc, sizeof(entry_desc));
1060                         tf->srr0 = entry_desc[0];
1061                         tf->fixreg[2] = entry_desc[1];
1062                         tf->fixreg[11] = entry_desc[2];
1063                 }
1064                 tf->srr1 = psl_userset | PSL_FE_DFLT;
1065             #endif
1066         }
1067
1068         td->td_pcb->pcb_flags = 0;
1069 #ifdef __SPE__
1070         td->td_pcb->pcb_vec.vscr = SPEFSCR_FINVE | SPEFSCR_FDBZE |
1071             SPEFSCR_FUNFE | SPEFSCR_FOVFE;
1072 #endif
1073
1074         td->td_retval[0] = (register_t)entry;
1075         td->td_retval[1] = 0;
1076 }
1077
1078 static int
1079 emulate_mfspr(int spr, int reg, struct trapframe *frame){
1080         struct thread *td;
1081
1082         td = curthread;
1083
1084         if (spr == SPR_DSCR || spr == SPR_DSCRP) {
1085                 // If DSCR was never set, get the default DSCR
1086                 if ((td->td_pcb->pcb_flags & PCB_CDSCR) == 0)
1087                         td->td_pcb->pcb_dscr = mfspr(SPR_DSCRP);
1088
1089                 frame->fixreg[reg] = td->td_pcb->pcb_dscr;
1090                 frame->srr0 += 4;
1091                 return 0;
1092         } else
1093                 return SIGILL;
1094 }
1095
1096 static int
1097 emulate_mtspr(int spr, int reg, struct trapframe *frame){
1098         struct thread *td;
1099
1100         td = curthread;
1101
1102         if (spr == SPR_DSCR || spr == SPR_DSCRP) {
1103                 td->td_pcb->pcb_flags |= PCB_CDSCR;
1104                 td->td_pcb->pcb_dscr = frame->fixreg[reg];
1105                 mtspr(SPR_DSCRP, frame->fixreg[reg]);
1106                 frame->srr0 += 4;
1107                 return 0;
1108         } else
1109                 return SIGILL;
1110 }
1111
1112 #define XFX 0xFC0007FF
1113 int
1114 ppc_instr_emulate(struct trapframe *frame, struct thread *td)
1115 {
1116         struct pcb *pcb;
1117         uint32_t instr;
1118         int reg, sig;
1119         int rs, spr;
1120
1121         instr = fuword32((void *)frame->srr0);
1122         sig = SIGILL;
1123
1124         if ((instr & 0xfc1fffff) == 0x7c1f42a6) {       /* mfpvr */
1125                 reg = (instr & ~0xfc1fffff) >> 21;
1126                 frame->fixreg[reg] = mfpvr();
1127                 frame->srr0 += 4;
1128                 return (0);
1129         } else if ((instr & XFX) == 0x7c0002a6) {       /* mfspr */
1130                 rs = (instr &  0x3e00000) >> 21;
1131                 spr = (instr & 0x1ff800) >> 16;
1132                 return emulate_mfspr(spr, rs, frame);
1133         } else if ((instr & XFX) == 0x7c0003a6) {       /* mtspr */
1134                 rs = (instr &  0x3e00000) >> 21;
1135                 spr = (instr & 0x1ff800) >> 16;
1136                 return emulate_mtspr(spr, rs, frame);
1137         } else if ((instr & 0xfc000ffe) == 0x7c0004ac) {        /* various sync */
1138                 powerpc_sync(); /* Do a heavy-weight sync */
1139                 frame->srr0 += 4;
1140                 return (0);
1141         }
1142
1143         pcb = td->td_pcb;
1144 #ifdef FPU_EMU
1145         if (!(pcb->pcb_flags & PCB_FPREGS)) {
1146                 bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu));
1147                 pcb->pcb_flags |= PCB_FPREGS;
1148         } else if (pcb->pcb_flags & PCB_FPU)
1149                 save_fpu(td);
1150         sig = fpu_emulate(frame, &pcb->pcb_fpu);
1151         if ((sig == 0 || sig == SIGFPE) && pcb->pcb_flags & PCB_FPU)
1152                 enable_fpu(td);
1153 #endif
1154         if (sig == SIGILL) {
1155                 if (pcb->pcb_lastill != frame->srr0) {
1156                         /* Allow a second chance, in case of cache sync issues. */
1157                         sig = 0;
1158                         pmap_sync_icache(PCPU_GET(curpmap), frame->srr0, 4);
1159                         pcb->pcb_lastill = frame->srr0;
1160                 }
1161         }
1162
1163         return (sig);
1164 }
1165