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/amd64/ia32/ia32_signal.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-3-Clause
    3  *
    4  * Copyright (c) 2003 Peter Wemm
    5  * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to Berkeley by
    9  * William Jolitz.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. Neither the name of the University nor the names of its contributors
   20  *    may be used to endorse or promote products derived from this software
   21  *    without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  */
   35 
   36 #include <sys/cdefs.h>
   37 __FBSDID("$FreeBSD$");
   38 
   39 #include <sys/param.h>
   40 #include <sys/exec.h>
   41 #include <sys/fcntl.h>
   42 #include <sys/imgact.h>
   43 #include <sys/kernel.h>
   44 #include <sys/lock.h>
   45 #include <sys/malloc.h>
   46 #include <sys/mutex.h>
   47 #include <sys/mman.h>
   48 #include <sys/namei.h>
   49 #include <sys/proc.h>
   50 #include <sys/procfs.h>
   51 #include <sys/resourcevar.h>
   52 #include <sys/systm.h>
   53 #include <sys/signalvar.h>
   54 #include <sys/stat.h>
   55 #include <sys/sx.h>
   56 #include <sys/syscall.h>
   57 #include <sys/syscallsubr.h>
   58 #include <sys/sysctl.h>
   59 #include <sys/sysent.h>
   60 #include <sys/vnode.h>
   61 
   62 #include <vm/vm.h>
   63 #include <vm/vm_kern.h>
   64 #include <vm/vm_param.h>
   65 #include <vm/pmap.h>
   66 #include <vm/vm_map.h>
   67 #include <vm/vm_object.h>
   68 #include <vm/vm_extern.h>
   69 
   70 #include <compat/freebsd32/freebsd32_signal.h>
   71 #include <compat/freebsd32/freebsd32_util.h>
   72 #include <compat/freebsd32/freebsd32_proto.h>
   73 #include <compat/freebsd32/freebsd32.h>
   74 #include <compat/ia32/ia32_signal.h>
   75 #include <machine/psl.h>
   76 #include <machine/segments.h>
   77 #include <machine/specialreg.h>
   78 #include <machine/frame.h>
   79 #include <machine/md_var.h>
   80 #include <machine/pcb.h>
   81 #include <machine/cpufunc.h>
   82 #include <machine/trap.h>
   83 
   84 #include "vdso_ia32_offsets.h"
   85 
   86 extern const char _binary_elf_vdso32_so_1_start[];
   87 extern const char _binary_elf_vdso32_so_1_end[];
   88 extern char _binary_elf_vdso32_so_1_size;
   89 
   90 #ifdef COMPAT_FREEBSD4
   91 static void freebsd4_ia32_sendsig(sig_t, ksiginfo_t *, sigset_t *);
   92 #endif
   93 
   94 static void
   95 ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp,
   96     char **xfpusave, size_t *xfpusave_len)
   97 {
   98         /*
   99          * XXX Format of 64bit and 32bit FXSAVE areas differs. FXSAVE
  100          * in 32bit mode saves %cs and %ds, while on 64bit it saves
  101          * 64bit instruction and data pointers. Ignore the difference
  102          * for now, it should be irrelevant for most applications.
  103          */
  104         mcp->mc_ownedfp = fpugetregs(td);
  105         bcopy(get_pcb_user_save_td(td), &mcp->mc_fpstate[0],
  106             sizeof(mcp->mc_fpstate));
  107         mcp->mc_fpformat = fpuformat();
  108         if (xfpusave == NULL)
  109                 return;
  110         if (!use_xsave || cpu_max_ext_state_size <= sizeof(struct savefpu)) {
  111                 *xfpusave_len = 0;
  112                 *xfpusave = NULL;
  113         } else {
  114                 mcp->mc_flags |= _MC_IA32_HASFPXSTATE;
  115                 *xfpusave_len = mcp->mc_xfpustate_len =
  116                     cpu_max_ext_state_size - sizeof(struct savefpu);
  117                 *xfpusave = (char *)(get_pcb_user_save_td(td) + 1);
  118         }
  119 }
  120 
  121 static int
  122 ia32_set_fpcontext(struct thread *td, struct ia32_mcontext *mcp,
  123     char *xfpustate, size_t xfpustate_len)
  124 {
  125         int error;
  126 
  127         if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
  128                 return (0);
  129         else if (mcp->mc_fpformat != _MC_FPFMT_XMM)
  130                 return (EINVAL);
  131         else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) {
  132                 /* We don't care what state is left in the FPU or PCB. */
  133                 fpstate_drop(td);
  134                 error = 0;
  135         } else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
  136             mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
  137                 error = fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate,
  138                     xfpustate, xfpustate_len);
  139         } else
  140                 return (EINVAL);
  141         return (error);
  142 }
  143 
  144 /*
  145  * Get machine context.
  146  */
  147 static int
  148 ia32_get_mcontext(struct thread *td, struct ia32_mcontext *mcp, int flags)
  149 {
  150         struct pcb *pcb;
  151         struct trapframe *tp;
  152 
  153         pcb = td->td_pcb;
  154         tp = td->td_frame;
  155 
  156         PROC_LOCK(curthread->td_proc);
  157         mcp->mc_onstack = sigonstack(tp->tf_rsp);
  158         PROC_UNLOCK(curthread->td_proc);
  159         /* Entry into kernel always sets TF_HASSEGS */
  160         mcp->mc_gs = tp->tf_gs;
  161         mcp->mc_fs = tp->tf_fs;
  162         mcp->mc_es = tp->tf_es;
  163         mcp->mc_ds = tp->tf_ds;
  164         mcp->mc_edi = tp->tf_rdi;
  165         mcp->mc_esi = tp->tf_rsi;
  166         mcp->mc_ebp = tp->tf_rbp;
  167         mcp->mc_isp = tp->tf_rsp;
  168         mcp->mc_eflags = tp->tf_rflags;
  169         if (flags & GET_MC_CLEAR_RET) {
  170                 mcp->mc_eax = 0;
  171                 mcp->mc_edx = 0;
  172                 mcp->mc_eflags &= ~PSL_C;
  173         } else {
  174                 mcp->mc_eax = tp->tf_rax;
  175                 mcp->mc_edx = tp->tf_rdx;
  176         }
  177         mcp->mc_ebx = tp->tf_rbx;
  178         mcp->mc_ecx = tp->tf_rcx;
  179         mcp->mc_eip = tp->tf_rip;
  180         mcp->mc_cs = tp->tf_cs;
  181         mcp->mc_esp = tp->tf_rsp;
  182         mcp->mc_ss = tp->tf_ss;
  183         mcp->mc_len = sizeof(*mcp);
  184         mcp->mc_flags = tp->tf_flags;
  185         ia32_get_fpcontext(td, mcp, NULL, 0);
  186         mcp->mc_fsbase = pcb->pcb_fsbase;
  187         mcp->mc_gsbase = pcb->pcb_gsbase;
  188         mcp->mc_xfpustate = 0;
  189         mcp->mc_xfpustate_len = 0;
  190         bzero(mcp->mc_spare2, sizeof(mcp->mc_spare2));
  191         return (0);
  192 }
  193 
  194 /*
  195  * Set machine context.
  196  *
  197  * However, we don't set any but the user modifiable flags, and we won't
  198  * touch the cs selector.
  199  */
  200 static int
  201 ia32_set_mcontext(struct thread *td, struct ia32_mcontext *mcp)
  202 {
  203         struct trapframe *tp;
  204         char *xfpustate;
  205         long rflags;
  206         int ret;
  207 
  208         tp = td->td_frame;
  209         if (mcp->mc_len != sizeof(*mcp))
  210                 return (EINVAL);
  211         rflags = (mcp->mc_eflags & PSL_USERCHANGE) |
  212             (tp->tf_rflags & ~PSL_USERCHANGE);
  213         if (mcp->mc_flags & _MC_IA32_HASFPXSTATE) {
  214                 if (mcp->mc_xfpustate_len > cpu_max_ext_state_size -
  215                     sizeof(struct savefpu))
  216                         return (EINVAL);
  217                 xfpustate = (char *)fpu_save_area_alloc();
  218                 ret = copyin(PTRIN(mcp->mc_xfpustate), xfpustate,
  219                     mcp->mc_xfpustate_len);
  220                 if (ret != 0) {
  221                         fpu_save_area_free((struct savefpu *)xfpustate);
  222                         return (ret);
  223                 }
  224         } else
  225                 xfpustate = NULL;
  226         ret = ia32_set_fpcontext(td, mcp, xfpustate, mcp->mc_xfpustate_len);
  227         fpu_save_area_free((struct savefpu *)xfpustate);
  228         if (ret != 0)
  229                 return (ret);
  230         tp->tf_gs = mcp->mc_gs;
  231         tp->tf_fs = mcp->mc_fs;
  232         tp->tf_es = mcp->mc_es;
  233         tp->tf_ds = mcp->mc_ds;
  234         tp->tf_flags = TF_HASSEGS;
  235         tp->tf_rdi = mcp->mc_edi;
  236         tp->tf_rsi = mcp->mc_esi;
  237         tp->tf_rbp = mcp->mc_ebp;
  238         tp->tf_rbx = mcp->mc_ebx;
  239         tp->tf_rdx = mcp->mc_edx;
  240         tp->tf_rcx = mcp->mc_ecx;
  241         tp->tf_rax = mcp->mc_eax;
  242         /* trapno, err */
  243         tp->tf_rip = mcp->mc_eip;
  244         tp->tf_rflags = rflags;
  245         tp->tf_rsp = mcp->mc_esp;
  246         tp->tf_ss = mcp->mc_ss;
  247         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
  248         return (0);
  249 }
  250 
  251 /*
  252  * The first two fields of a ucontext_t are the signal mask and
  253  * the machine context.  The next field is uc_link; we want to
  254  * avoid destroying the link when copying out contexts.
  255  */
  256 #define UC_COPY_SIZE    offsetof(struct ia32_ucontext, uc_link)
  257 
  258 int
  259 freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap)
  260 {
  261         struct ia32_ucontext uc;
  262         int ret;
  263 
  264         if (uap->ucp == NULL)
  265                 ret = EINVAL;
  266         else {
  267                 bzero(&uc, sizeof(uc));
  268                 ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
  269                 PROC_LOCK(td->td_proc);
  270                 uc.uc_sigmask = td->td_sigmask;
  271                 PROC_UNLOCK(td->td_proc);
  272                 ret = copyout(&uc, uap->ucp, UC_COPY_SIZE);
  273         }
  274         return (ret);
  275 }
  276 
  277 int
  278 freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap)
  279 {
  280         struct ia32_ucontext uc;
  281         int ret;
  282 
  283         if (uap->ucp == NULL)
  284                 ret = EINVAL;
  285         else {
  286                 ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
  287                 if (ret == 0) {
  288                         ret = ia32_set_mcontext(td, &uc.uc_mcontext);
  289                         if (ret == 0) {
  290                                 kern_sigprocmask(td, SIG_SETMASK,
  291                                     &uc.uc_sigmask, NULL, 0);
  292                         }
  293                 }
  294         }
  295         return (ret == 0 ? EJUSTRETURN : ret);
  296 }
  297 
  298 int
  299 freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
  300 {
  301         struct ia32_ucontext uc;
  302         int ret;
  303 
  304         if (uap->oucp == NULL || uap->ucp == NULL)
  305                 ret = EINVAL;
  306         else {
  307                 bzero(&uc, sizeof(uc));
  308                 ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
  309                 PROC_LOCK(td->td_proc);
  310                 uc.uc_sigmask = td->td_sigmask;
  311                 PROC_UNLOCK(td->td_proc);
  312                 ret = copyout(&uc, uap->oucp, UC_COPY_SIZE);
  313                 if (ret == 0) {
  314                         ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
  315                         if (ret == 0) {
  316                                 ret = ia32_set_mcontext(td, &uc.uc_mcontext);
  317                                 if (ret == 0) {
  318                                         kern_sigprocmask(td, SIG_SETMASK,
  319                                             &uc.uc_sigmask, NULL, 0);
  320                                 }
  321                         }
  322                 }
  323         }
  324         return (ret == 0 ? EJUSTRETURN : ret);
  325 }
  326 
  327 /*
  328  * Send an interrupt to process.
  329  *
  330  * Stack is set up to allow sigcode stored
  331  * at top to call routine, followed by kcall
  332  * to sigreturn routine below.  After sigreturn
  333  * resets the signal mask, the stack, and the
  334  * frame pointer, it returns to the user
  335  * specified pc, psl.
  336  */
  337 
  338 #ifdef COMPAT_43
  339 static void
  340 ia32_osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
  341 {
  342         struct ia32_osigframe sf, *fp;
  343         struct proc *p;
  344         struct thread *td;
  345         struct sigacts *psp;
  346         struct trapframe *regs;
  347         int sig;
  348         int oonstack;
  349 
  350         td = curthread;
  351         p = td->td_proc;
  352         PROC_LOCK_ASSERT(p, MA_OWNED);
  353         sig = ksi->ksi_signo;
  354         psp = p->p_sigacts;
  355         mtx_assert(&psp->ps_mtx, MA_OWNED);
  356         regs = td->td_frame;
  357         oonstack = sigonstack(regs->tf_rsp);
  358 
  359         /* Allocate space for the signal handler context. */
  360         if ((td->td_pflags & TDP_ALTSTACK) && !oonstack &&
  361             SIGISMEMBER(psp->ps_sigonstack, sig)) {
  362                 fp = (struct ia32_osigframe *)((uintptr_t)td->td_sigstk.ss_sp +
  363                     td->td_sigstk.ss_size - sizeof(sf));
  364                 td->td_sigstk.ss_flags |= SS_ONSTACK;
  365         } else
  366                 fp = (struct ia32_osigframe *)regs->tf_rsp - 1;
  367 
  368         /* Build the argument list for the signal handler. */
  369         sf.sf_signum = sig;
  370         sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc;
  371         bzero(&sf.sf_siginfo, sizeof(sf.sf_siginfo));
  372         if (SIGISMEMBER(psp->ps_siginfo, sig)) {
  373                 /* Signal handler installed with SA_SIGINFO. */
  374                 sf.sf_arg2 = (register_t)&fp->sf_siginfo;
  375                 sf.sf_siginfo.si_signo = sig;
  376                 sf.sf_siginfo.si_code = ksi->ksi_code;
  377                 sf.sf_ah = (uintptr_t)catcher;
  378                 sf.sf_addr = 0;
  379         } else {
  380                 /* Old FreeBSD-style arguments. */
  381                 sf.sf_arg2 = ksi->ksi_code;
  382                 sf.sf_addr = (register_t)ksi->ksi_addr;
  383                 sf.sf_ah = (uintptr_t)catcher;
  384         }
  385         mtx_unlock(&psp->ps_mtx);
  386         PROC_UNLOCK(p);
  387 
  388         /* Save most if not all of trap frame. */
  389         sf.sf_siginfo.si_sc.sc_eax = regs->tf_rax;
  390         sf.sf_siginfo.si_sc.sc_ebx = regs->tf_rbx;
  391         sf.sf_siginfo.si_sc.sc_ecx = regs->tf_rcx;
  392         sf.sf_siginfo.si_sc.sc_edx = regs->tf_rdx;
  393         sf.sf_siginfo.si_sc.sc_esi = regs->tf_rsi;
  394         sf.sf_siginfo.si_sc.sc_edi = regs->tf_rdi;
  395         sf.sf_siginfo.si_sc.sc_cs = regs->tf_cs;
  396         sf.sf_siginfo.si_sc.sc_ds = regs->tf_ds;
  397         sf.sf_siginfo.si_sc.sc_ss = regs->tf_ss;
  398         sf.sf_siginfo.si_sc.sc_es = regs->tf_es;
  399         sf.sf_siginfo.si_sc.sc_fs = regs->tf_fs;
  400         sf.sf_siginfo.si_sc.sc_gs = regs->tf_gs;
  401         sf.sf_siginfo.si_sc.sc_isp = regs->tf_rsp;
  402 
  403         /* Build the signal context to be used by osigreturn(). */
  404         sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0;
  405         SIG2OSIG(*mask, sf.sf_siginfo.si_sc.sc_mask);
  406         sf.sf_siginfo.si_sc.sc_esp = regs->tf_rsp;
  407         sf.sf_siginfo.si_sc.sc_ebp = regs->tf_rbp;
  408         sf.sf_siginfo.si_sc.sc_eip = regs->tf_rip;
  409         sf.sf_siginfo.si_sc.sc_eflags = regs->tf_rflags;
  410         sf.sf_siginfo.si_sc.sc_trapno = regs->tf_trapno;
  411         sf.sf_siginfo.si_sc.sc_err = regs->tf_err;
  412 
  413         /*
  414          * Copy the sigframe out to the user's stack.
  415          */
  416         if (copyout(&sf, fp, sizeof(*fp)) != 0) {
  417 #ifdef DEBUG
  418                 printf("process %ld has trashed its stack\n", (long)p->p_pid);
  419 #endif
  420                 PROC_LOCK(p);
  421                 sigexit(td, SIGILL);
  422         }
  423 
  424         regs->tf_rsp = (uintptr_t)fp;
  425         regs->tf_rip = PROC_PS_STRINGS(p) -
  426             (_binary_elf_vdso32_so_1_end - _binary_elf_vdso32_so_1_start) +
  427             VDSO_IA32_OSIGCODE_OFFSET;
  428         regs->tf_rflags &= ~(PSL_T | PSL_D);
  429         regs->tf_cs = _ucode32sel;
  430         regs->tf_ds = _udatasel;
  431         regs->tf_es = _udatasel;
  432         regs->tf_fs = _udatasel;
  433         regs->tf_ss = _udatasel;
  434         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
  435         PROC_LOCK(p);
  436         mtx_lock(&psp->ps_mtx);
  437 }
  438 #endif
  439 
  440 #ifdef COMPAT_FREEBSD4
  441 static void
  442 freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
  443 {
  444         struct ia32_freebsd4_sigframe sf, *sfp;
  445         struct siginfo32 siginfo;
  446         struct proc *p;
  447         struct thread *td;
  448         struct sigacts *psp;
  449         struct trapframe *regs;
  450         int oonstack;
  451         int sig;
  452 
  453         td = curthread;
  454         p = td->td_proc;
  455         siginfo_to_siginfo32(&ksi->ksi_info, &siginfo);
  456 
  457         PROC_LOCK_ASSERT(p, MA_OWNED);
  458         sig = siginfo.si_signo;
  459         psp = p->p_sigacts;
  460         mtx_assert(&psp->ps_mtx, MA_OWNED);
  461         regs = td->td_frame;
  462         oonstack = sigonstack(regs->tf_rsp);
  463 
  464         /* Save user context. */
  465         bzero(&sf, sizeof(sf));
  466         sf.sf_uc.uc_sigmask = *mask;
  467         sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
  468         sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size;
  469         sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
  470             ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
  471         sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
  472         sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi;
  473         sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi;
  474         sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp;
  475         sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */
  476         sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx;
  477         sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx;
  478         sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx;
  479         sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax;
  480         sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno;
  481         sf.sf_uc.uc_mcontext.mc_err = regs->tf_err;
  482         sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip;
  483         sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs;
  484         sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags;
  485         sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp;
  486         sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss;
  487         sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds;
  488         sf.sf_uc.uc_mcontext.mc_es = regs->tf_es;
  489         sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs;
  490         sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs;
  491         bzero(sf.sf_uc.uc_mcontext.mc_fpregs,
  492             sizeof(sf.sf_uc.uc_mcontext.mc_fpregs));
  493         bzero(sf.sf_uc.uc_mcontext.__spare__,
  494             sizeof(sf.sf_uc.uc_mcontext.__spare__));
  495         bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__));
  496 
  497         /* Allocate space for the signal handler context. */
  498         if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
  499             SIGISMEMBER(psp->ps_sigonstack, sig)) {
  500                 sfp = (struct ia32_freebsd4_sigframe *)((uintptr_t)td->td_sigstk.ss_sp +
  501                     td->td_sigstk.ss_size - sizeof(sf));
  502         } else
  503                 sfp = (struct ia32_freebsd4_sigframe *)regs->tf_rsp - 1;
  504         PROC_UNLOCK(p);
  505 
  506         /* Build the argument list for the signal handler. */
  507         sf.sf_signum = sig;
  508         sf.sf_ucontext = (register_t)&sfp->sf_uc;
  509         bzero(&sf.sf_si, sizeof(sf.sf_si));
  510         if (SIGISMEMBER(psp->ps_siginfo, sig)) {
  511                 /* Signal handler installed with SA_SIGINFO. */
  512                 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si;
  513                 sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
  514 
  515                 /* Fill in POSIX parts */
  516                 sf.sf_si = siginfo;
  517                 sf.sf_si.si_signo = sig;
  518         } else {
  519                 /* Old FreeBSD-style arguments. */
  520                 sf.sf_siginfo = siginfo.si_code;
  521                 sf.sf_addr = (u_int32_t)siginfo.si_addr;
  522                 sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
  523         }
  524         mtx_unlock(&psp->ps_mtx);
  525 
  526         /*
  527          * Copy the sigframe out to the user's stack.
  528          */
  529         if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
  530 #ifdef DEBUG
  531                 printf("process %ld has trashed its stack\n", (long)p->p_pid);
  532 #endif
  533                 PROC_LOCK(p);
  534                 sigexit(td, SIGILL);
  535         }
  536 
  537         regs->tf_rsp = (uintptr_t)sfp;
  538         regs->tf_rip = PROC_SIGCODE(p) +
  539             VDSO_FREEBSD4_IA32_SIGCODE_OFFSET - VDSO_IA32_SIGCODE_OFFSET;
  540         regs->tf_rflags &= ~(PSL_T | PSL_D);
  541         regs->tf_cs = _ucode32sel;
  542         regs->tf_ss = _udatasel;
  543         regs->tf_ds = _udatasel;
  544         regs->tf_es = _udatasel;
  545         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
  546         /* leave user %fs and %gs untouched */
  547         PROC_LOCK(p);
  548         mtx_lock(&psp->ps_mtx);
  549 }
  550 #endif  /* COMPAT_FREEBSD4 */
  551 
  552 void
  553 ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
  554 {
  555         struct ia32_sigframe sf, *sfp;
  556         struct siginfo32 siginfo;
  557         struct proc *p;
  558         struct thread *td;
  559         struct sigacts *psp;
  560         char *sp;
  561         struct trapframe *regs;
  562         char *xfpusave;
  563         size_t xfpusave_len;
  564         int oonstack;
  565         int sig;
  566 
  567         siginfo_to_siginfo32(&ksi->ksi_info, &siginfo);
  568         td = curthread;
  569         p = td->td_proc;
  570         PROC_LOCK_ASSERT(p, MA_OWNED);
  571         sig = siginfo.si_signo;
  572         psp = p->p_sigacts;
  573 #ifdef COMPAT_FREEBSD4
  574         if (SIGISMEMBER(psp->ps_freebsd4, sig)) {
  575                 freebsd4_ia32_sendsig(catcher, ksi, mask);
  576                 return;
  577         }
  578 #endif
  579 #ifdef COMPAT_43
  580         if (SIGISMEMBER(psp->ps_osigset, sig)) {
  581                 ia32_osendsig(catcher, ksi, mask);
  582                 return;
  583         }
  584 #endif
  585         mtx_assert(&psp->ps_mtx, MA_OWNED);
  586         regs = td->td_frame;
  587         oonstack = sigonstack(regs->tf_rsp);
  588 
  589         /* Save user context. */
  590         bzero(&sf, sizeof(sf));
  591         sf.sf_uc.uc_sigmask = *mask;
  592         sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
  593         sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size;
  594         sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
  595             ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
  596         sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
  597         sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi;
  598         sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi;
  599         sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp;
  600         sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */
  601         sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx;
  602         sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx;
  603         sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx;
  604         sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax;
  605         sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno;
  606         sf.sf_uc.uc_mcontext.mc_err = regs->tf_err;
  607         sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip;
  608         sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs;
  609         sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags;
  610         sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp;
  611         sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss;
  612         sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds;
  613         sf.sf_uc.uc_mcontext.mc_es = regs->tf_es;
  614         sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs;
  615         sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs;
  616         sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
  617         ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext, &xfpusave, &xfpusave_len);
  618         sf.sf_uc.uc_mcontext.mc_fsbase = td->td_pcb->pcb_fsbase;
  619         sf.sf_uc.uc_mcontext.mc_gsbase = td->td_pcb->pcb_gsbase;
  620 
  621         /* Allocate space for the signal handler context. */
  622         if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
  623             SIGISMEMBER(psp->ps_sigonstack, sig))
  624                 sp = (char *)td->td_sigstk.ss_sp + td->td_sigstk.ss_size;
  625         else
  626                 sp = (char *)regs->tf_rsp;
  627         if (xfpusave != NULL) {
  628                 sp -= xfpusave_len;
  629                 sp = (char *)((unsigned long)sp & ~0x3Ful);
  630                 sf.sf_uc.uc_mcontext.mc_xfpustate = (register_t)sp;
  631         }
  632         sp -= sizeof(sf);
  633         /* Align to 16 bytes. */
  634         sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF);
  635         PROC_UNLOCK(p);
  636 
  637         /* Build the argument list for the signal handler. */
  638         sf.sf_signum = sig;
  639         sf.sf_ucontext = (register_t)&sfp->sf_uc;
  640         bzero(&sf.sf_si, sizeof(sf.sf_si));
  641         if (SIGISMEMBER(psp->ps_siginfo, sig)) {
  642                 /* Signal handler installed with SA_SIGINFO. */
  643                 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si;
  644                 sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
  645 
  646                 /* Fill in POSIX parts */
  647                 sf.sf_si = siginfo;
  648                 sf.sf_si.si_signo = sig;
  649         } else {
  650                 /* Old FreeBSD-style arguments. */
  651                 sf.sf_siginfo = siginfo.si_code;
  652                 sf.sf_addr = (u_int32_t)siginfo.si_addr;
  653                 sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
  654         }
  655         mtx_unlock(&psp->ps_mtx);
  656 
  657         /*
  658          * Copy the sigframe out to the user's stack.
  659          */
  660         if (copyout(&sf, sfp, sizeof(*sfp)) != 0 ||
  661             (xfpusave != NULL && copyout(xfpusave,
  662             PTRIN(sf.sf_uc.uc_mcontext.mc_xfpustate), xfpusave_len)
  663             != 0)) {
  664 #ifdef DEBUG
  665                 printf("process %ld has trashed its stack\n", (long)p->p_pid);
  666 #endif
  667                 PROC_LOCK(p);
  668                 sigexit(td, SIGILL);
  669         }
  670 
  671         fpstate_drop(td);
  672         regs->tf_rsp = (uintptr_t)sfp;
  673         regs->tf_rip = PROC_SIGCODE(p);
  674         regs->tf_rflags &= ~(PSL_T | PSL_D);
  675         regs->tf_cs = _ucode32sel;
  676         regs->tf_ss = _udatasel;
  677         regs->tf_ds = _udatasel;
  678         regs->tf_es = _udatasel;
  679         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
  680         /* XXXKIB leave user %fs and %gs untouched */
  681         PROC_LOCK(p);
  682         mtx_lock(&psp->ps_mtx);
  683 }
  684 
  685 /*
  686  * System call to cleanup state after a signal
  687  * has been taken.  Reset signal mask and
  688  * stack state from context left by sendsig (above).
  689  * Return to previous pc and psl as specified by
  690  * context left by sendsig. Check carefully to
  691  * make sure that the user has not modified the
  692  * state to gain improper privileges.
  693  */
  694 
  695 #ifdef COMPAT_43
  696 int
  697 ofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap)
  698 {
  699         struct ia32_osigcontext sc, *scp;
  700         struct trapframe *regs;
  701         int eflags, error;
  702         ksiginfo_t ksi;
  703 
  704         regs = td->td_frame;
  705         error = copyin(uap->sigcntxp, &sc, sizeof(sc));
  706         if (error != 0)
  707                 return (error);
  708         scp = &sc;
  709         eflags = scp->sc_eflags;
  710         if (!EFL_SECURE(eflags, regs->tf_rflags)) {
  711                 return (EINVAL);
  712         }
  713         if (!CS_SECURE(scp->sc_cs)) {
  714                 ksiginfo_init_trap(&ksi);
  715                 ksi.ksi_signo = SIGBUS;
  716                 ksi.ksi_code = BUS_OBJERR;
  717                 ksi.ksi_trapno = T_PROTFLT;
  718                 ksi.ksi_addr = (void *)regs->tf_rip;
  719                 trapsignal(td, &ksi);
  720                 return (EINVAL);
  721         }
  722         regs->tf_ds = scp->sc_ds;
  723         regs->tf_es = scp->sc_es;
  724         regs->tf_fs = scp->sc_fs;
  725         regs->tf_gs = scp->sc_gs;
  726 
  727         regs->tf_rax = scp->sc_eax;
  728         regs->tf_rbx = scp->sc_ebx;
  729         regs->tf_rcx = scp->sc_ecx;
  730         regs->tf_rdx = scp->sc_edx;
  731         regs->tf_rsi = scp->sc_esi;
  732         regs->tf_rdi = scp->sc_edi;
  733         regs->tf_cs = scp->sc_cs;
  734         regs->tf_ss = scp->sc_ss;
  735         regs->tf_rbp = scp->sc_ebp;
  736         regs->tf_rsp = scp->sc_esp;
  737         regs->tf_rip = scp->sc_eip;
  738         regs->tf_rflags = eflags;
  739 
  740         if (scp->sc_onstack & 1)
  741                 td->td_sigstk.ss_flags |= SS_ONSTACK;
  742         else
  743                 td->td_sigstk.ss_flags &= ~SS_ONSTACK;
  744 
  745         kern_sigprocmask(td, SIG_SETMASK, (sigset_t *)&scp->sc_mask, NULL,
  746             SIGPROCMASK_OLD);
  747         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
  748         return (EJUSTRETURN);
  749 }
  750 #endif
  751 
  752 #ifdef COMPAT_FREEBSD4
  753 int
  754 freebsd4_freebsd32_sigreturn(struct thread *td,
  755     struct freebsd4_freebsd32_sigreturn_args *uap)
  756 {
  757         struct ia32_freebsd4_ucontext uc;
  758         struct trapframe *regs;
  759         struct ia32_freebsd4_ucontext *ucp;
  760         int cs, eflags, error;
  761         ksiginfo_t ksi;
  762 
  763         error = copyin(uap->sigcntxp, &uc, sizeof(uc));
  764         if (error != 0)
  765                 return (error);
  766         ucp = &uc;
  767         regs = td->td_frame;
  768         eflags = ucp->uc_mcontext.mc_eflags;
  769         /*
  770          * Don't allow users to change privileged or reserved flags.
  771          */
  772         if (!EFL_SECURE(eflags, regs->tf_rflags)) {
  773                 uprintf("pid %d (%s): freebsd4_freebsd32_sigreturn eflags = 0x%x\n",
  774                     td->td_proc->p_pid, td->td_name, eflags);
  775                 return (EINVAL);
  776         }
  777 
  778         /*
  779          * Don't allow users to load a valid privileged %cs.  Let the
  780          * hardware check for invalid selectors, excess privilege in
  781          * other selectors, invalid %eip's and invalid %esp's.
  782          */
  783         cs = ucp->uc_mcontext.mc_cs;
  784         if (!CS_SECURE(cs)) {
  785                 uprintf("pid %d (%s): freebsd4_sigreturn cs = 0x%x\n",
  786                     td->td_proc->p_pid, td->td_name, cs);
  787                 ksiginfo_init_trap(&ksi);
  788                 ksi.ksi_signo = SIGBUS;
  789                 ksi.ksi_code = BUS_OBJERR;
  790                 ksi.ksi_trapno = T_PROTFLT;
  791                 ksi.ksi_addr = (void *)regs->tf_rip;
  792                 trapsignal(td, &ksi);
  793                 return (EINVAL);
  794         }
  795 
  796         regs->tf_rdi = ucp->uc_mcontext.mc_edi;
  797         regs->tf_rsi = ucp->uc_mcontext.mc_esi;
  798         regs->tf_rbp = ucp->uc_mcontext.mc_ebp;
  799         regs->tf_rbx = ucp->uc_mcontext.mc_ebx;
  800         regs->tf_rdx = ucp->uc_mcontext.mc_edx;
  801         regs->tf_rcx = ucp->uc_mcontext.mc_ecx;
  802         regs->tf_rax = ucp->uc_mcontext.mc_eax;
  803         regs->tf_trapno = ucp->uc_mcontext.mc_trapno;
  804         regs->tf_err = ucp->uc_mcontext.mc_err;
  805         regs->tf_rip = ucp->uc_mcontext.mc_eip;
  806         regs->tf_cs = cs;
  807         regs->tf_rflags = ucp->uc_mcontext.mc_eflags;
  808         regs->tf_rsp = ucp->uc_mcontext.mc_esp;
  809         regs->tf_ss = ucp->uc_mcontext.mc_ss;
  810         regs->tf_ds = ucp->uc_mcontext.mc_ds;
  811         regs->tf_es = ucp->uc_mcontext.mc_es;
  812         regs->tf_fs = ucp->uc_mcontext.mc_fs;
  813         regs->tf_gs = ucp->uc_mcontext.mc_gs;
  814 
  815         kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0);
  816         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
  817         return (EJUSTRETURN);
  818 }
  819 #endif  /* COMPAT_FREEBSD4 */
  820 
  821 int
  822 freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap)
  823 {
  824         struct ia32_ucontext uc;
  825         struct trapframe *regs;
  826         struct ia32_ucontext *ucp;
  827         char *xfpustate;
  828         size_t xfpustate_len;
  829         int cs, eflags, error, ret;
  830         ksiginfo_t ksi;
  831 
  832         error = copyin(uap->sigcntxp, &uc, sizeof(uc));
  833         if (error != 0)
  834                 return (error);
  835         ucp = &uc;
  836         regs = td->td_frame;
  837         eflags = ucp->uc_mcontext.mc_eflags;
  838         /*
  839          * Don't allow users to change privileged or reserved flags.
  840          */
  841         if (!EFL_SECURE(eflags, regs->tf_rflags)) {
  842                 uprintf("pid %d (%s): freebsd32_sigreturn eflags = 0x%x\n",
  843                     td->td_proc->p_pid, td->td_name, eflags);
  844                 return (EINVAL);
  845         }
  846 
  847         /*
  848          * Don't allow users to load a valid privileged %cs.  Let the
  849          * hardware check for invalid selectors, excess privilege in
  850          * other selectors, invalid %eip's and invalid %esp's.
  851          */
  852         cs = ucp->uc_mcontext.mc_cs;
  853         if (!CS_SECURE(cs)) {
  854                 uprintf("pid %d (%s): sigreturn cs = 0x%x\n",
  855                     td->td_proc->p_pid, td->td_name, cs);
  856                 ksiginfo_init_trap(&ksi);
  857                 ksi.ksi_signo = SIGBUS;
  858                 ksi.ksi_code = BUS_OBJERR;
  859                 ksi.ksi_trapno = T_PROTFLT;
  860                 ksi.ksi_addr = (void *)regs->tf_rip;
  861                 trapsignal(td, &ksi);
  862                 return (EINVAL);
  863         }
  864 
  865         if ((ucp->uc_mcontext.mc_flags & _MC_HASFPXSTATE) != 0) {
  866                 xfpustate_len = uc.uc_mcontext.mc_xfpustate_len;
  867                 if (xfpustate_len > cpu_max_ext_state_size -
  868                     sizeof(struct savefpu)) {
  869                         uprintf("pid %d (%s): sigreturn xfpusave_len = 0x%zx\n",
  870                             td->td_proc->p_pid, td->td_name, xfpustate_len);
  871                         return (EINVAL);
  872                 }
  873                 xfpustate = (char *)fpu_save_area_alloc();
  874                 error = copyin(PTRIN(ucp->uc_mcontext.mc_xfpustate),
  875                     xfpustate, xfpustate_len);
  876                 if (error != 0) {
  877                         fpu_save_area_free((struct savefpu *)xfpustate);
  878                         uprintf(
  879         "pid %d (%s): sigreturn copying xfpustate failed\n",
  880                             td->td_proc->p_pid, td->td_name);
  881                         return (error);
  882                 }
  883         } else {
  884                 xfpustate = NULL;
  885                 xfpustate_len = 0;
  886         }
  887         ret = ia32_set_fpcontext(td, &ucp->uc_mcontext, xfpustate,
  888             xfpustate_len);
  889         fpu_save_area_free((struct savefpu *)xfpustate);
  890         if (ret != 0) {
  891                 uprintf("pid %d (%s): sigreturn set_fpcontext err %d\n",
  892                     td->td_proc->p_pid, td->td_name, ret);
  893                 return (ret);
  894         }
  895 
  896         regs->tf_rdi = ucp->uc_mcontext.mc_edi;
  897         regs->tf_rsi = ucp->uc_mcontext.mc_esi;
  898         regs->tf_rbp = ucp->uc_mcontext.mc_ebp;
  899         regs->tf_rbx = ucp->uc_mcontext.mc_ebx;
  900         regs->tf_rdx = ucp->uc_mcontext.mc_edx;
  901         regs->tf_rcx = ucp->uc_mcontext.mc_ecx;
  902         regs->tf_rax = ucp->uc_mcontext.mc_eax;
  903         regs->tf_trapno = ucp->uc_mcontext.mc_trapno;
  904         regs->tf_err = ucp->uc_mcontext.mc_err;
  905         regs->tf_rip = ucp->uc_mcontext.mc_eip;
  906         regs->tf_cs = cs;
  907         regs->tf_rflags = ucp->uc_mcontext.mc_eflags;
  908         regs->tf_rsp = ucp->uc_mcontext.mc_esp;
  909         regs->tf_ss = ucp->uc_mcontext.mc_ss;
  910         regs->tf_ds = ucp->uc_mcontext.mc_ds;
  911         regs->tf_es = ucp->uc_mcontext.mc_es;
  912         regs->tf_fs = ucp->uc_mcontext.mc_fs;
  913         regs->tf_gs = ucp->uc_mcontext.mc_gs;
  914         regs->tf_flags = TF_HASSEGS;
  915 
  916         kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0);
  917         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
  918         return (EJUSTRETURN);
  919 }
  920 
  921 /*
  922  * Clear registers on exec
  923  */
  924 void
  925 ia32_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack)
  926 {
  927         struct trapframe *regs;
  928         struct pcb *pcb;
  929         register_t saved_rflags;
  930 
  931         regs = td->td_frame;
  932         pcb = td->td_pcb;
  933 
  934         if (td->td_proc->p_md.md_ldt != NULL)
  935                 user_ldt_free(td);
  936 #ifdef COMPAT_43
  937         setup_lcall_gate();
  938 #endif
  939 
  940         pcb->pcb_fsbase = 0;
  941         pcb->pcb_gsbase = 0;
  942         pcb->pcb_initial_fpucw = __INITIAL_FPUCW_I386__;
  943 
  944         saved_rflags = regs->tf_rflags & PSL_T;
  945         bzero((char *)regs, sizeof(struct trapframe));
  946         regs->tf_rip = imgp->entry_addr;
  947         regs->tf_rsp = stack;
  948         regs->tf_rflags = PSL_USER | saved_rflags;
  949         regs->tf_ss = _udatasel;
  950         regs->tf_cs = _ucode32sel;
  951         regs->tf_rbx = (register_t)imgp->ps_strings;
  952         regs->tf_ds = _udatasel;
  953         regs->tf_es = _udatasel;
  954         regs->tf_fs = _ufssel;
  955         regs->tf_gs = _ugssel;
  956         regs->tf_flags = TF_HASSEGS;
  957 
  958         x86_clear_dbregs(pcb);
  959 
  960         fpstate_drop(td);
  961 
  962         /* Return via doreti so that we can change to a different %cs */
  963         set_pcb_flags(pcb, PCB_32BIT | PCB_FULL_IRET);
  964 }

Cache object: c623e5a843362a197b4963a2f3dc8ff3


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