The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/powerpc/powerpc/exec_machdep.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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: releng/8.3/sys/powerpc/powerpc/exec_machdep.c 211595 2010-08-22 00:04:24Z nwhitehorn $");
   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 

Cache object: 356fa3daf03f8104bb8a44905928cd1f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.