root/arch/i386/i386/process_machdep.c

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

DEFINITIONS

This source file includes following definitions.
  1. process_frame
  2. process_fpframe
  3. process_xmm_to_s87
  4. process_fninit_xmm
  5. process_read_regs
  6. process_read_fpregs
  7. process_s87_to_xmm
  8. process_write_regs
  9. process_write_fpregs
  10. process_read_xmmregs
  11. process_write_xmmregs
  12. process_sstep
  13. process_set_pc

    1 /*      $OpenBSD: process_machdep.c,v 1.22 2007/05/08 20:26:54 deraadt Exp $    */
    2 /*      $NetBSD: process_machdep.c,v 1.22 1996/05/03 19:42:25 christos Exp $    */
    3 
    4 /*
    5  * Copyright (c) 1995, 1996 Charles M. Hannum.  All rights reserved.
    6  * Copyright (c) 1993 The Regents of the University of California.
    7  * Copyright (c) 1993 Jan-Simon Pendry
    8  * All rights reserved.
    9  *
   10  * This code is derived from software contributed to Berkeley by
   11  * Jan-Simon Pendry.
   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  * From:
   38  *      Id: procfs_i386.c,v 4.1 1993/12/17 10:47:45 jsp Rel
   39  */
   40 
   41 /*
   42  * This file may seem a bit stylized, but that so that it's easier to port.
   43  * Functions to be implemented here are:
   44  *
   45  * process_read_regs(proc, regs)
   46  *      Get the current user-visible register set from the process
   47  *      and copy it into the regs structure (<machine/reg.h>).
   48  *      The process is stopped at the time read_regs is called.
   49  *
   50  * process_write_regs(proc, regs)
   51  *      Update the current register set from the passed in regs
   52  *      structure.  Take care to avoid clobbering special CPU
   53  *      registers or privileged bits in the PSL.
   54  *      The process is stopped at the time write_regs is called.
   55  *
   56  * process_sstep(proc)
   57  *      Arrange for the process to trap after executing a single instruction.
   58  *
   59  * process_set_pc(proc)
   60  *      Set the process's program counter.
   61  */
   62 
   63 #include <sys/param.h>
   64 #include <sys/systm.h>
   65 #include <sys/time.h>
   66 #include <sys/kernel.h>
   67 #include <sys/proc.h>
   68 #include <sys/user.h>
   69 #include <sys/vnode.h>
   70 #include <sys/ptrace.h>
   71 
   72 #include <machine/psl.h>
   73 #include <machine/reg.h>
   74 #include <machine/segments.h>
   75 
   76 #ifdef VM86
   77 #include <machine/vm86.h>
   78 #endif
   79 
   80 #include "npx.h"
   81 
   82 static __inline struct trapframe *process_frame(struct proc *);
   83 static __inline union savefpu *process_fpframe(struct proc *);
   84 void process_fninit_xmm(struct savexmm *);
   85 
   86 static __inline struct trapframe *
   87 process_frame(struct proc *p)
   88 {
   89 
   90         return (p->p_md.md_regs);
   91 }
   92 
   93 static __inline union savefpu *
   94 process_fpframe(struct proc *p)
   95 {
   96 
   97         return (&p->p_addr->u_pcb.pcb_savefpu);
   98 }
   99 
  100 void
  101 process_xmm_to_s87(const struct savexmm *sxmm, struct save87 *s87)
  102 {
  103         int i;
  104 
  105         /* FPU control/status */
  106         s87->sv_env.en_cw = sxmm->sv_env.en_cw;
  107         s87->sv_env.en_sw = sxmm->sv_env.en_sw;
  108         /* tag word handled below */
  109         s87->sv_env.en_fip = sxmm->sv_env.en_fip;
  110         s87->sv_env.en_fcs = sxmm->sv_env.en_fcs;
  111         s87->sv_env.en_opcode = sxmm->sv_env.en_opcode;
  112         s87->sv_env.en_foo = sxmm->sv_env.en_foo;
  113         s87->sv_env.en_fos = sxmm->sv_env.en_fos;
  114 
  115         /* Tag word and registers. */
  116         for (i = 0; i < 8; i++) {
  117                 if (sxmm->sv_env.en_tw & (1U << i))
  118                         s87->sv_env.en_tw &= ~(3U << (i * 2));
  119                 else
  120                         s87->sv_env.en_tw |= (3U << (i * 2));
  121 
  122                 if (sxmm->sv_ex_tw & (1U << i))
  123                         s87->sv_ex_tw &= ~(3U << (i * 2));
  124                 else
  125                         s87->sv_ex_tw |= (3U << (i * 2));
  126 
  127                 memcpy(&s87->sv_ac[i].fp_bytes, &sxmm->sv_ac[i].fp_bytes,
  128                     sizeof(s87->sv_ac[i].fp_bytes));
  129         }
  130 
  131         s87->sv_ex_sw = sxmm->sv_ex_sw;
  132 }
  133 
  134 void
  135 process_fninit_xmm(struct savexmm *sxmm)
  136 {
  137         /*
  138          * The initial control word was already set by setregs(), so
  139          * save it temporarily.
  140          */
  141         uint32_t mxcsr = sxmm->sv_env.en_mxcsr;
  142         uint16_t cw = sxmm->sv_env.en_cw;
  143 
  144         /* XXX Don't zero XMM regs? */
  145         memset(sxmm, 0, sizeof(*sxmm));
  146         sxmm->sv_env.en_cw = cw;
  147         sxmm->sv_env.en_mxcsr = mxcsr;
  148         sxmm->sv_env.en_sw = 0x0000;
  149         sxmm->sv_env.en_tw = 0x00;
  150 }
  151 
  152 int
  153 process_read_regs(struct proc *p, struct reg *regs)
  154 {
  155         struct trapframe *tf = process_frame(p);
  156 
  157 #ifdef VM86
  158         if (tf->tf_eflags & PSL_VM) {
  159                 regs->r_gs = tf->tf_vm86_gs & 0xffff;
  160                 regs->r_fs = tf->tf_vm86_fs & 0xffff;
  161                 regs->r_es = tf->tf_vm86_es & 0xffff;
  162                 regs->r_ds = tf->tf_vm86_ds & 0xffff;
  163                 regs->r_eflags = get_vflags(p);
  164         } else
  165 #endif
  166         {
  167                 regs->r_gs = tf->tf_gs & 0xffff;
  168                 regs->r_fs = tf->tf_fs & 0xffff;
  169                 regs->r_es = tf->tf_es & 0xffff;
  170                 regs->r_ds = tf->tf_ds & 0xffff;
  171                 regs->r_eflags = tf->tf_eflags;
  172         }
  173         regs->r_edi = tf->tf_edi;
  174         regs->r_esi = tf->tf_esi;
  175         regs->r_ebp = tf->tf_ebp;
  176         regs->r_ebx = tf->tf_ebx;
  177         regs->r_edx = tf->tf_edx;
  178         regs->r_ecx = tf->tf_ecx;
  179         regs->r_eax = tf->tf_eax;
  180         regs->r_eip = tf->tf_eip;
  181         regs->r_cs = tf->tf_cs & 0xffff;
  182         regs->r_esp = tf->tf_esp;
  183         regs->r_ss = tf->tf_ss & 0xffff;
  184 
  185         return (0);
  186 }
  187 
  188 int
  189 process_read_fpregs(struct proc *p, struct fpreg *regs)
  190 {
  191         union savefpu *frame = process_fpframe(p);
  192 
  193         if (p->p_md.md_flags & MDP_USEDFPU) {
  194 #if NNPX > 0
  195                 npxsave_proc(p, 1);
  196 #endif
  197         } else {
  198                 /* Fake a FNINIT. */
  199                 if (i386_use_fxsave) {
  200                         process_fninit_xmm(&frame->sv_xmm);
  201                 } else {
  202                         /*
  203                          * The initial control word was already set by
  204                          * setregs(), so save it temporarily.
  205                          */
  206                         uint16_t cw = frame->sv_87.sv_env.en_cw;
  207 
  208                         memset(&frame->sv_87, 0, sizeof(frame->sv_87));
  209                         frame->sv_87.sv_env.en_cw = cw;
  210                         frame->sv_87.sv_env.en_sw = 0x0000;
  211                         frame->sv_87.sv_env.en_tw = 0xffff;
  212                 }
  213                 p->p_md.md_flags |= MDP_USEDFPU;
  214         }
  215 
  216         if (i386_use_fxsave) {
  217                 struct save87 s87;
  218 
  219                 /* XXX Yuck */
  220                 process_xmm_to_s87(&frame->sv_xmm, &s87);
  221                 memcpy(regs, &s87, sizeof(*regs));
  222         } else
  223                 memcpy(regs, &frame->sv_87, sizeof(*regs));
  224 
  225         return (0);
  226 }
  227 
  228 #ifdef PTRACE
  229 
  230 void
  231 process_s87_to_xmm(const struct save87 *s87, struct savexmm *sxmm)
  232 {
  233         int i;
  234 
  235         /* FPU control/status */
  236         sxmm->sv_env.en_cw = s87->sv_env.en_cw;
  237         sxmm->sv_env.en_sw = s87->sv_env.en_sw;
  238         /* tag word handled below */
  239         sxmm->sv_env.en_fip = s87->sv_env.en_fip;
  240         sxmm->sv_env.en_fcs = s87->sv_env.en_fcs;
  241         sxmm->sv_env.en_opcode = s87->sv_env.en_opcode;
  242         sxmm->sv_env.en_foo = s87->sv_env.en_foo;
  243         sxmm->sv_env.en_fos = s87->sv_env.en_fos;
  244 
  245         /* Tag word and registers. */
  246         for (i = 0; i < 8; i++) {
  247                 if (((s87->sv_env.en_tw >> (i * 2)) & 3) == 3)
  248                         sxmm->sv_env.en_tw &= ~(1U << i);
  249                 else
  250                         sxmm->sv_env.en_tw |= (1U << i);
  251 
  252                 if (((s87->sv_ex_tw >> (i * 2)) & 3) == 3)
  253                         sxmm->sv_ex_tw &= ~(1U << i);
  254                 else
  255                         sxmm->sv_ex_tw |= (1U << i);
  256 
  257                 memcpy(&sxmm->sv_ac[i].fp_bytes, &s87->sv_ac[i].fp_bytes,
  258                     sizeof(sxmm->sv_ac[i].fp_bytes));
  259         }
  260 
  261         sxmm->sv_ex_sw = s87->sv_ex_sw;
  262 }
  263 
  264 int
  265 process_write_regs(struct proc *p, struct reg *regs)
  266 {
  267         struct trapframe *tf = process_frame(p);
  268 
  269 #ifdef VM86
  270         if (tf->tf_eflags & PSL_VM) {
  271                 tf->tf_vm86_gs = regs->r_gs & 0xffff;
  272                 tf->tf_vm86_fs = regs->r_fs & 0xffff;
  273                 tf->tf_vm86_es = regs->r_es & 0xffff;
  274                 tf->tf_vm86_ds = regs->r_ds & 0xffff;
  275                 set_vflags(p, regs->r_eflags);
  276         } else
  277 #endif
  278         {
  279                 /*
  280                  * Check for security violations.
  281                  */
  282                 if (((regs->r_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 ||
  283                     !USERMODE(regs->r_cs, regs->r_eflags))
  284                         return (EINVAL);
  285 
  286                 tf->tf_gs = regs->r_gs & 0xffff;
  287                 tf->tf_fs = regs->r_fs & 0xffff;
  288                 tf->tf_es = regs->r_es & 0xffff;
  289                 tf->tf_ds = regs->r_ds & 0xffff;
  290                 tf->tf_eflags = regs->r_eflags;
  291         }
  292         tf->tf_edi = regs->r_edi;
  293         tf->tf_esi = regs->r_esi;
  294         tf->tf_ebp = regs->r_ebp;
  295         tf->tf_ebx = regs->r_ebx;
  296         tf->tf_edx = regs->r_edx;
  297         tf->tf_ecx = regs->r_ecx;
  298         tf->tf_eax = regs->r_eax;
  299         tf->tf_eip = regs->r_eip;
  300         tf->tf_cs = regs->r_cs & 0xffff;
  301         tf->tf_esp = regs->r_esp;
  302         tf->tf_ss = regs->r_ss & 0xffff;
  303 
  304         return (0);
  305 }
  306 
  307 int
  308 process_write_fpregs(struct proc *p, struct fpreg *regs)
  309 {
  310         union savefpu *frame = process_fpframe(p);
  311 
  312         if (p->p_md.md_flags & MDP_USEDFPU) {
  313 #if NNPX > 0
  314                 npxsave_proc(p, 0);
  315 #endif
  316         } else
  317                 p->p_md.md_flags |= MDP_USEDFPU;
  318 
  319         if (i386_use_fxsave) {
  320                 struct save87 s87;
  321 
  322                 /* XXX Yuck. */
  323                 memcpy(&s87, regs, sizeof(*regs));
  324                 process_s87_to_xmm(&s87, &frame->sv_xmm);
  325         } else
  326                 memcpy(&frame->sv_87, regs, sizeof(*regs));
  327 
  328         return (0);
  329 }
  330 
  331 int
  332 process_read_xmmregs(struct proc *p, struct xmmregs *regs)
  333 {
  334         union savefpu *frame = process_fpframe(p);
  335 
  336         if (!i386_use_fxsave)
  337                 return (EINVAL);
  338 
  339         if (p->p_md.md_flags & MDP_USEDFPU) {
  340 #if NNPX > 0
  341                 npxsave_proc(p, 1);
  342 #endif
  343         } else {
  344                 /* Fake a FNINIT. */
  345                 process_fninit_xmm(&frame->sv_xmm);
  346                 p->p_md.md_flags |= MDP_USEDFPU;
  347         }
  348 
  349         memcpy(regs, &frame->sv_xmm, sizeof(*regs));
  350         return (0);
  351 }
  352 
  353 int
  354 process_write_xmmregs(struct proc *p, const struct xmmregs *regs)
  355 {
  356         union savefpu *frame = process_fpframe(p);
  357 
  358         if (!i386_use_fxsave)
  359                 return (EINVAL);
  360 
  361         if (p->p_md.md_flags & MDP_USEDFPU) {
  362 #if NNPX > 0
  363                 npxsave_proc(p, 0);
  364 #endif
  365         } else
  366                 p->p_md.md_flags |= MDP_USEDFPU;
  367 
  368         memcpy(&frame->sv_xmm, regs, sizeof(*regs));
  369         return (0);
  370 }
  371 
  372 int
  373 process_sstep(struct proc *p, int sstep)
  374 {
  375         struct trapframe *tf = process_frame(p);
  376 
  377         if (sstep)
  378                 tf->tf_eflags |= PSL_T;
  379         else
  380                 tf->tf_eflags &= ~PSL_T;
  381         
  382         return (0);
  383 }
  384 
  385 int
  386 process_set_pc(struct proc *p, caddr_t addr)
  387 {
  388         struct trapframe *tf = process_frame(p);
  389 
  390         tf->tf_eip = (int)addr;
  391 
  392         return (0);
  393 }
  394 
  395 #endif  /* PTRACE */

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