root/arch/i386/i386/freebsd_machdep.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. freebsd_sendsig
  2. freebsd_sys_sigreturn
  3. netbsd_to_freebsd_ptrace_regs
  4. freebsd_to_netbsd_ptrace_regs
  5. freebsd_ptrace_getregs
  6. freebsd_ptrace_setregs

    1 /*      $OpenBSD: freebsd_machdep.c,v 1.21 2006/12/29 13:04:36 pedro Exp $      */
    2 /*      $NetBSD: freebsd_machdep.c,v 1.10 1996/05/03 19:42:05 christos Exp $    */
    3 
    4 /*-
    5  * Copyright (c) 1993, 1994, 1995, 1996 Charles M. Hannum.  All rights reserved.
    6  * Copyright (c) 1992 Terrence R. Lambert.
    7  * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
    8  * All rights reserved.
    9  *
   10  * This code is derived from software contributed to Berkeley by
   11  * William Jolitz.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 3. Neither the name of the University nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  *
   37  *      @(#)machdep.c   7.4 (Berkeley) 6/3/91
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/signalvar.h>
   43 #include <sys/proc.h>
   44 #include <sys/user.h>
   45 #include <sys/exec.h>
   46 #include <sys/mount.h>
   47 
   48 #include <uvm/uvm_extern.h>
   49 
   50 #include <machine/cpufunc.h>
   51 #include <machine/npx.h>
   52 #include <machine/reg.h>
   53 #include <machine/vm86.h>
   54 #include <machine/freebsd_machdep.h>
   55 
   56 #include <compat/freebsd/freebsd_signal.h>
   57 #include <compat/freebsd/freebsd_syscallargs.h>
   58 #include <compat/freebsd/freebsd_exec.h>
   59 #include <compat/freebsd/freebsd_ptrace.h>
   60 
   61 /*
   62  * signal support
   63  */
   64 
   65 /*
   66  * Send an interrupt to process.
   67  *
   68  * Stack is set up to allow sigcode stored
   69  * in u. to call routine, followed by kcall
   70  * to sigreturn routine below.  After sigreturn
   71  * resets the signal mask, the stack, and the
   72  * frame pointer, it returns to the user
   73  * specified pc, psl.
   74  */
   75 void
   76 freebsd_sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
   77     union sigval val)
   78 {
   79         struct proc *p = curproc;
   80         struct trapframe *tf;
   81         struct freebsd_sigframe *fp, frame;
   82         struct sigacts *psp = p->p_sigacts;
   83         int oonstack;
   84 
   85         /*
   86          * Build the argument list for the signal handler.
   87          */
   88         frame.sf_signum = sig;
   89 
   90         tf = p->p_md.md_regs;
   91         oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
   92 
   93         /*
   94          * Allocate space for the signal handler context.
   95          */
   96         if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
   97             (psp->ps_sigonstack & sigmask(sig))) {
   98                 fp = (struct freebsd_sigframe *)((char *)psp->ps_sigstk.ss_sp +
   99                     psp->ps_sigstk.ss_size - sizeof(struct freebsd_sigframe));
  100                 psp->ps_sigstk.ss_flags |= SS_ONSTACK;
  101         } else {
  102                 fp = (struct freebsd_sigframe *)tf->tf_esp - 1;
  103         }
  104 
  105         frame.sf_code = code;
  106         frame.sf_scp = &fp->sf_sc;
  107         frame.sf_addr = (char *)rcr2();
  108         frame.sf_handler = catcher;
  109 
  110         /*
  111          * Build the signal context to be used by sigreturn.
  112          */
  113         frame.sf_sc.sc_onstack = oonstack;
  114         frame.sf_sc.sc_mask = mask;
  115 #ifdef VM86
  116         if (tf->tf_eflags & PSL_VM) {
  117                 frame.sf_sc.sc_es = tf->tf_vm86_es;
  118                 frame.sf_sc.sc_ds = tf->tf_vm86_ds;
  119                 frame.sf_sc.sc_eflags = get_vflags(p);
  120         } else
  121 #endif
  122         {
  123                 frame.sf_sc.sc_es = tf->tf_es;
  124                 frame.sf_sc.sc_ds = tf->tf_ds;
  125                 frame.sf_sc.sc_eflags = tf->tf_eflags;
  126         }
  127         frame.sf_sc.sc_edi = tf->tf_edi;
  128         frame.sf_sc.sc_esi = tf->tf_esi;
  129         frame.sf_sc.sc_ebp = tf->tf_ebp;
  130         frame.sf_sc.sc_isp = 0; /* don't have to pass kernel sp to user. */
  131         frame.sf_sc.sc_ebx = tf->tf_ebx;
  132         frame.sf_sc.sc_edx = tf->tf_edx;
  133         frame.sf_sc.sc_ecx = tf->tf_ecx;
  134         frame.sf_sc.sc_eax = tf->tf_eax;
  135         frame.sf_sc.sc_eip = tf->tf_eip;
  136         frame.sf_sc.sc_cs = tf->tf_cs;
  137         frame.sf_sc.sc_esp = tf->tf_esp;
  138         frame.sf_sc.sc_ss = tf->tf_ss;
  139 
  140         if (copyout(&frame, fp, sizeof(frame)) != 0) {
  141                 /*
  142                  * Process has trashed its stack; give it an illegal
  143                  * instruction to halt it in its tracks.
  144                  */
  145                 sigexit(p, SIGILL);
  146                 /* NOTREACHED */
  147         }
  148 
  149         /*
  150          * Build context to run handler in.
  151          */
  152         tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
  153         tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
  154         tf->tf_eip = p->p_sigcode;
  155         tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
  156         tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
  157         tf->tf_esp = (int)fp;
  158         tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
  159 }
  160 
  161 /*
  162  * System call to cleanup state after a signal
  163  * has been taken.  Reset signal mask and
  164  * stack state from context left by sendsig (above).
  165  * Return to previous pc and psl as specified by
  166  * context left by sendsig. Check carefully to
  167  * make sure that the user has not modified the
  168  * psl to gain improper privileges or to cause
  169  * a machine fault.
  170  */
  171 int
  172 freebsd_sys_sigreturn(struct proc *p, void *v, register_t *retval)
  173 {
  174         struct freebsd_sys_sigreturn_args /* {
  175                 syscallarg(struct freebsd_sigcontext *) scp;
  176         } */ *uap = v;
  177         struct freebsd_sigcontext *scp, context;
  178         struct trapframe *tf;
  179 
  180         tf = p->p_md.md_regs;
  181 
  182         /*
  183          * The trampoline code hands us the context.
  184          * It is unsafe to keep track of it ourselves, in the event that a
  185          * program jumps out of a signal handler.
  186          */
  187         scp = SCARG(uap, scp);
  188         if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0)
  189                 return (EFAULT);
  190 
  191         /*
  192          * Restore signal context.
  193          */
  194 #ifdef VM86
  195         if (context.sc_eflags & PSL_VM) {
  196                 tf->tf_vm86_es = context.sc_es;
  197                 tf->tf_vm86_ds = context.sc_ds;
  198                 set_vflags(p, context.sc_eflags);
  199         } else
  200 #endif
  201         {
  202                 /*
  203                  * Check for security violations.  If we're returning to
  204                  * protected mode, the CPU will validate the segment registers
  205                  * automatically and generate a trap on violations.  We handle
  206                  * the trap, rather than doing all of the checking here.
  207                  */
  208                 if (((context.sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 ||
  209                     !USERMODE(context.sc_cs, context.sc_eflags))
  210                         return (EINVAL);
  211 
  212                 tf->tf_es = context.sc_es;
  213                 tf->tf_ds = context.sc_ds;
  214                 tf->tf_eflags = context.sc_eflags;
  215         }
  216         tf->tf_edi = context.sc_edi;
  217         tf->tf_esi = context.sc_esi;
  218         tf->tf_ebp = context.sc_ebp;
  219         /* FreeBSD's context.sc_isp is useless. (`popal' ignores it.) */
  220         tf->tf_ebx = context.sc_ebx;
  221         tf->tf_edx = context.sc_edx;
  222         tf->tf_ecx = context.sc_ecx;
  223         tf->tf_eax = context.sc_eax;
  224         tf->tf_eip = context.sc_eip;
  225         tf->tf_cs = context.sc_cs;
  226         tf->tf_esp = context.sc_esp;
  227         tf->tf_ss = context.sc_ss;
  228 
  229         if (context.sc_onstack & 01)
  230                 p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
  231         else
  232                 p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
  233         p->p_sigmask = context.sc_mask & ~sigcantmask;
  234 
  235         return (EJUSTRETURN);
  236 }
  237 
  238 
  239 /*
  240  * freebsd_ptrace(2) support
  241  */
  242 
  243 void
  244 netbsd_to_freebsd_ptrace_regs(struct reg *nregs, struct fpreg *nfpregs,
  245     struct freebsd_ptrace_reg *fregs)
  246 {
  247         struct save87 *nframe = (struct save87 *)nfpregs;
  248 
  249         fregs->freebsd_ptrace_regs.tf_es = nregs->r_es;
  250         fregs->freebsd_ptrace_regs.tf_ds = nregs->r_ds;
  251         fregs->freebsd_ptrace_regs.tf_edi = nregs->r_edi;
  252         fregs->freebsd_ptrace_regs.tf_esi = nregs->r_esi;
  253         fregs->freebsd_ptrace_regs.tf_ebp = nregs->r_ebp;
  254         fregs->freebsd_ptrace_regs.tf_isp = 0;
  255         fregs->freebsd_ptrace_regs.tf_ebx = nregs->r_ebx;
  256         fregs->freebsd_ptrace_regs.tf_edx = nregs->r_edx;
  257         fregs->freebsd_ptrace_regs.tf_ecx = nregs->r_ecx;
  258         fregs->freebsd_ptrace_regs.tf_eax = nregs->r_eax;
  259         fregs->freebsd_ptrace_regs.tf_trapno = 0;
  260 
  261         fregs->freebsd_ptrace_regs.tf_err = 0;
  262         fregs->freebsd_ptrace_regs.tf_eip = nregs->r_eip;
  263         fregs->freebsd_ptrace_regs.tf_cs = nregs->r_cs;
  264         fregs->freebsd_ptrace_regs.tf_eflags = nregs->r_eflags;
  265 
  266         fregs->freebsd_ptrace_regs.tf_esp = nregs->r_esp;
  267         fregs->freebsd_ptrace_regs.tf_ss = nregs->r_ss;
  268 
  269         fregs->freebsd_ptrace_fpregs.sv_env =
  270                 *(struct freebsd_env87 *)&nframe->sv_env;
  271         bcopy(nframe->sv_ac, fregs->freebsd_ptrace_fpregs.sv_ac,
  272               sizeof(fregs->freebsd_ptrace_fpregs.sv_ac));
  273         fregs->freebsd_ptrace_fpregs.sv_ex_sw =
  274                 nframe->sv_ex_sw;
  275 #if 0
  276         /*
  277          * fortunately, sizeof(freebsd_save87) >= sizeof(save87)
  278          */
  279 #ifdef DIAGNOSTIC
  280         if (sizeof(fregs->freebsd_ptrace_fpregs.sv_pad) <
  281             sizeof(nframe->sv_ex_tw) + sizeof(nframe->sv_pad)) {
  282                 panic("netbsd_to_freebsd_ptrace_regs: %s",
  283                       "sizeof(freebsd_save87) >= sizeof(save87)");
  284         }
  285 #endif
  286 #endif
  287         bcopy(&nframe->sv_ex_tw, fregs->freebsd_ptrace_fpregs.sv_pad,
  288               sizeof(nframe->sv_ex_tw));
  289 #if 0
  290         bcopy(nframe->sv_pad,
  291               (caddr_t)fregs->freebsd_ptrace_fpregs.sv_pad +
  292               sizeof(nframe->sv_ex_tw),
  293               sizeof(nframe->sv_pad));
  294         bzero((caddr_t)fregs->freebsd_ptrace_fpregs.sv_pad +
  295               sizeof(nframe->sv_ex_tw) + sizeof(nframe->sv_pad),
  296               sizeof(fregs->freebsd_ptrace_fpregs.sv_pad) -
  297               sizeof(nframe->sv_ex_tw) - sizeof(nframe->sv_pad));
  298 #endif
  299 }
  300 
  301 void
  302 freebsd_to_netbsd_ptrace_regs(struct freebsd_ptrace_reg *fregs,
  303     struct reg *nregs, struct fpreg *nfpregs)
  304 {
  305         struct save87 *nframe = (struct save87 *)nfpregs;
  306 
  307         nregs->r_es = fregs->freebsd_ptrace_regs.tf_es;
  308         nregs->r_ds = fregs->freebsd_ptrace_regs.tf_ds;
  309         nregs->r_edi = fregs->freebsd_ptrace_regs.tf_edi;
  310         nregs->r_esi = fregs->freebsd_ptrace_regs.tf_esi;
  311         nregs->r_ebp = fregs->freebsd_ptrace_regs.tf_ebp;
  312         nregs->r_ebx = fregs->freebsd_ptrace_regs.tf_ebx;
  313         nregs->r_edx = fregs->freebsd_ptrace_regs.tf_edx;
  314         nregs->r_ecx = fregs->freebsd_ptrace_regs.tf_ecx;
  315         nregs->r_eax = fregs->freebsd_ptrace_regs.tf_eax;
  316 
  317         nregs->r_eip = fregs->freebsd_ptrace_regs.tf_eip;
  318         nregs->r_cs = fregs->freebsd_ptrace_regs.tf_cs;
  319         nregs->r_eflags = fregs->freebsd_ptrace_regs.tf_eflags;
  320 
  321         nregs->r_esp = fregs->freebsd_ptrace_regs.tf_esp;
  322         nregs->r_ss = fregs->freebsd_ptrace_regs.tf_ss;
  323 
  324         nframe->sv_env =
  325                 *(struct env87 *)&fregs->freebsd_ptrace_fpregs.sv_env;
  326         bcopy(fregs->freebsd_ptrace_fpregs.sv_ac, nframe->sv_ac,
  327               sizeof(nframe->sv_ac));
  328         nframe->sv_ex_sw =
  329                 fregs->freebsd_ptrace_fpregs.sv_ex_sw;
  330         /*
  331          * fortunately, sizeof(freebsd_save87) >= sizeof(save87)
  332          */
  333         bcopy(fregs->freebsd_ptrace_fpregs.sv_pad, &nframe->sv_ex_tw,
  334               sizeof(nframe->sv_ex_tw));
  335 #if 0
  336         bcopy((caddr_t)fregs->freebsd_ptrace_fpregs.sv_pad +
  337               sizeof(nframe->sv_ex_tw),
  338               nframe->sv_pad, sizeof(nframe->sv_pad));
  339 #endif
  340 }
  341 
  342 /* random value, except FREEBSD_U_AR0_OFFSET..., FREEBSD_U_SAVEFP_OFFSET... */
  343 #define FREEBSD_REGS_OFFSET 0x2000
  344 
  345 int
  346 freebsd_ptrace_getregs(struct freebsd_ptrace_reg *fregs, caddr_t addr,
  347     register_t *datap)
  348 {
  349         vaddr_t offset = (vaddr_t)addr;
  350 
  351         if (offset == FREEBSD_U_AR0_OFFSET) {
  352                 *datap = FREEBSD_REGS_OFFSET + FREEBSD_USRSTACK;
  353                 return 0;
  354         } else if (offset >= FREEBSD_REGS_OFFSET &&
  355                    offset <= FREEBSD_REGS_OFFSET +
  356                       sizeof(fregs->freebsd_ptrace_regs)-sizeof(register_t)) {
  357                 *datap = *(register_t *)&((caddr_t)&fregs->freebsd_ptrace_regs)
  358                         [(vaddr_t) addr - FREEBSD_REGS_OFFSET];
  359                 return 0;
  360         } else if (offset >= FREEBSD_U_SAVEFP_OFFSET &&
  361                    offset <= FREEBSD_U_SAVEFP_OFFSET +
  362                       sizeof(fregs->freebsd_ptrace_fpregs)-sizeof(register_t)){
  363                 *datap= *(register_t *)&((caddr_t)&fregs->freebsd_ptrace_fpregs)
  364                         [offset - FREEBSD_U_SAVEFP_OFFSET];
  365                 return 0;
  366         }
  367 #ifdef DIAGNOSTIC
  368         printf("freebsd_ptrace_getregs: *(0x%08lx)\n", offset);
  369 #endif
  370         return EFAULT;
  371 }
  372 
  373 int
  374 freebsd_ptrace_setregs(struct freebsd_ptrace_reg *fregs, caddr_t addr, int data)
  375 {
  376         vaddr_t offset = (vaddr_t)addr;
  377 
  378         if (offset >= FREEBSD_REGS_OFFSET &&
  379             offset <= FREEBSD_REGS_OFFSET +
  380                         sizeof(fregs->freebsd_ptrace_regs) - sizeof(int)) {
  381                 *(int *)&((caddr_t)&fregs->freebsd_ptrace_regs)
  382                         [offset - FREEBSD_REGS_OFFSET] = data;
  383                 return 0;
  384         } else if (offset >= FREEBSD_U_SAVEFP_OFFSET &&
  385                    offset <= FREEBSD_U_SAVEFP_OFFSET +
  386                         sizeof(fregs->freebsd_ptrace_fpregs) - sizeof(int)) {
  387                 *(int *)&((caddr_t)&fregs->freebsd_ptrace_fpregs)
  388                         [offset - FREEBSD_U_SAVEFP_OFFSET] = data;
  389                 return 0;
  390         }
  391 #ifdef DIAGNOSTIC
  392         printf("freebsd_ptrace_setregs: *(0x%08lx) = 0x%08x\n", offset, data);
  393 #endif
  394         return EFAULT;
  395 }

/* [<][>][^][v][top][bottom][index][help] */