notify clock routines when a process requests profiling
[unix-history] / usr / src / sys / kern / sys_process.c
index ff849cf..ab623e6 100644 (file)
@@ -1,19 +1,25 @@
-/*     sys_process.c   5.6     82/10/31        */
-
-#include "../h/param.h"
-#include "../h/systm.h"
-#include "../h/dir.h"
-#include "../h/user.h"
-#include "../h/proc.h"
-#include "../h/inode.h"
-#include "../h/reg.h"
-#include "../h/text.h"
-#include "../h/seg.h"
-#include "../h/pte.h"
-#include "../h/psl.h"
-#include "../h/vm.h"
-#include "../h/buf.h"
-#include "../h/acct.h"
+/*-
+ * Copyright (c) 1982, 1986, 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.proprietary.c%
+ *
+ *     @(#)sys_process.c       7.26 (Berkeley) %G%
+ */
+
+#define IPCREG
+#include "param.h"
+#include "proc.h"
+#include "vnode.h"
+#include "buf.h"
+#include "ptrace.h"
+
+#include "machine/reg.h"
+#include "machine/psl.h"
+#include "vm/vm.h"
+#include "vm/vm_page.h"
+
+#include "user.h"
 
 /*
  * Priority for tracing
 
 /*
  * Priority for tracing
@@ -36,28 +42,28 @@ struct {
 } ipc;
 
 /*
 } ipc;
 
 /*
- * sys-trace system call.
+ * Process debugging system call.
  */
  */
-ptrace()
-{
-       register struct proc *p;
-       register struct a {
+ptrace(curp, uap, retval)
+       struct proc *curp;
+       register struct args {
                int     req;
                int     pid;
                int     *addr;
                int     data;
        } *uap;
                int     req;
                int     pid;
                int     *addr;
                int     data;
        } *uap;
+       int *retval;
+{
+       register struct proc *p;
 
 
-       uap = (struct a *)u.u_ap;
        if (uap->req <= 0) {
        if (uap->req <= 0) {
-               u.u_procp->p_flag |= STRC;
-               return;
+               curp->p_flag |= STRC;
+               return (0);
        }
        p = pfind(uap->pid);
        }
        p = pfind(uap->pid);
-       if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid) {
-               u.u_error = ESRCH;
-               return;
-       }
+       if (p == 0 || p->p_stat != SSTOP || p->p_pptr != curp ||
+           !(p->p_flag & STRC))
+               return (ESRCH);
        while (ipc.ip_lock)
                sleep((caddr_t)&ipc, IPCPRI);
        ipc.ip_lock = p->p_pid;
        while (ipc.ip_lock)
                sleep((caddr_t)&ipc, IPCPRI);
        ipc.ip_lock = p->p_pid;
@@ -70,138 +76,154 @@ ptrace()
                        setrun(p);
                sleep((caddr_t)&ipc, IPCPRI);
        }
                        setrun(p);
                sleep((caddr_t)&ipc, IPCPRI);
        }
-       u.u_r.r_val1 = ipc.ip_data;
-       if (ipc.ip_req < 0)
-               u.u_error = EIO;
+       *retval = ipc.ip_data;
        ipc.ip_lock = 0;
        wakeup((caddr_t)&ipc);
        ipc.ip_lock = 0;
        wakeup((caddr_t)&ipc);
+       if (ipc.ip_req < 0)
+               return (EIO);
+       return (0);
 }
 
 }
 
-#if vax
-#define        NIPCREG 16
-#endif
-#if sun
-#define        NIPCREG 17
-#endif
-int ipcreg[NIPCREG] =
-#if vax
-       {R0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,AP,FP,SP,PC};
-#endif
-#if sun
-       {R0,R1,R2,R3,R4,R5,R6,R7,AR0,AR1,AR2,AR3,AR4,AR5,AR6,AR7,PC};
-#endif
+#define        PHYSOFF(p, o) ((caddr_t)(p) + (o))
 
 
-#define        PHYSOFF(p, o) \
-       ((physadr)(p)+((o)/sizeof(((physadr)0)->r[0])))
+#if defined(i386)
+#undef        PC
+#undef        SP
+#undef        PS
+#undef        R0
+#undef        R1
+
+#define       PC      tEIP
+#define       SP      tESP
+#define       PS      tEFLAGS
+#define       R0      tEDX
+#define       R1      tECX
+#endif
 
 /*
 
 /*
- * Code that the child process
- * executes to implement the command
- * of the parent process in tracing.
+ * Transmit a tracing request from the parent to the child process
+ * being debugged. This code runs in the context of the child process
+ * to fulfill the command requested by the parent.
  */
  */
