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

Cache object: 9a522957f710b7741a8fee516e2bec3a


[ 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.