]> CyberLeo.Net >> Repos - FreeBSD/releng/8.2.git/blob - sys/powerpc/powerpc/exec_machdep.c
Copy stable/8 to releng/8.2 in preparation for FreeBSD-8.2 release.
[FreeBSD/releng/8.2.git] / sys / powerpc / powerpc / exec_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
62 #include <sys/param.h>
63 #include <sys/proc.h>
64 #include <sys/systm.h>
65 #include <sys/bio.h>
66 #include <sys/buf.h>
67 #include <sys/bus.h>
68 #include <sys/cons.h>
69 #include <sys/cpu.h>
70 #include <sys/exec.h>
71 #include <sys/imgact.h>
72 #include <sys/kernel.h>
73 #include <sys/ktr.h>
74 #include <sys/lock.h>
75 #include <sys/malloc.h>
76 #include <sys/mutex.h>
77 #include <sys/signalvar.h>
78 #include <sys/syscallsubr.h>
79 #include <sys/syscall.h>
80 #include <sys/sysent.h>
81 #include <sys/sysproto.h>
82 #include <sys/ucontext.h>
83 #include <sys/uio.h>
84
85 #include <machine/altivec.h>
86 #include <machine/cpu.h>
87 #include <machine/elf.h>
88 #include <machine/fpu.h>
89 #include <machine/pcb.h>
90 #include <machine/reg.h>
91 #include <machine/sigframe.h>
92 #include <machine/trap.h>
93 #include <machine/vmparam.h>
94
95 static int      grab_mcontext(struct thread *, mcontext_t *, int);
96
97 void
98 sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
99 {
100         struct trapframe *tf;
101         struct sigacts *psp;
102         struct sigframe sf;
103         struct thread *td;
104         struct proc *p;
105         size_t sfpsize;
106         caddr_t sfp, usfp;
107         int oonstack, rndfsize;
108         int sig;
109         int code;
110
111         td = curthread;
112         p = td->td_proc;
113         PROC_LOCK_ASSERT(p, MA_OWNED);
114
115         psp = p->p_sigacts;
116         mtx_assert(&psp->ps_mtx, MA_OWNED);
117         tf = td->td_frame;
118         oonstack = sigonstack(tf->fixreg[1]);
119
120         /*
121          * Fill siginfo structure.
122          */
123         ksi->ksi_info.si_signo = ksi->ksi_signo;
124         #ifdef AIM
125         ksi->ksi_info.si_addr = (void *)((tf->exc == EXC_DSI) ? 
126             tf->cpu.aim.dar : tf->srr0);
127         #else
128         ksi->ksi_info.si_addr = (void *)((tf->exc == EXC_DSI) ? 
129             tf->cpu.booke.dear : tf->srr0);
130         #endif
131
132         sig = ksi->ksi_signo;
133         code = ksi->ksi_code;
134         sfp = (caddr_t)&sf;
135         sfpsize = sizeof(sf);
136         rndfsize = ((sizeof(sf) + 15) / 16) * 16;
137
138         /*
139          * Save user context
140          */
141
142         memset(&sf, 0, sizeof(sf));
143         grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0);
144
145         sf.sf_uc.uc_sigmask = *mask;
146         sf.sf_uc.uc_stack = td->td_sigstk;
147         sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
148             ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
149
150         sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
151
152         CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
153              catcher, sig);
154
155         /*
156          * Allocate and validate space for the signal handler context.
157          */
158         if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
159             SIGISMEMBER(psp->ps_sigonstack, sig)) {
160                 usfp = (void *)(td->td_sigstk.ss_sp +
161                    td->td_sigstk.ss_size - rndfsize);
162         } else {
163                 usfp = (void *)(tf->fixreg[1] - rndfsize);
164         }
165
166         /*
167          * Translate the signal if appropriate (Linux emu ?)
168          */
169         if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
170                 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
171
172         /*
173          * Save the floating-point state, if necessary, then copy it.
174          */
175         /* XXX */
176
177         /*
178          * Set up the registers to return to sigcode.
179          *
180          *   r1/sp - sigframe ptr
181          *   lr    - sig function, dispatched to by blrl in trampoline
182          *   r3    - sig number
183          *   r4    - SIGINFO ? &siginfo : exception code
184          *   r5    - user context
185          *   srr0  - trampoline function addr
186          */
187         tf->lr = (register_t)catcher;
188         tf->fixreg[1] = (register_t)usfp;
189         tf->fixreg[FIRSTARG] = sig;
190         tf->fixreg[FIRSTARG+2] = (register_t)usfp +
191             offsetof(struct sigframe, sf_uc);
192         if (SIGISMEMBER(psp->ps_siginfo, sig)) {
193                 /*
194                  * Signal handler installed with SA_SIGINFO.
195                  */
196                         tf->fixreg[FIRSTARG+1] = (register_t)usfp +
197                             offsetof(struct sigframe, sf_si);
198                         sf.sf_si = ksi->ksi_info;
199         } else {
200                 /* Old FreeBSD-style arguments. */
201                 tf->fixreg[FIRSTARG+1] = code;
202                 #ifdef AIM
203                 tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? 
204                     tf->cpu.aim.dar : tf->srr0;
205                 #else
206                 tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? 
207                     tf->cpu.booke.dear : tf->srr0;
208                 #endif
209         }
210         mtx_unlock(&psp->ps_mtx);
211         PROC_UNLOCK(p);
212
213         tf->srr0 = (register_t)(p->p_sysent->sv_psstrings -
214             *(p->p_sysent->sv_szsigcode));
215
216         /*
217          * copy the frame out to userland.
218          */
219         if (copyout(sfp, usfp, sfpsize) != 0) {
220                 /*
221                  * Process has trashed its stack. Kill it.
222                  */
223                 CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp);
224                 PROC_LOCK(p);
225                 sigexit(td, SIGILL);
226         }
227
228         CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td,
229              tf->srr0, tf->fixreg[1]);
230
231         PROC_LOCK(p);
232         mtx_lock(&psp->ps_mtx);
233 }
234
235 int
236 sigreturn(struct thread *td, struct sigreturn_args *uap)
237 {
238         ucontext_t uc;
239         int error;
240
241         CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
242
243         if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
244                 CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
245                 return (EFAULT);
246         }
247
248         error = set_mcontext(td, &uc.uc_mcontext);
249         if (error != 0)
250                 return (error);
251
252         kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
253
254         CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
255              td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
256
257         return (EJUSTRETURN);
258 }
259
260 #ifdef COMPAT_FREEBSD4
261 int
262 freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
263 {
264
265         return sigreturn(td, (struct sigreturn_args *)uap);
266 }
267 #endif
268
269 /*
270  * Construct a PCB from a trapframe. This is called from kdb_trap() where
271  * we want to start a backtrace from the function that caused us to enter
272  * the debugger. We have the context in the trapframe, but base the trace
273  * on the PCB. The PCB doesn't have to be perfect, as long as it contains
274  * enough for a backtrace.
275  */
276 void
277 makectx(struct trapframe *tf, struct pcb *pcb)
278 {
279
280         pcb->pcb_lr = tf->srr0;
281         pcb->pcb_sp = tf->fixreg[1];
282 }
283
284 /*
285  * get_mcontext/sendsig helper routine that doesn't touch the
286  * proc lock
287  */
288 static int
289 grab_mcontext(struct thread *td, mcontext_t *mcp, int flags)
290 {
291         struct pcb *pcb;
292
293         pcb = td->td_pcb;
294
295         memset(mcp, 0, sizeof(mcontext_t));
296
297         mcp->mc_vers = _MC_VERSION;
298         mcp->mc_flags = 0;
299         memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe));
300         if (flags & GET_MC_CLEAR_RET) {
301                 mcp->mc_gpr[3] = 0;
302                 mcp->mc_gpr[4] = 0;
303         }
304
305 #ifdef AIM
306         /*
307          * This assumes that floating-point context is *not* lazy,
308          * so if the thread has used FP there would have been a
309          * FP-unavailable exception that would have set things up
310          * correctly.
311          */
312         if (pcb->pcb_flags & PCB_FPU) {
313                 KASSERT(td == curthread,
314                         ("get_mcontext: fp save not curthread"));
315                 critical_enter();
316                 save_fpu(td);
317                 critical_exit();
318                 mcp->mc_flags |= _MC_FP_VALID;
319                 memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
320                 memcpy(mcp->mc_fpreg, pcb->pcb_fpu.fpr, 32*sizeof(double));
321         }
322
323         /*
324          * Repeat for Altivec context
325          */
326
327         if (pcb->pcb_flags & PCB_VEC) {
328                 KASSERT(td == curthread,
329                         ("get_mcontext: fp save not curthread"));
330                 critical_enter();
331                 save_vec(td);
332                 critical_exit();
333                 mcp->mc_flags |= _MC_AV_VALID;
334                 mcp->mc_vscr  = pcb->pcb_vec.vscr;
335                 mcp->mc_vrsave =  pcb->pcb_vec.vrsave;
336                 memcpy(mcp->mc_avec, pcb->pcb_vec.vr, sizeof(mcp->mc_avec));
337         }
338 #endif
339
340         mcp->mc_len = sizeof(*mcp);
341
342         return (0);
343 }
344
345 int
346 get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
347 {
348         int error;
349
350         error = grab_mcontext(td, mcp, flags);
351         if (error == 0) {
352                 PROC_LOCK(curthread->td_proc);
353                 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]);
354                 PROC_UNLOCK(curthread->td_proc);
355         }
356
357         return (error);
358 }
359
360 int
361 set_mcontext(struct thread *td, const mcontext_t *mcp)
362 {
363         struct pcb *pcb;
364         struct trapframe *tf;
365
366         pcb = td->td_pcb;
367         tf = td->td_frame;
368
369         if (mcp->mc_vers != _MC_VERSION || mcp->mc_len != sizeof(*mcp))
370                 return (EINVAL);
371
372         #ifdef AIM
373         /*
374          * Don't let the user set privileged MSR bits
375          */
376         if ((mcp->mc_srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) {
377                 return (EINVAL);
378         }
379         #endif
380
381         memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame));
382
383         #ifdef AIM
384         if (mcp->mc_flags & _MC_FP_VALID) {
385                 if ((pcb->pcb_flags & PCB_FPU) != PCB_FPU) {
386                         critical_enter();
387                         enable_fpu(td);
388                         critical_exit();
389                 }
390                 memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double));
391                 memcpy(pcb->pcb_fpu.fpr, mcp->mc_fpreg, 32*sizeof(double));
392         }
393
394         if (mcp->mc_flags & _MC_AV_VALID) {
395                 if ((pcb->pcb_flags & PCB_VEC) != PCB_VEC) {
396                         critical_enter();
397                         enable_vec(td);
398                         critical_exit();
399                 }
400                 pcb->pcb_vec.vscr = mcp->mc_vscr;
401                 pcb->pcb_vec.vrsave = mcp->mc_vrsave;
402                 memcpy(pcb->pcb_vec.vr, mcp->mc_avec, sizeof(mcp->mc_avec));
403         }
404         #endif
405
406         return (0);
407 }
408
409 /*
410  * Set set up registers on exec.
411  */
412 void
413 exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
414 {
415         struct trapframe        *tf;
416         register_t              argc;
417
418         tf = trapframe(td);
419         bzero(tf, sizeof *tf);
420         tf->fixreg[1] = -roundup(-stack + 8, 16);
421
422         /*
423          * Set up arguments for _start():
424          *      _start(argc, argv, envp, obj, cleanup, ps_strings);
425          *
426          * Notes:
427          *      - obj and cleanup are the auxilliary and termination
428          *        vectors.  They are fixed up by ld.elf_so.
429          *      - ps_strings is a NetBSD extention, and will be
430          *        ignored by executables which are strictly
431          *        compliant with the SVR4 ABI.
432          *
433          * XXX We have to set both regs and retval here due to different
434          * XXX calling convention in trap.c and init_main.c.
435          */
436
437         /* Collect argc from the user stack */
438         argc = fuword((void *)stack);
439
440         /*
441          * XXX PG: these get overwritten in the syscall return code.
442          * execve() should return EJUSTRETURN, like it does on NetBSD.
443          * Emulate by setting the syscall return value cells. The
444          * registers still have to be set for init's fork trampoline.
445          */
446         td->td_retval[0] = argc;
447         td->td_retval[1] = stack + sizeof(register_t);
448         tf->fixreg[3] = argc;
449         tf->fixreg[4] = stack + sizeof(register_t);
450         tf->fixreg[5] = stack + (2 + argc)*sizeof(register_t);
451         tf->fixreg[6] = 0;                              /* auxillary vector */
452         tf->fixreg[7] = 0;                              /* termination vector */
453         tf->fixreg[8] = (register_t)ps_strings;         /* NetBSD extension */
454
455         tf->srr0 = entry;
456         tf->srr1 = PSL_USERSET | PSL_FE_DFLT;
457         td->td_pcb->pcb_flags = 0;
458 }
459
460
461 int
462 fill_regs(struct thread *td, struct reg *regs)
463 {
464         struct trapframe *tf;
465
466         tf = td->td_frame;
467         memcpy(regs, tf, sizeof(struct reg));
468
469         return (0);
470 }
471
472 int
473 fill_dbregs(struct thread *td, struct dbreg *dbregs)
474 {
475         /* No debug registers on PowerPC */
476         return (ENOSYS);
477 }
478
479 int
480 fill_fpregs(struct thread *td, struct fpreg *fpregs)
481 {
482         struct pcb *pcb;
483
484         pcb = td->td_pcb;
485
486         if ((pcb->pcb_flags & PCB_FPU) == 0)
487                 memset(fpregs, 0, sizeof(struct fpreg));
488         else
489                 memcpy(fpregs, &pcb->pcb_fpu, sizeof(struct fpreg));
490
491         return (0);
492 }
493
494 int
495 set_regs(struct thread *td, struct reg *regs)
496 {
497         struct trapframe *tf;
498
499         tf = td->td_frame;
500         memcpy(tf, regs, sizeof(struct reg));
501         
502         return (0);
503 }
504
505 int
506 set_dbregs(struct thread *td, struct dbreg *dbregs)
507 {
508         /* No debug registers on PowerPC */
509         return (ENOSYS);
510 }
511
512 int
513 set_fpregs(struct thread *td, struct fpreg *fpregs)
514 {
515 #ifdef AIM
516         struct pcb *pcb;
517
518         pcb = td->td_pcb;
519         if ((pcb->pcb_flags & PCB_FPU) == 0)
520                 enable_fpu(td);
521         memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg));
522 #endif
523
524         return (0);
525 }
526
527
528
529 void
530 cpu_set_syscall_retval(struct thread *td, int error)
531 {
532         struct proc *p;
533         struct trapframe *tf;
534         int fixup;
535
536         if (error == EJUSTRETURN)
537                 return;
538
539         p = td->td_proc;
540         tf = td->td_frame;
541
542         if (tf->fixreg[0] == SYS___syscall) {
543                 int code = tf->fixreg[FIRSTARG + 1];
544                 if (p->p_sysent->sv_mask)
545                         code &= p->p_sysent->sv_mask;
546                 fixup = (code != SYS_freebsd6_lseek && code != SYS_lseek) ?
547                     1 : 0;
548         } else
549                 fixup = 0;
550
551         switch (error) {
552         case 0:
553                 if (fixup) {
554                         /*
555                          * 64-bit return, 32-bit syscall. Fixup byte order
556                          */
557                         tf->fixreg[FIRSTARG] = 0;
558                         tf->fixreg[FIRSTARG + 1] = td->td_retval[0];
559                 } else {
560                         tf->fixreg[FIRSTARG] = td->td_retval[0];
561                         tf->fixreg[FIRSTARG + 1] = td->td_retval[1];
562                 }
563                 tf->cr &= ~0x10000000;          /* Unset summary overflow */
564                 break;
565         case ERESTART:
566                 /*
567                  * Set user's pc back to redo the system call.
568                  */
569                 tf->srr0 -= 4;
570                 break;
571         default:
572                 if (p->p_sysent->sv_errsize) {
573                         error = (error < p->p_sysent->sv_errsize) ?
574                             p->p_sysent->sv_errtbl[error] : -1;
575                 }
576                 tf->fixreg[FIRSTARG] = error;
577                 tf->cr |= 0x10000000;           /* Set summary overflow */
578                 break;
579         }
580 }
581
582 /*
583  * Threading functions
584  */
585 void
586 cpu_thread_exit(struct thread *td)
587 {
588 }
589
590 void
591 cpu_thread_clean(struct thread *td)
592 {
593 }
594
595 void
596 cpu_thread_alloc(struct thread *td)
597 {
598         struct pcb *pcb;
599
600         pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE -
601             sizeof(struct pcb)) & ~0x2fUL);
602         td->td_pcb = pcb;
603         td->td_frame = (struct trapframe *)pcb - 1;
604 }
605
606 void
607 cpu_thread_free(struct thread *td)
608 {
609 }
610
611 int
612 cpu_set_user_tls(struct thread *td, void *tls_base)
613 {
614
615         td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008;
616         return (0);
617 }
618
619 void
620 cpu_set_upcall(struct thread *td, struct thread *td0)
621 {
622         struct pcb *pcb2;
623         struct trapframe *tf;
624         struct callframe *cf;
625
626         pcb2 = td->td_pcb;
627
628         /* Copy the upcall pcb */
629         bcopy(td0->td_pcb, pcb2, sizeof(*pcb2));
630
631         /* Create a stack for the new thread */
632         tf = td->td_frame;
633         bcopy(td0->td_frame, tf, sizeof(struct trapframe));
634         tf->fixreg[FIRSTARG] = 0;
635         tf->fixreg[FIRSTARG + 1] = 0;
636         tf->cr &= ~0x10000000;
637
638         /* Set registers for trampoline to user mode. */
639         cf = (struct callframe *)tf - 1;
640         memset(cf, 0, sizeof(struct callframe));
641         cf->cf_func = (register_t)fork_return;
642         cf->cf_arg0 = (register_t)td;
643         cf->cf_arg1 = (register_t)tf;
644
645         pcb2->pcb_sp = (register_t)cf;
646         pcb2->pcb_lr = (register_t)fork_trampoline;
647         pcb2->pcb_cpu.aim.usr = 0;
648
649         /* Setup to release spin count in fork_exit(). */
650         td->td_md.md_spinlock_count = 1;
651         td->td_md.md_saved_msr = PSL_KERNSET;
652 }
653
654 void
655 cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
656         stack_t *stack)
657 {
658         struct trapframe *tf;
659         uintptr_t sp;
660
661         tf = td->td_frame;
662         /* align stack and alloc space for frame ptr and saved LR */
663         sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 8) &
664             ~0x1f;
665         bzero(tf, sizeof(struct trapframe));
666
667         tf->fixreg[1] = (register_t)sp;
668         tf->fixreg[3] = (register_t)arg;
669         tf->srr0 = (register_t)entry;
670     #ifdef AIM
671         tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
672     #else
673         tf->srr1 = PSL_USERSET;
674     #endif
675
676         td->td_pcb->pcb_flags = 0;
677
678         td->td_retval[0] = (register_t)entry;
679         td->td_retval[1] = 0;
680 }
681