-procxmt()
+procxmt(p)
+       register struct proc *p;
 {
 {
-       register int i;
-       register *p;
-       register struct text *xp;
+       register int i, *poff;
+       extern char kstack[];
 
 
-       if (ipc.ip_lock != u.u_procp->p_pid)
+       if (ipc.ip_lock != p->p_pid)
                return (0);
                return (0);
-       u.u_procp->p_slptime = 0;
+       p->p_slptime = 0;
+       p->p_addr->u_kproc.kp_proc.p_md.md_regs = p->p_md.md_regs; /* u.u_ar0 */
        i = ipc.ip_req;
        ipc.ip_req = 0;
        switch (i) {
 
        i = ipc.ip_req;
        ipc.ip_req = 0;
        switch (i) {
 
-       /* read user I */
-       case 1:
+       case PT_READ_I:                 /* read the child's text space */
                if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
                        goto error;
                ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
                break;
 
                if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
                        goto error;
                ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
                break;
 
-       /* read user D */
-       case 2:
+       case PT_READ_D:                 /* read the child's data space */
                if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
                        goto error;
                ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
                break;
 
                if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
                        goto error;
                ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
                break;
 
-       /* read u */
-       case 3:
+       case PT_READ_U:                 /* read the child's u. */
+#ifdef HPUXCOMPAT
+               if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE)
+                       i = hpuxtobsduoff(ipc.ip_addr);
+               else
+#endif
                i = (int)ipc.ip_addr;
                i = (int)ipc.ip_addr;
-               if (i<0 || i >= ctob(UPAGES))
+               if ((u_int) i > ctob(UPAGES)-sizeof(int) || (i & 1) != 0)
                        goto error;
                        goto error;
-               ipc.ip_data = *(int *)PHYSOFF(&u, i);
+               ipc.ip_data = *(int *)PHYSOFF(p->p_addr, i);
                break;
 
                break;
 
-       /* write user I */
-       /* Must set up to allow writing */
-       case 4:
-               /*
-                * If text, must assure exclusive use
-                */
-               if (xp = u.u_procp->p_textp) {
-                       if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX)
-                               goto error;
-                       xp->x_iptr->i_flag &= ~ITEXT;
-               }
-               i = -1;
+       case PT_WRITE_I:                /* write the child's text space */
                if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
                if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
-                       if (chgprot((caddr_t)ipc.ip_addr, RW) &&
-                           chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW))
+                       vm_offset_t sa, ea;
+                       int rv;
+
+                       sa = trunc_page((vm_offset_t)ipc.ip_addr);
+                       ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1);
+                       rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
+                                       VM_PROT_DEFAULT, FALSE);
+                       if (rv == KERN_SUCCESS) {
                                i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
                                i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
-                       (void) chgprot((caddr_t)ipc.ip_addr, RO);
-                       (void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO);
+                               (void) vm_map_protect(&p->p_vmspace->vm_map,
+                                       sa, ea, VM_PROT_READ|VM_PROT_EXECUTE,
+                                       FALSE);
+                       }
                }
                if (i < 0)
                        goto error;
                }
                if (i < 0)
                        goto error;
-               if (xp)
-                       xp->x_flag |= XWRIT;
                break;
 
                break;
 
-       /* write user D */
-       case 5:
+       case PT_WRITE_D:                /* write the child's data space */
                if (suword((caddr_t)ipc.ip_addr, 0) < 0)
                        goto error;
                (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data);
                break;
 
                if (suword((caddr_t)ipc.ip_addr, 0) < 0)
                        goto error;
                (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data);
                break;
 
