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$");
   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         ksi->ksi_info.si_addr = (void *)((tf->exc == EXC_DSI) ? 
  156             tf->dar : tf->srr0);
  157 
  158         #ifdef COMPAT_FREEBSD32
  159         if (SV_PROC_FLAG(p, SV_ILP32)) {
  160                 siginfo_to_siginfo32(&ksi->ksi_info, &siginfo32);
  161                 sig = siginfo32.si_signo;
  162                 code = siginfo32.si_code;
  163                 sfp = (caddr_t)&sf32;
  164                 sfpsize = sizeof(sf32);
  165                 rndfsize = roundup(sizeof(sf32), 16);
  166 
  167                 /*
  168                  * Save user context
  169                  */
  170 
  171                 memset(&sf32, 0, sizeof(sf32));
  172                 grab_mcontext32(td, &sf32.sf_uc.uc_mcontext, 0);
  173 
  174                 sf32.sf_uc.uc_sigmask = *mask;
  175                 sf32.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
  176                 sf32.sf_uc.uc_stack.ss_size = (uint32_t)td->td_sigstk.ss_size;
  177                 sf32.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
  178                     ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
  179 
  180                 sf32.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
  181         } else {
  182         #endif
  183                 sig = ksi->ksi_signo;
  184                 code = ksi->ksi_code;
  185                 sfp = (caddr_t)&sf;
  186                 sfpsize = sizeof(sf);
  187                 #ifdef __powerpc64__
  188                 /*
  189                  * 64-bit PPC defines a 288 byte scratch region
  190                  * below the stack.
  191                  */
  192                 rndfsize = 288 + roundup(sizeof(sf), 48);
  193                 #else
  194                 rndfsize = roundup(sizeof(sf), 16);
  195                 #endif
  196 
  197                 /*
  198                  * Save user context
  199                  */
  200 
  201                 memset(&sf, 0, sizeof(sf));
  202                 grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0);
  203 
  204                 sf.sf_uc.uc_sigmask = *mask;
  205                 sf.sf_uc.uc_stack = td->td_sigstk;
  206                 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
  207                     ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
  208 
  209                 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
  210         #ifdef COMPAT_FREEBSD32
  211         }
  212         #endif
  213 
  214         CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
  215              catcher, sig);
  216 
  217         /*
  218          * Allocate and validate space for the signal handler context.
  219          */
  220         if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
  221             SIGISMEMBER(psp->ps_sigonstack, sig)) {
  222                 usfp = (void *)(((uintptr_t)td->td_sigstk.ss_sp +
  223                    td->td_sigstk.ss_size - rndfsize) & ~0xFul);
  224         } else {
  225                 usfp = (void *)((tf->fixreg[1] - rndfsize) & ~0xFul);
  226         }
  227 
  228         /*
  229          * Save the floating-point state, if necessary, then copy it.
  230          */
  231         /* XXX */
  232 
  233         /*
  234          * Set up the registers to return to sigcode.
  235          *
  236          *   r1/sp - sigframe ptr
  237          *   lr    - sig function, dispatched to by blrl in trampoline
  238          *   r3    - sig number
  239          *   r4    - SIGINFO ? &siginfo : exception code
  240          *   r5    - user context
  241          *   srr0  - trampoline function addr
  242          */
  243         tf->lr = (register_t)catcher;
  244         tf->fixreg[1] = (register_t)usfp;
  245         tf->fixreg[FIRSTARG] = sig;
  246         #ifdef COMPAT_FREEBSD32
  247         tf->fixreg[FIRSTARG+2] = (register_t)usfp +
  248             ((SV_PROC_FLAG(p, SV_ILP32)) ?
  249             offsetof(struct sigframe32, sf_uc) :
  250             offsetof(struct sigframe, sf_uc));
  251         #else
  252         tf->fixreg[FIRSTARG+2] = (register_t)usfp +
  253             offsetof(struct sigframe, sf_uc);
  254         #endif
  255         if (SIGISMEMBER(psp->ps_siginfo, sig)) {
  256                 /*
  257                  * Signal handler installed with SA_SIGINFO.
  258                  */
  259                 #ifdef COMPAT_FREEBSD32
  260                 if (SV_PROC_FLAG(p, SV_ILP32)) {
  261                         sf32.sf_si = siginfo32;
  262                         tf->fixreg[FIRSTARG+1] = (register_t)usfp +
  263                             offsetof(struct sigframe32, sf_si);
  264                         sf32.sf_si = siginfo32;
  265                 } else  {
  266                 #endif
  267                         tf->fixreg[FIRSTARG+1] = (register_t)usfp +
  268                             offsetof(struct sigframe, sf_si);
  269                         sf.sf_si = ksi->ksi_info;
  270                 #ifdef COMPAT_FREEBSD32
  271                 }
  272                 #endif
  273         } else {
  274                 /* Old FreeBSD-style arguments. */
  275                 tf->fixreg[FIRSTARG+1] = code;
  276                 tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? 
  277                     tf->dar : tf->srr0;
  278         }
  279         mtx_unlock(&psp->ps_mtx);
  280         PROC_UNLOCK(p);
  281 
  282         tf->srr0 = (register_t)p->p_sysent->sv_sigcode_base;
  283 
  284         /*
  285          * copy the frame out to userland.
  286          */
  287         if (copyout(sfp, usfp, sfpsize) != 0) {
  288                 /*
  289                  * Process has trashed its stack. Kill it.
  290                  */
  291                 CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp);
  292                 PROC_LOCK(p);
  293                 sigexit(td, SIGILL);
  294         }
  295 
  296         CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td,
  297              tf->srr0, tf->fixreg[1]);
  298 
  299         PROC_LOCK(p);
  300         mtx_lock(&psp->ps_mtx);
  301 }
  302 
  303 int
  304 sys_sigreturn(struct thread *td, struct sigreturn_args *uap)
  305 {
  306         ucontext_t uc;
  307         int error;
  308 
  309         CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
  310 
  311         if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
  312                 CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
  313                 return (EFAULT);
  314         }
  315 
  316         error = set_mcontext(td, &uc.uc_mcontext);
  317         if (error != 0)
  318                 return (error);
  319 
  320         kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
  321 
  322         CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
  323              td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
  324 
  325         return (EJUSTRETURN);
  326 }
  327 
  328 #ifdef COMPAT_FREEBSD4
  329 int
  330 freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
  331 {
  332 
  333         return sys_sigreturn(td, (struct sigreturn_args *)uap);
  334 }
  335 #endif
  336 
  337 /*
  338  * Construct a PCB from a trapframe. This is called from kdb_trap() where
  339  * we want to start a backtrace from the function that caused us to enter
  340  * the debugger. We have the context in the trapframe, but base the trace
  341  * on the PCB. The PCB doesn't have to be perfect, as long as it contains
  342  * enough for a backtrace.
  343  */
  344 void
  345 makectx(struct trapframe *tf, struct pcb *pcb)
  346 {
  347 
  348         pcb->pcb_lr = tf->srr0;
  349         pcb->pcb_sp = tf->fixreg[1];
  350 }
  351 
  352 /*
  353  * get_mcontext/sendsig helper routine that doesn't touch the
  354  * proc lock
  355  */
  356 static int
  357 grab_mcontext(struct thread *td, mcontext_t *mcp, int flags)
  358 {
  359         struct pcb *pcb;
  360         int i;
  361 
  362         pcb = td->td_pcb;
  363 
  364         memset(mcp, 0, sizeof(mcontext_t));
  365 
  366         mcp->mc_vers = _MC_VERSION;
  367         mcp->mc_flags = 0;
  368         memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe));
  369         if (flags & GET_MC_CLEAR_RET) {
  370                 mcp->mc_gpr[3] = 0;
  371                 mcp->mc_gpr[4] = 0;
  372         }
  373 
  374         /*
  375          * This assumes that floating-point context is *not* lazy,
  376          * so if the thread has used FP there would have been a
  377          * FP-unavailable exception that would have set things up
  378          * correctly.
  379          */
  380         if (pcb->pcb_flags & PCB_FPREGS) {
  381                 if (pcb->pcb_flags & PCB_FPU) {
  382                         KASSERT(td == curthread,
  383                                 ("get_mcontext: fp save not curthread"));
  384                         critical_enter();
  385                         save_fpu(td);
  386                         critical_exit();
  387                 }
  388                 mcp->mc_flags |= _MC_FP_VALID;
  389                 memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
  390                 for (i = 0; i < 32; i++)
  391                         memcpy(&mcp->mc_fpreg[i], &pcb->pcb_fpu.fpr[i].fpr,
  392                             sizeof(double));
  393         }
  394 
  395         if (pcb->pcb_flags & PCB_VSX) {
  396                 for (i = 0; i < 32; i++)
  397                         memcpy(&mcp->mc_vsxfpreg[i],
  398                             &pcb->pcb_fpu.fpr[i].vsr[2], sizeof(double));
  399         }
  400 
  401         /*
  402          * Repeat for Altivec context
  403          */
  404 
  405         if (pcb->pcb_flags & PCB_VEC) {
  406                 KASSERT(td == curthread,
  407                         ("get_mcontext: fp save not curthread"));
  408                 critical_enter();
  409                 save_vec(td);
  410                 critical_exit();
  411                 mcp->mc_flags |= _MC_AV_VALID;
  412                 mcp->mc_vscr  = pcb->pcb_vec.vscr;
  413                 mcp->mc_vrsave =  pcb->pcb_vec.vrsave;
  414                 memcpy(mcp->mc_avec, pcb->pcb_vec.vr, sizeof(mcp->mc_avec));
  415         }
  416 
  417         mcp->mc_len = sizeof(*mcp);
  418 
  419         return (0);
  420 }
  421 
  422 int
  423 get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
  424 {
  425         int error;
  426 
  427         error = grab_mcontext(td, mcp, flags);
  428         if (error == 0) {
  429                 PROC_LOCK(curthread->td_proc);
  430                 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]);
  431                 PROC_UNLOCK(curthread->td_proc);
  432         }
  433 
  434         return (error);
  435 }
  436 
  437 int
  438 set_mcontext(struct thread *td, mcontext_t *mcp)
  439 {
  440         struct pcb *pcb;
  441         struct trapframe *tf;
  442         register_t tls;
  443         int i;
  444 
  445         pcb = td->td_pcb;
  446         tf = td->td_frame;
  447 
  448         if (mcp->mc_vers != _MC_VERSION || mcp->mc_len != sizeof(*mcp))
  449                 return (EINVAL);
  450 
  451         /*
  452          * Don't let the user set privileged MSR bits
  453          */
  454         if ((mcp->mc_srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) {
  455                 return (EINVAL);
  456         }
  457 
  458         /* Copy trapframe, preserving TLS pointer across context change */
  459         if (SV_PROC_FLAG(td->td_proc, SV_LP64))
  460                 tls = tf->fixreg[13];
  461         else
  462                 tls = tf->fixreg[2];
  463         memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame));
  464         if (SV_PROC_FLAG(td->td_proc, SV_LP64))
  465                 tf->fixreg[13] = tls;
  466         else
  467                 tf->fixreg[2] = tls;
  468 
  469         if (mcp->mc_flags & _MC_FP_VALID) {
  470                 /* enable_fpu() will happen lazily on a fault */
  471                 pcb->pcb_flags |= PCB_FPREGS;
  472                 memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double));
  473                 bzero(pcb->pcb_fpu.fpr, sizeof(pcb->pcb_fpu.fpr));
  474                 for (i = 0; i < 32; i++) {
  475                         memcpy(&pcb->pcb_fpu.fpr[i].fpr, &mcp->mc_fpreg[i],
  476                             sizeof(double));
  477                         memcpy(&pcb->pcb_fpu.fpr[i].vsr[2],
  478                             &mcp->mc_vsxfpreg[i], sizeof(double));
  479                 }
  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 
  505         tf = trapframe(td);
  506         bzero(tf, sizeof *tf);
  507         #ifdef __powerpc64__
  508         tf->fixreg[1] = -roundup(-stack + 48, 16);
  509         #else
  510         tf->fixreg[1] = -roundup(-stack + 8, 16);
  511         #endif
  512 
  513         /*
  514          * Set up arguments for _start():
  515          *      _start(argc, argv, envp, obj, cleanup, ps_strings);
  516          *
  517          * Notes:
  518          *      - obj and cleanup are the auxilliary and termination
  519          *        vectors.  They are fixed up by ld.elf_so.
  520          *      - ps_strings is a NetBSD extention, and will be
  521          *        ignored by executables which are strictly
  522          *        compliant with the SVR4 ABI.
  523          *
  524          * XXX We have to set both regs and retval here due to different
  525          * XXX calling convention in trap.c and init_main.c.
  526          */
  527 
  528         /* Collect argc from the user stack */
  529         argc = fuword((void *)stack);
  530 
  531         /*
  532          * XXX PG: these get overwritten in the syscall return code.
  533          * execve() should return EJUSTRETURN, like it does on NetBSD.
  534          * Emulate by setting the syscall return value cells. The
  535          * registers still have to be set for init's fork trampoline.
  536          */
  537         td->td_retval[0] = argc;
  538         td->td_retval[1] = stack + sizeof(register_t);
  539         tf->fixreg[3] = argc;
  540         tf->fixreg[4] = stack + sizeof(register_t);
  541         tf->fixreg[5] = stack + (2 + argc)*sizeof(register_t);
  542         tf->fixreg[6] = 0;                              /* auxillary vector */
  543         tf->fixreg[7] = 0;                              /* termination vector */
  544         tf->fixreg[8] = (register_t)imgp->ps_strings;   /* NetBSD extension */
  545 
  546         tf->srr0 = imgp->entry_addr;
  547         #ifdef __powerpc64__
  548         tf->fixreg[12] = imgp->entry_addr;
  549         tf->srr1 = PSL_SF | PSL_USERSET | PSL_FE_DFLT;
  550         if (mfmsr() & PSL_HV)
  551                 tf->srr1 |= PSL_HV;
  552         #else
  553         tf->srr1 = PSL_USERSET | PSL_FE_DFLT;
  554         #endif
  555         td->td_pcb->pcb_flags = 0;
  556 }
  557 
  558 #ifdef COMPAT_FREEBSD32
  559 void
  560 ppc32_setregs(struct thread *td, struct image_params *imgp, u_long stack)
  561 {
  562         struct trapframe        *tf;
  563         uint32_t                argc;
  564 
  565         tf = trapframe(td);
  566         bzero(tf, sizeof *tf);
  567         tf->fixreg[1] = -roundup(-stack + 8, 16);
  568 
  569         argc = fuword32((void *)stack);
  570 
  571         td->td_retval[0] = argc;
  572         td->td_retval[1] = stack + sizeof(uint32_t);
  573         tf->fixreg[3] = argc;
  574         tf->fixreg[4] = stack + sizeof(uint32_t);
  575         tf->fixreg[5] = stack + (2 + argc)*sizeof(uint32_t);
  576         tf->fixreg[6] = 0;                              /* auxillary vector */
  577         tf->fixreg[7] = 0;                              /* termination vector */
  578         tf->fixreg[8] = (register_t)imgp->ps_strings;   /* NetBSD extension */
  579 
  580         tf->srr0 = imgp->entry_addr;
  581         tf->srr1 = PSL_USERSET | PSL_FE_DFLT;
  582         tf->srr1 &= ~PSL_SF;
  583         if (mfmsr() & PSL_HV)
  584                 tf->srr1 |= PSL_HV;
  585         td->td_pcb->pcb_flags = 0;
  586 }
  587 #endif
  588 
  589 int
  590 fill_regs(struct thread *td, struct reg *regs)
  591 {
  592         struct trapframe *tf;
  593 
  594         tf = td->td_frame;
  595         memcpy(regs, tf, sizeof(struct reg));
  596 
  597         return (0);
  598 }
  599 
  600 int
  601 fill_dbregs(struct thread *td, struct dbreg *dbregs)
  602 {
  603         /* No debug registers on PowerPC */
  604         return (ENOSYS);
  605 }
  606 
  607 int
  608 fill_fpregs(struct thread *td, struct fpreg *fpregs)
  609 {
  610         struct pcb *pcb;
  611         int i;
  612 
  613         pcb = td->td_pcb;
  614 
  615         if ((pcb->pcb_flags & PCB_FPREGS) == 0)
  616                 memset(fpregs, 0, sizeof(struct fpreg));
  617         else {
  618                 memcpy(&fpregs->fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
  619                 for (i = 0; i < 32; i++)
  620                         memcpy(&fpregs->fpreg[i], &pcb->pcb_fpu.fpr[i].fpr,
  621                             sizeof(double));
  622         }
  623 
  624         return (0);
  625 }
  626 
  627 int
  628 set_regs(struct thread *td, struct reg *regs)
  629 {
  630         struct trapframe *tf;
  631 
  632         tf = td->td_frame;
  633         memcpy(tf, regs, sizeof(struct reg));
  634         
  635         return (0);
  636 }
  637 
  638 int
  639 set_dbregs(struct thread *td, struct dbreg *dbregs)
  640 {
  641         /* No debug registers on PowerPC */
  642         return (ENOSYS);
  643 }
  644 
  645 int
  646 set_fpregs(struct thread *td, struct fpreg *fpregs)
  647 {
  648         struct pcb *pcb;
  649         int i;
  650 
  651         pcb = td->td_pcb;
  652         pcb->pcb_flags |= PCB_FPREGS;
  653         memcpy(&pcb->pcb_fpu.fpscr, &fpregs->fpscr, sizeof(double));
  654         for (i = 0; i < 32; i++) {
  655                 memcpy(&pcb->pcb_fpu.fpr[i].fpr, &fpregs->fpreg[i],
  656                     sizeof(double));
  657         }
  658 
  659         return (0);
  660 }
  661 
  662 #ifdef COMPAT_FREEBSD32
  663 int
  664 set_regs32(struct thread *td, struct reg32 *regs)
  665 {
  666         struct trapframe *tf;
  667         int i;
  668 
  669         tf = td->td_frame;
  670         for (i = 0; i < 32; i++)
  671                 tf->fixreg[i] = regs->fixreg[i];
  672         tf->lr = regs->lr;
  673         tf->cr = regs->cr;
  674         tf->xer = regs->xer;
  675         tf->ctr = regs->ctr;
  676         tf->srr0 = regs->pc;
  677 
  678         return (0);
  679 }
  680 
  681 int
  682 fill_regs32(struct thread *td, struct reg32 *regs)
  683 {
  684         struct trapframe *tf;
  685         int i;
  686 
  687         tf = td->td_frame;
  688         for (i = 0; i < 32; i++)
  689                 regs->fixreg[i] = tf->fixreg[i];
  690         regs->lr = tf->lr;
  691         regs->cr = tf->cr;
  692         regs->xer = tf->xer;
  693         regs->ctr = tf->ctr;
  694         regs->pc = tf->srr0;
  695 
  696         return (0);
  697 }
  698 
  699 static int
  700 grab_mcontext32(struct thread *td, mcontext32_t *mcp, int flags)
  701 {
  702         mcontext_t mcp64;
  703         int i, error;
  704 
  705         error = grab_mcontext(td, &mcp64, flags);
  706         if (error != 0)
  707                 return (error);
  708         
  709         mcp->mc_vers = mcp64.mc_vers;
  710         mcp->mc_flags = mcp64.mc_flags;
  711         mcp->mc_onstack = mcp64.mc_onstack;
  712         mcp->mc_len = mcp64.mc_len;
  713         memcpy(mcp->mc_avec,mcp64.mc_avec,sizeof(mcp64.mc_avec));
  714         memcpy(mcp->mc_av,mcp64.mc_av,sizeof(mcp64.mc_av));
  715         for (i = 0; i < 42; i++)
  716                 mcp->mc_frame[i] = mcp64.mc_frame[i];
  717         memcpy(mcp->mc_fpreg,mcp64.mc_fpreg,sizeof(mcp64.mc_fpreg));
  718         memcpy(mcp->mc_vsxfpreg,mcp64.mc_vsxfpreg,sizeof(mcp64.mc_vsxfpreg));
  719 
  720         return (0);
  721 }
  722 
  723 static int
  724 get_mcontext32(struct thread *td, mcontext32_t *mcp, int flags)
  725 {
  726         int error;
  727 
  728         error = grab_mcontext32(td, mcp, flags);
  729         if (error == 0) {
  730                 PROC_LOCK(curthread->td_proc);
  731                 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]);
  732                 PROC_UNLOCK(curthread->td_proc);
  733         }
  734 
  735         return (error);
  736 }
  737 
  738 static int
  739 set_mcontext32(struct thread *td, mcontext32_t *mcp)
  740 {
  741         mcontext_t mcp64;
  742         int i, error;
  743 
  744         mcp64.mc_vers = mcp->mc_vers;
  745         mcp64.mc_flags = mcp->mc_flags;
  746         mcp64.mc_onstack = mcp->mc_onstack;
  747         mcp64.mc_len = mcp->mc_len;
  748         memcpy(mcp64.mc_avec,mcp->mc_avec,sizeof(mcp64.mc_avec));
  749         memcpy(mcp64.mc_av,mcp->mc_av,sizeof(mcp64.mc_av));
  750         for (i = 0; i < 42; i++)
  751                 mcp64.mc_frame[i] = mcp->mc_frame[i];
  752         mcp64.mc_srr1 |= (td->td_frame->srr1 & 0xFFFFFFFF00000000ULL);
  753         memcpy(mcp64.mc_fpreg,mcp->mc_fpreg,sizeof(mcp64.mc_fpreg));
  754         memcpy(mcp64.mc_vsxfpreg,mcp->mc_vsxfpreg,sizeof(mcp64.mc_vsxfpreg));
  755 
  756         error = set_mcontext(td, &mcp64);
  757 
  758         return (error);
  759 }
  760 #endif
  761 
  762 #ifdef COMPAT_FREEBSD32
  763 int
  764 freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap)
  765 {
  766         ucontext32_t uc;
  767         int error;
  768 
  769         CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
  770 
  771         if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
  772                 CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
  773                 return (EFAULT);
  774         }
  775 
  776         error = set_mcontext32(td, &uc.uc_mcontext);
  777         if (error != 0)
  778                 return (error);
  779 
  780         kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
  781 
  782         CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
  783              td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
  784 
  785         return (EJUSTRETURN);
  786 }
  787 
  788 /*
  789  * The first two fields of a ucontext_t are the signal mask and the machine
  790  * context.  The next field is uc_link; we want to avoid destroying the link
  791  * when copying out contexts.
  792  */
  793 #define UC32_COPY_SIZE  offsetof(ucontext32_t, uc_link)
  794 
  795 int
  796 freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap)
  797 {
  798         ucontext32_t uc;
  799         int ret;
  800 
  801         if (uap->ucp == NULL)
  802                 ret = EINVAL;
  803         else {
  804                 bzero(&uc, sizeof(uc));
  805                 get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
  806                 PROC_LOCK(td->td_proc);
  807                 uc.uc_sigmask = td->td_sigmask;
  808                 PROC_UNLOCK(td->td_proc);
  809                 ret = copyout(&uc, uap->ucp, UC32_COPY_SIZE);
  810         }
  811         return (ret);
  812 }
  813 
  814 int
  815 freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap)
  816 {
  817         ucontext32_t uc;
  818         int ret;        
  819 
  820         if (uap->ucp == NULL)
  821                 ret = EINVAL;
  822         else {
  823                 ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE);
  824                 if (ret == 0) {
  825                         ret = set_mcontext32(td, &uc.uc_mcontext);
  826                         if (ret == 0) {
  827                                 kern_sigprocmask(td, SIG_SETMASK,
  828                                     &uc.uc_sigmask, NULL, 0);
  829                         }
  830                 }
  831         }
  832         return (ret == 0 ? EJUSTRETURN : ret);
  833 }
  834 
  835 int
  836 freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
  837 {
  838         ucontext32_t uc;
  839         int ret;
  840 
  841         if (uap->oucp == NULL || uap->ucp == NULL)
  842                 ret = EINVAL;
  843         else {
  844                 bzero(&uc, sizeof(uc));
  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 = (
  885 #if defined(COMPAT_FREEBSD6) && defined(SYS_freebsd6_lseek)
  886                     code != SYS_freebsd6_lseek &&
  887 #endif
  888                     code != SYS_lseek) ?  1 : 0;
  889         } else
  890                 fixup = 0;
  891 
  892         switch (error) {
  893         case 0:
  894                 if (fixup) {
  895                         /*
  896                          * 64-bit return, 32-bit syscall. Fixup byte order
  897                          */
  898                         tf->fixreg[FIRSTARG] = 0;
  899                         tf->fixreg[FIRSTARG + 1] = td->td_retval[0];
  900                 } else {
  901                         tf->fixreg[FIRSTARG] = td->td_retval[0];
  902                         tf->fixreg[FIRSTARG + 1] = td->td_retval[1];
  903                 }
  904                 tf->cr &= ~0x10000000;          /* Unset summary overflow */
  905                 break;
  906         case ERESTART:
  907                 /*
  908                  * Set user's pc back to redo the system call.
  909                  */
  910                 tf->srr0 -= 4;
  911                 break;
  912         default:
  913                 tf->fixreg[FIRSTARG] = SV_ABI_ERRNO(p, error);
  914                 tf->cr |= 0x10000000;           /* Set summary overflow */
  915                 break;
  916         }
  917 }
  918 
  919 /*
  920  * Threading functions
  921  */
  922 void
  923 cpu_thread_exit(struct thread *td)
  924 {
  925 }
  926 
  927 void
  928 cpu_thread_clean(struct thread *td)
  929 {
  930 }
  931 
  932 void
  933 cpu_thread_alloc(struct thread *td)
  934 {
  935         struct pcb *pcb;
  936 
  937         pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE -
  938             sizeof(struct pcb)) & ~0x2fUL);
  939         td->td_pcb = pcb;
  940         td->td_frame = (struct trapframe *)pcb - 1;
  941 }
  942 
  943 void
  944 cpu_thread_free(struct thread *td)
  945 {
  946 }
  947 
  948 int
  949 cpu_set_user_tls(struct thread *td, void *tls_base)
  950 {
  951 
  952         if (SV_PROC_FLAG(td->td_proc, SV_LP64))
  953                 td->td_frame->fixreg[13] = (register_t)tls_base + 0x7010;
  954         else
  955                 td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008;
  956         return (0);
  957 }
  958 
  959 void
  960 cpu_copy_thread(struct thread *td, struct thread *td0)
  961 {
  962         struct pcb *pcb2;
  963         struct trapframe *tf;
  964         struct callframe *cf;
  965 
  966         pcb2 = td->td_pcb;
  967 
  968         /* Copy the upcall pcb */
  969         bcopy(td0->td_pcb, pcb2, sizeof(*pcb2));
  970 
  971         /* Create a stack for the new thread */
  972         tf = td->td_frame;
  973         bcopy(td0->td_frame, tf, sizeof(struct trapframe));
  974         tf->fixreg[FIRSTARG] = 0;
  975         tf->fixreg[FIRSTARG + 1] = 0;
  976         tf->cr &= ~0x10000000;
  977 
  978         /* Set registers for trampoline to user mode. */
  979         cf = (struct callframe *)tf - 1;
  980         memset(cf, 0, sizeof(struct callframe));
  981         cf->cf_func = (register_t)fork_return;
  982         cf->cf_arg0 = (register_t)td;
  983         cf->cf_arg1 = (register_t)tf;
  984 
  985         pcb2->pcb_sp = (register_t)cf;
  986         #if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1)
  987         pcb2->pcb_lr = ((register_t *)fork_trampoline)[0];
  988         pcb2->pcb_toc = ((register_t *)fork_trampoline)[1];
  989         #else
  990         pcb2->pcb_lr = (register_t)fork_trampoline;
  991         pcb2->pcb_context[0] = pcb2->pcb_lr;
  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(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, &pcb->pcb_fpu);
 1075 #endif
 1076 
 1077         return (sig);
 1078 }
 1079 

Cache object: 5b09ca5f8e20aaf1549882d76fb06031


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