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

Cache object: 9741009503b9d63b29f9ce51678ec783


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