-       /* write u */
-       case 6:
+       case PT_WRITE_U:                /* write the child's u. */
+#ifdef HPUXCOMPAT
+               if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE)
+                       i = hpuxtobsduoff(ipc.ip_addr);
+               else
+#endif
                i = (int)ipc.ip_addr;
                i = (int)ipc.ip_addr;
-               p = (int *)PHYSOFF(&u, i);
+#ifdef mips
+               poff = (int *)PHYSOFF(curproc->p_addr, i);
+#else
+               poff = (int *)PHYSOFF(kstack, i);
+#endif
                for (i=0; i<NIPCREG; i++)
                for (i=0; i<NIPCREG; i++)
-                       if (p == &u.u_ar0[ipcreg[i]])
+                       if (poff == &p->p_md.md_regs[ipcreg[i]])
                                goto ok;
                                goto ok;
-               if (p == &u.u_ar0[PS]) {
+               if (poff == &p->p_md.md_regs[PS]) {
                        ipc.ip_data |= PSL_USERSET;
                        ipc.ip_data |= PSL_USERSET;
-                       ipc.ip_data &=  ~PSL_USERCLR;
+                       ipc.ip_data &= ~PSL_USERCLR;
+#ifdef PSL_CM_CLR
+                       if (ipc.ip_data & PSL_CM)
+                               ipc.ip_data &= ~PSL_CM_CLR;
+#endif
                        goto ok;
                }
                        goto ok;
                }
+#if defined(hp300) || defined(luna68k)
+#ifdef FPCOPROC
+               if (poff >= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_regs &&
+                   poff <= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_fpiar)
+                       goto ok;
+#endif
+#endif
                goto error;
 
        ok:
                goto error;
 
        ok:
-               *p = ipc.ip_data;
+               *poff = ipc.ip_data;
                break;
 
                break;
 
-       /* set signal and continue */
-       /* one version causes a trace-trap */
-       case 9:
-       case 7:
+       case PT_STEP:                   /* single step the child */
+       case PT_CONTINUE:               /* continue the child */
                if ((int)ipc.ip_addr != 1)
                if ((int)ipc.ip_addr != 1)
-                       u.u_ar0[PC] = (int)ipc.ip_addr;
+                       p->p_md.md_regs[PC] = (int)ipc.ip_addr;
                if ((unsigned)ipc.ip_data > NSIG)
                        goto error;
                if ((unsigned)ipc.ip_data > NSIG)
                        goto error;
-               u.u_procp->p_cursig = ipc.ip_data;      /* see issig */
-               if (i == 9)
-                       u.u_ar0[PS] |= PSL_T;
+               p->p_xstat = ipc.ip_data;       /* see issig */
+#ifdef PSL_T
+               /* need something more machine independent here... */
+               if (i == PT_STEP) 
+                       p->p_md.md_regs[PS] |= PSL_T;
+#endif
                wakeup((caddr_t)&ipc);
                return (1);
 
                wakeup((caddr_t)&ipc);
                return (1);
 
-       /* force exit */
-       case 8:
+       case PT_KILL:                   /* kill the child process */
                wakeup((caddr_t)&ipc);
                wakeup((caddr_t)&ipc);
-               exit(u.u_procp->p_cursig);
+               exit(p, (int)p->p_xstat);
 
        default:
        error:
 
        default:
        error:
@@ -210,3 +232,28 @@ procxmt()
        wakeup((caddr_t)&ipc);
        return (0);
 }
        wakeup((caddr_t)&ipc);
        return (0);
 }
+
+/*
+ * Process debugging system call.
+ */
+/* ARGSUSED */
+profil(p, uap, retval)
+       struct proc *p;
+       register struct args {
+               short   *bufbase;
+               unsigned bufsize;
+               unsigned pcoffset;
+               unsigned pcscale;
+       } *uap;
+       int *retval;
+{
+       register struct uprof *upp = &p->p_stats->p_prof;
+
+       upp->pr_base = uap->bufbase;
+       upp->pr_size = uap->bufsize;
+       upp->pr_off = uap->pcoffset;
+       upp->pr_scale = uap->pcscale;
+       if (uap->pcscale)
+               startprofclock(p);
+       return (0);
+}