From b41c1385b99723d468877994cc776ed594d41f7d Mon Sep 17 00:00:00 2001 From: Bill Joy Date: Sun, 9 Nov 1980 08:35:32 -0800 Subject: [PATCH] BSD 4 development Work on file usr/src/sys/sys/prf.c Work on file usr/src/sys/sys/main.c Work on file usr/src/sys/sys/sig.c Work on file usr/src/sys/sys/sys1.c Work on file usr/src/sys/sys/trap.c Synthesized-from: CSRG//cd1/4.0 --- usr/src/sys/sys/main.c | 245 ++++++++++++++ usr/src/sys/sys/prf.c | 226 +++++++++++++ usr/src/sys/sys/sig.c | 722 +++++++++++++++++++++++++++++++++++++++++ usr/src/sys/sys/sys1.c | 670 ++++++++++++++++++++++++++++++++++++++ usr/src/sys/sys/trap.c | 225 +++++++++++++ 5 files changed, 2088 insertions(+) create mode 100644 usr/src/sys/sys/main.c create mode 100644 usr/src/sys/sys/prf.c create mode 100644 usr/src/sys/sys/sig.c create mode 100644 usr/src/sys/sys/sys1.c create mode 100644 usr/src/sys/sys/trap.c diff --git a/usr/src/sys/sys/main.c b/usr/src/sys/sys/main.c new file mode 100644 index 0000000000..d57eebe0bb --- /dev/null +++ b/usr/src/sys/sys/main.c @@ -0,0 +1,245 @@ +/* main.c 4.2 11/9/80 */ + +#include "../h/param.h" +#include "../h/systm.h" +#include "../h/dir.h" +#include "../h/user.h" +#include "../h/filsys.h" +#include "../h/mount.h" +#include "../h/map.h" +#include "../h/proc.h" +#include "../h/inode.h" +#include "../h/seg.h" +#include "../h/conf.h" +#include "../h/buf.h" +#include "../h/mtpr.h" +#include "../h/pte.h" +#include "../h/clock.h" +#include "../h/vm.h" +#include "../h/cmap.h" +#include "../h/text.h" +#include "../h/vlimit.h" + +/* + * Initialization code. + * Called from cold start routine as + * soon as a stack and segmentation + * have been established. + * Functions: + * clear and free user core + * turn on clock + * hand craft 0th process + * call all initialization routines + * fork - process 0 to schedule + * - process 2 to page out + * - process 1 execute bootstrap + * + * loop at loc 13 (0xd) in user mode -- /etc/init + * cannot be executed. + */ +main(firstaddr) +{ + register int i; + + cpusid = mfpr(SID); /* get system identification */ +#ifdef FASTVAX + rqinit(); +#endif + startup(firstaddr); + if (lotsfree == 0) + lotsfree = LOTSFREE; + + /* + * set up system process 0 (swapper) + */ + + proc[0].p_p0br = (struct pte *)mfpr(P0BR); + proc[0].p_szpt = 1; + proc[0].p_addr = uaddr(&proc[0]); + proc[0].p_stat = SRUN; + proc[0].p_flag |= SLOAD|SSYS; + proc[0].p_nice = NZERO; + u.u_procp = &proc[0]; + u.u_cmask = CMASK; + for (i = 1; i < sizeof(u.u_limit)/sizeof(u.u_limit[0]); i++) + switch (i) { + + case LIM_STACK: + u.u_limit[i] = 512*1024; + continue; + case LIM_DATA: + u.u_limit[i] = ctob(MAXDSIZ); + continue; + default: + u.u_limit[i] = INFINITY; + continue; + } + clkstart(); + + /* + * Initialize devices and + * set up 'known' i-nodes + */ + + ihinit(); + bhinit(); + cinit(); + binit(); + bswinit(); + iinit(); + rootdir = iget(rootdev, (ino_t)ROOTINO); + rootdir->i_flag &= ~ILOCK; + u.u_cdir = iget(rootdev, (ino_t)ROOTINO); + u.u_cdir->i_flag &= ~ILOCK; + u.u_rdir = NULL; + u.u_dmap = zdmap; + u.u_smap = zdmap; + + /* + * make page-out daemon (process 2) + * the daemon has ctopt(NSWBUF*CLSIZE*KLMAX) pages of page + * table so that it can map dirty pages into + * its address space during asychronous pushes. + */ + + mpid = 1; + proc[0].p_szpt = clrnd(ctopt(NSWBUF*CLSIZE*KLMAX + UPAGES)); + proc[1].p_stat = SZOMB; /* force it to be in proc slot 2 */ + if (newproc(0)) { + proc[2].p_flag |= SLOAD|SSYS; + proc[2].p_dsize = u.u_dsize = NSWBUF*CLSIZE*KLMAX; + pageout(); + } + + /* + * make init process and + * enter scheduling loop + */ + + mpid = 0; + proc[1].p_stat = 0; + proc[0].p_szpt = CLSIZE; + if (newproc(0)) { + expand(clrnd((int)btoc(szicode)), P0BR); + (void) swpexpand(u.u_dsize, 0, &u.u_dmap, &u.u_smap); + (void) copyout((caddr_t)icode, (caddr_t)0, (unsigned)szicode); + /* + * Return goes to loc. 0 of user init + * code just copied out. + */ + return; + } + proc[0].p_szpt = 1; + sched(); +} + +/* + * iinit is called once (from main) + * very early in initialization. + * It reads the root's super block + * and initializes the current date + * from the last modified date. + * + * panic: iinit -- cannot read the super + * block. Usually because of an IO error. + */ +iinit() +{ + register struct buf *cp, *bp; + register struct filsys *fp; + + (*bdevsw[major(rootdev)].d_open)(rootdev, 1); + bp = bread(rootdev, SUPERB); + cp = geteblk(); + if(u.u_error) + panic("iinit"); + bcopy(bp->b_un.b_addr, cp->b_un.b_addr, sizeof(struct filsys)); + brelse(bp); + mount[0].m_bufp = cp; + mount[0].m_dev = rootdev; + fp = cp->b_un.b_filsys; + fp->s_flock = 0; + fp->s_ilock = 0; + fp->s_ronly = 0; + fp->s_lasti = 1; + fp->s_nbehind = 0; + clkinit(fp->s_time); + bootime = time; +} + +/* + * This is the set of buffers proper, whose heads + * were declared in buf.h. There can exist buffer + * headers not pointing here that are used purely + * as arguments to the I/O routines to describe + * I/O to be done-- e.g. swap headers swbuf[] for + * swapping. + * + * These are actually allocated kernel map slots and space is + * allocated in locore.s for them. + */ +char buffers[NBUF][BSIZE]; + +/* + * Initialize the buffer I/O system by freeing + * all buffers and setting all device buffer lists to empty. + */ +binit() +{ + register struct buf *bp; + register struct buf *dp; + register int i; + struct bdevsw *bdp; + struct swdevt *swp; + + bfreelist.b_forw = bfreelist.b_back = + bfreelist.av_forw = bfreelist.av_back = &bfreelist; + for (i=0; ib_dev = NODEV; + bp->b_un.b_addr = buffers[i]; + bp->b_back = &bfreelist; + bp->b_forw = bfreelist.b_forw; + bfreelist.b_forw->b_back = bp; + bfreelist.b_forw = bp; + bp->b_flags = B_BUSY; + brelse(bp); + } + for (bdp = bdevsw; bdp->d_open; bdp++) { + dp = bdp->d_tab; + if(dp) { + dp->b_forw = dp; + dp->b_back = dp; + } + nblkdev++; + } + /* + * Count swap devices, and adjust total swap space available. + * Some of this space will not be available until a vswapon() + * system is issued, usually when the system goes multi-user. + */ + nswdev = 0; + for (swp = swdevt; swp->sw_dev; swp++) + nswdev++; + if (nswdev == 0) + panic("binit"); + nswap *= nswdev; + maxpgio *= nswdev; + swfree(0); +} + +/* + * Initialize linked list of free swap + * headers. These do not actually point + * to buffers, but rather to pages that + * are being swapped in and out. + */ +bswinit() +{ + register int i; + + bswlist.av_forw = &swbuf[0]; + for (i=0; i= &trcbuf[TRCBUFS]) { + trcbufp = trcbuf; + trcwrap = 1; + } + } else +#endif + putchar(c, trace); + } else if (c == 'D') { + printn(*(long *)adx, 10, trace); + adx += (sizeof(long) / sizeof(int)) - 1; + } + adx++; + goto loop; +} + +printx(x, trace) +long x; +{ + int i; + + for (i = 0; i < 8; i++) + putchar("0123456789ABCDEF"[(x>>((7-i)*4))&0xf], trace); +} + +/* + * Print an unsigned integer in base b. + */ +printn(n, b, trace) +long n; +{ + register long a; + + if (n<0) { /* shouldn't happen */ + putchar('-', trace); + n = -n; + } + if(a = n/b) + printn(a, b, trace); + putchar("0123456789ABCDEF"[(int)(n%b)], trace); +} + +/* + * Panic is called on unresolvable fatal errors. + * It syncs, prints "panic: mesg", and then reboots. + */ +panic(s) +char *s; +{ + panicstr = s; + printf("panic: %s\n", s); + (void) spl0(); + for(;;) + boot(RB_PANIC, RB_AUTOBOOT); +} + +/* + * prdev prints a warning message of the + * form "mesg on dev x/y". + * x and y are the major and minor parts of + * the device argument. + */ +prdev(str, dev) +char *str; +dev_t dev; +{ + + printf("%s on dev %u/%u\n", str, major(dev), minor(dev)); +} + +/* + * deverr prints a diagnostic from + * a device driver. + * It prints the device, block number, + * and an octal word (usually some error + * status register) passed as argument. + */ +deverror(bp, o1, o2) +register struct buf *bp; +{ + + prdev("err", bp->b_dev); + printf("bn=%d er=%x,%x\n", bp->b_blkno, o1,o2); +} + +#ifdef TRACE +dumptrc() +{ + register char *cp; + register int pos, nch; + + nch = trcprt; + if (nch < 0 || nch > TRCBUFS) + nch = TRCBUFS; + pos = (trcbufp - trcbuf) - nch; + if (pos < 0) + if (trcwrap) + pos += TRCBUFS; + else { + nch += pos; + pos = 0; + } + for (cp = &trcbuf[pos]; nch > 0; nch--) { + putchar(*cp++, 0); + if (cp >= &trcbuf[TRCBUFS]) + cp = trcbuf; + } +} +#else +/*ARGSUSED*/ +dumptrc(nch) + int nch; +{ + +} +#endif + +char *msgbufp = msgbuf; /* Next saved printf character */ +/* + * Print a character on console or in internal trace buffer. + * If destination is console then the last MSGBUFS characters + * are saved in msgbuf for inspection later. + */ +/*ARGSUSED*/ +putchar(c, trace) +register c; +{ + +#ifdef TRACE + if (trace) { + *trcbufp++ = c; + if (trcbufp >= &trcbuf[TRCBUFS]) { + trcbufp = trcbuf; + trcwrap = 1; + } + return; + } +#endif + if (c != '\0' && c != '\r' && c != 0177) { + *msgbufp++ = c; + if (msgbufp >= &msgbuf[MSGBUFS]) + msgbufp = msgbuf; + } + if (c == 0) + return; + cnputc(c); +} diff --git a/usr/src/sys/sys/sig.c b/usr/src/sys/sys/sig.c new file mode 100644 index 0000000000..237fd540fb --- /dev/null +++ b/usr/src/sys/sys/sig.c @@ -0,0 +1,722 @@ +/* sig.c 4.3 11/9/80 */ + +#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/mtpr.h" +#include "../h/pte.h" +#include "../h/psl.h" +#include "../h/vm.h" +#include "../h/buf.h" +#include "../h/vlimit.h" + +/* + * Priority for tracing + */ +#define IPCPRI PZERO + +/* + * Tracing variables. + * Used to pass trace command from + * parent to child being traced. + * This data base cannot be + * shared and is locked + * per user. + */ +struct +{ + int ip_lock; + int ip_req; + int *ip_addr; + int ip_data; +} ipc; + +/* + * Send the specified signal to + * all processes with 'pgrp' as + * process group. + * Called by tty.c for quits and + * interrupts. + */ +gsignal(pgrp, sig) +register pgrp; +{ + register struct proc *p; + + if(pgrp == 0) + return; + for(p = &proc[0]; p < &proc[NPROC]; p++) + if(p->p_pgrp == pgrp) + psignal(p, sig); +} + +/* + * Send the specified signal to + * the specified process. + */ +psignal(p, sig) +register struct proc *p; +register int sig; +{ + register s; + register int (*action)(); + long sigmask; + + if((unsigned)sig >= NSIG) + return; + sigmask = (1L << (sig-1)); + + /* + * If proc is traced, always give parent a chance. + * Otherwise get the signal action from the bits in the proc table. + */ + if (p->p_flag & STRC) + action = SIG_DFL; + else { + s = (p->p_siga1&sigmask) != 0; + s <<= 1; + s |= (p->p_siga0&sigmask) != 0; + action = (int(*)())s; + /* + * If the signal is ignored, we forget about it immediately. + */ + if (action == SIG_IGN) + return; + } + if (sig) + p->p_sig |= sigmask; + /* + * Defer further processing for signals which are held. + */ + if (action == SIG_HOLD) + return; + s = spl6(); + switch (p->p_stat) { + + case SSLEEP: + /* + * If process is sleeping at negative priority + * we can't interrupt the sleep... the signal will + * be noticed when the process returns through + * trap() or syscall(). + */ + if (p->p_pri <= PZERO) + goto out; + /* + * Process is sleeping and traced... make it runnable + * so it can discover the signal in issig() and stop + * for the parent. + */ + if (p->p_flag&STRC) + goto run; + switch (sig) { + + case SIGSTOP: + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + /* + * These are the signals which by default + * stop a process. + */ + if (action != SIG_DFL) + goto run; + /* + * Don't clog system with children of init + * stopped from the keyboard. + */ + if (sig != SIGSTOP && p->p_pptr == &proc[1]) { + psignal(p, SIGKILL); + p->p_sig &= ~sigmask; + return; + } + /* + * If a child in vfork(), stopping could + * cause deadlock. + */ + if (p->p_flag&SVFORK) + goto out; + p->p_sig &= ~sigmask; + p->p_cursig = sig; + stop(p); + goto out; + + case SIGTINT: + case SIGCHLD: + /* + * These signals are special in that they + * don't get propogated... if the process + * isn't interested, forget it. + */ + if (action != SIG_DFL) + goto run; + p->p_sig &= ~sigmask; /* take it away */ + goto out; + + default: + /* + * All other signals cause the process to run + */ + goto run; + } + /*NOTREACHED*/ + + case SSTOP: + /* + * If traced process is already stopped, + * then no further action is necessary. + */ + if (p->p_flag&STRC) + goto out; + switch (sig) { + + case SIGKILL: + /* + * Kill signal always sets processes running. + */ + goto run; + + case SIGCONT: + /* + * If the process catches SIGCONT, let it handle + * the signal itself. If it isn't waiting on + * an event, then it goes back to run state. + * Otherwise, process goes back to sleep state. + */ + if (action != SIG_DFL || p->p_wchan == 0) + goto run; + p->p_stat = SSLEEP; + goto out; + + case SIGSTOP: + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + /* + * Already stopped, don't need to stop again. + * (If we did the shell could get confused.) + */ + p->p_sig &= ~sigmask; /* take it away */ + goto out; + + default: + /* + * If process is sleeping interruptibly, then + * unstick it so that when it is continued + * it can look at the signal. + * But don't setrun the process as its not to + * be unstopped by the signal alone. + */ + if (p->p_wchan && p->p_pri > PZERO) + unsleep(p); + goto out; + } + /*NOTREACHED*/ + + default: + /* + * SRUN, SIDL, SZOMB do nothing with the signal. + * It will either never be noticed, or noticed very soon. + */ + goto out; + } + /*NOTREACHED*/ +run: + /* + * Raise priority to at least PUSER. + */ + if (p->p_pri > PUSER) + if ((p != u.u_procp || noproc) && p->p_stat == SRUN && + (p->p_flag & SLOAD)) { + remrq(p); + p->p_pri = PUSER; + setrq(p); + } else + p->p_pri = PUSER; + setrun(p); +out: + splx(s); +} + +/* + * Returns true if the current + * process has a signal to process. + * The signal to process is put in p_cursig. + * This is asked at least once each time a process enters the + * system (though this can usually be done without actually + * calling issig by checking the pending signal masks.) + * A signal does not do anything + * directly to a process; it sets + * a flag that asks the process to + * do something to itself. + */ +issig() +{ + register struct proc *p; + register int sig; + long sigbits; + long sigmask; + + p = u.u_procp; + for (;;) { + sigbits = p->p_sig; + if ((p->p_flag&STRC) == 0) + sigbits &= ~p->p_ignsig; + if (p->p_flag&SVFORK) +#define bit(a) (1<<(a-1)) + sigbits &= ~(bit(SIGSTOP)|bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU)); + if (sigbits == 0) + break; + sig = ffs(sigbits); + sigmask = 1L << (sig-1); + p->p_sig &= ~sigmask; /* take the signal! */ + p->p_cursig = sig; + if (p->p_flag&STRC && (p->p_flag&SVFORK)==0) { + /* + * If traced, always stop, and stay + * stopped until released by the parent. + */ + do { + stop(p); + swtch(); + } while (!procxmt() && p->p_flag&STRC); + /* + * If parent wants us to take the signal, + * then it will leave it in p->p_cursig; + * otherwise we just look for signals again. + */ + sig = p->p_cursig; + if (sig == 0) + continue; + } + switch (u.u_signal[sig]) { + + case SIG_DFL: + /* + * Don't take default actions on system processes. + */ + if (p <= &proc[2]) + break; + switch (sig) { + + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + /* + * Children of init aren't allowed to stop + * on signals from the keyboard. + */ + if (p->p_pptr == &proc[1]) { + psignal(p, SIGKILL); + continue; + } + /* fall into ... */ + + case SIGSTOP: + if (p->p_flag&STRC) + continue; + stop(p); + swtch(); + continue; + + case SIGTINT: + case SIGCONT: + case SIGCHLD: + /* + * These signals are normally not + * sent if the action is the default. + * This can happen only if you reset the + * signal action from an action which was + * not deferred to SIG_DFL before the + * system gets a chance to post the signal. + */ + continue; /* == ignore */ + + default: + goto send; + } + /*NOTREACHED*/ + + case SIG_HOLD: + case SIG_IGN: + /* + * Masking above should prevent us + * ever trying to take action on a held + * or ignored signal, unless process is traced. + */ + if ((p->p_flag&STRC) == 0) + printf("issig\n"); + continue; + + default: + /* + * This signal has an action, let + * psig process it. + */ + goto send; + } + /*NOTREACHED*/ + } + /* + * Didn't find a signal to send. + */ + p->p_cursig = 0; + return (0); + +send: + /* + * Let psig process the signal. + */ + return (sig); +} + +ffs(mask) +register long mask; +{ + register int i; + + for(i=1; i>= 1; + } + return(0); +} + +/* + * Put the argument process into the stopped + * state and notify the parent via wakeup and/or signal. + */ +stop(p) + register struct proc *p; +{ + + p->p_stat = SSTOP; + p->p_flag &= ~SWTED; + wakeup((caddr_t)p->p_pptr); + /* + * Avoid sending signal to parent if process is traced + */ + if (p->p_flag&STRC) + return; + psignal(p->p_pptr, SIGCHLD); +} + +/* + * Perform the action specified by + * the current signal. + * The usual sequence is: + * if(issig()) + * psig(); + * The signal bit has already been cleared by issig, + * and the current signal number stored in p->p_cursig. + */ +psig() +{ + register struct proc *rp = u.u_procp; + register int n = rp->p_cursig; + long sigmask = 1L << (n-1); + register int (*action)(); + + if (rp->p_cursig == 0) + panic("psig"); + action = u.u_signal[n]; + if (action != SIG_DFL) { + if (action == SIG_IGN || action == SIG_HOLD) + panic("psig action"); + u.u_error = 0; + if(n != SIGILL && n != SIGTRAP) + u.u_signal[n] = 0; + /* + * If this catch value indicates automatic holding of + * subsequent signals, set the hold value. + */ + if (SIGISDEFER(action)) { + (void) spl6(); + if ((int)SIG_HOLD & 1) + rp->p_siga0 |= sigmask; + else + rp->p_siga0 &= ~sigmask; + if ((int)SIG_HOLD & 2) + rp->p_siga1 |= sigmask; + else + rp->p_siga1 &= ~sigmask; + u.u_signal[n] = SIG_HOLD; + (void) spl0(); + action = SIGUNDEFER(action); + } + sendsig(action, n); + rp->p_cursig = 0; + return; + } + switch (n) { + + case SIGILL: + case SIGIOT: + case SIGBUS: + case SIGQUIT: + case SIGTRAP: + case SIGEMT: + case SIGFPE: + case SIGSEGV: + case SIGSYS: + u.u_arg[0] = n; + if(core()) + n += 0200; + } + exit(n); +} + +/* + * Create a core image on the file "core" + * If you are looking for protection glitches, + * there are probably a wealth of them here + * when this occurs to a suid command. + * + * It writes UPAGES block of the + * user.h area followed by the entire + * data+stack segments. + */ + +core() +{ + register struct inode *ip; + extern schar(); + +/* + if (coresw) + panic("core"); +*/ + if (coresw) { + int i; + for (i = 0; i < 10; i++) + if (u.u_comm[i]) + putchar(u.u_comm[i], 0); + printf(", uid %d\n", u.u_uid); + if (coresw&2) + asm("halt"); + } + if (ctob(UPAGES+u.u_dsize+u.u_ssize) >= u.u_limit[LIM_CORE]) + return (0); + u.u_error = 0; + u.u_dirp = "core"; + ip = namei(schar, 1); + if(ip == NULL) { + if(u.u_error) + return(0); + ip = maknode(0666); + if (ip==NULL) + return(0); + } + if(!access(ip, IWRITE) && + (ip->i_mode&IFMT) == IFREG && ip->i_vfdcnt == 0 && +#ifdef UCB + u.u_uid == u.u_ruid && ip->i_nlink == 1) { +#else + u.u_uid == u.u_ruid) { +#endif + itrunc(ip); + u.u_offset = 0; + u.u_base = (caddr_t)&u; + u.u_count = ctob(UPAGES); + u.u_segflg = 1; + writei(ip); + u.u_base = (char *)ctob(u.u_tsize); + u.u_count = ctob(u.u_dsize); + u.u_segflg = 0; + writei(ip); + u.u_base = (char *)(USRSTACK - ctob(u.u_ssize)); + u.u_count = ctob(u.u_ssize); + writei(ip); + } else + u.u_error = EFAULT; + iput(ip); + return(u.u_error==0); +} + +/* + * grow the stack to include the SP + * true return if successful. + */ +grow(sp) +unsigned sp; +{ + register si; + + if(sp >= USRSTACK-ctob(u.u_ssize)) + return(0); + si = clrnd(btoc((USRSTACK-sp)) - u.u_ssize + SINCR); + if (ctob(u.u_ssize+si) > u.u_limit[LIM_STACK]) + return(0); + if (chksize(u.u_tsize, u.u_dsize, u.u_ssize+si)) + return(0); + if (swpexpand(u.u_dsize, u.u_ssize+si, &u.u_dmap, &u.u_smap)==0) + return(0); + + expand(si, P1BR); + return(1); +} + +/* + * sys-trace system call. + */ +ptrace() +{ + register struct proc *p; + register struct a { + int req; + int pid; + int *addr; + int data; + } *uap; + + uap = (struct a *)u.u_ap; + if (uap->req <= 0) { + u.u_procp->p_flag |= STRC; + return; + } + p = pfind(uap->pid); + if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid) { + u.u_error = ESRCH; + return; + } + while (ipc.ip_lock) + sleep((caddr_t)&ipc, IPCPRI); + ipc.ip_lock = p->p_pid; + ipc.ip_data = uap->data; + ipc.ip_addr = uap->addr; + ipc.ip_req = uap->req; + p->p_flag &= ~SWTED; + while (ipc.ip_req > 0) { + if (p->p_stat==SSTOP) + setrun(p); + sleep((caddr_t)&ipc, IPCPRI); + } + u.u_r.r_val1 = ipc.ip_data; + if (ipc.ip_req < 0) + u.u_error = EIO; + ipc.ip_lock = 0; + wakeup((caddr_t)&ipc); +} + +int ipcreg[] = {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC}; +/* + * Code that the child process + * executes to implement the command + * of the parent process in tracing. + */ +procxmt() +{ + register int i; + register *p; + register struct text *xp; + + if (ipc.ip_lock != u.u_procp->p_pid) + return(0); + u.u_procp->p_slptime = 0; + i = ipc.ip_req; + ipc.ip_req = 0; + switch (i) { + + /* read user I */ + case 1: + 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: + 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: + i = (int)ipc.ip_addr; + if (i<0 || i >= ctob(UPAGES)) + goto error; + ipc.ip_data = ((physadr)&u)->r[i>>2]; + 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; + if (chgprot((caddr_t)ipc.ip_addr, RW) && + chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW)) + 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); + if (i < 0) + goto error; + if (xp) + xp->x_flag |= XWRIT; + break; + + /* write user D */ + case 5: + 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: + i = (int)ipc.ip_addr; + p = (int *)&((physadr)&u)->r[i>>2]; + for (i=0; i<16; i++) + if (p == &u.u_ar0[ipcreg[i]]) + goto ok; + if (p == &u.u_ar0[PS]) { + ipc.ip_data |= PSL_CURMOD|PSL_PRVMOD; + ipc.ip_data &= ~PSL_USERCLR; + goto ok; + } + goto error; + + ok: + *p = ipc.ip_data; + break; + + /* set signal and continue */ + /* one version causes a trace-trap */ + case 9: + case 7: + if ((int)ipc.ip_addr != 1) + u.u_ar0[PC] = (int)ipc.ip_addr; + 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; + wakeup((caddr_t)&ipc); + return (1); + + /* force exit */ + case 8: + wakeup((caddr_t)&ipc); + exit(u.u_procp->p_cursig); + + default: + error: + ipc.ip_req = -1; + } + wakeup((caddr_t)&ipc); + return(0); +} diff --git a/usr/src/sys/sys/sys1.c b/usr/src/sys/sys/sys1.c new file mode 100644 index 0000000000..3949f508a8 --- /dev/null +++ b/usr/src/sys/sys/sys1.c @@ -0,0 +1,670 @@ +/* sys1.c 4.2 11/9/80 */ + +#include "../h/param.h" +#include "../h/systm.h" +#include "../h/map.h" +#include "../h/mtpr.h" +#include "../h/dir.h" +#include "../h/user.h" +#include "../h/proc.h" +#include "../h/buf.h" +#include "../h/reg.h" +#include "../h/inode.h" +#include "../h/seg.h" +#include "../h/acct.h" +#include "/usr/include/wait.h" +#include "../h/pte.h" +#include "../h/vm.h" +#include "../h/text.h" +#include "../h/psl.h" +#include "../h/vlimit.h" +#include "../h/file.h" + +/* + * exec system call, with and without environments. + */ +struct execa { + char *fname; + char **argp; + char **envp; +}; + +exec() +{ + ((struct execa *)u.u_ap)->envp = NULL; + exece(); +} + +exece() +{ + register nc; + register char *cp; + register struct buf *bp; + register struct execa *uap; + int na, ne, ucp, ap, c; + struct inode *ip; + swblk_t bno; + + if ((ip = namei(uchar, 0)) == NULL) + return; + bno = 0; + bp = 0; + if(access(ip, IEXEC)) + goto bad; + if((ip->i_mode & IFMT) != IFREG || + (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { + u.u_error = EACCES; + goto bad; + } + /* + * Collect arguments on "file" in swap space. + */ + na = 0; + ne = 0; + nc = 0; + uap = (struct execa *)u.u_ap; + if ((bno = malloc(argmap, ctod(clrnd((int) btoc(NCARGS))))) == 0) { + swkill(u.u_procp, "exece"); + goto bad; + } + if (bno % CLSIZE) + panic("execa malloc"); + if (uap->argp) for (;;) { + ap = NULL; + if (uap->argp) { + ap = fuword((caddr_t)uap->argp); + uap->argp++; + } + if (ap==NULL && uap->envp) { + uap->argp = NULL; + if ((ap = fuword((caddr_t)uap->envp)) == NULL) + break; + uap->envp++; + ne++; + } + if (ap==NULL) + break; + na++; + if(ap == -1) + u.u_error = EFAULT; + do { + if (nc >= NCARGS-1) + u.u_error = E2BIG; + if ((c = fubyte((caddr_t)ap++)) < 0) + u.u_error = EFAULT; + if (u.u_error) { + if (bp) + brelse(bp); + bp = 0; + goto badarg; + } + if ((nc&BMASK) == 0) { + if (bp) + bdwrite(bp); + bp = getblk(argdev, + (daddr_t)(dbtofsb(bno)+(nc>>BSHIFT))); + cp = bp->b_un.b_addr; + } + nc++; + *cp++ = c; + } while (c>0); + } + if (bp) + bdwrite(bp); + bp = 0; + nc = (nc + NBPW-1) & ~(NBPW-1); + getxfile(ip, nc + (na+4)*NBPW); + if (u.u_error) { +badarg: + for (c = 0; c < nc; c += BSIZE) + if (bp = baddr(argdev, dbtofsb(bno)+(c>>BSHIFT))) { + bp->b_flags |= B_AGE; /* throw away */ + bp->b_flags &= ~B_DELWRI; /* cancel io */ + brelse(bp); + bp = 0; + } + goto bad; + } + + /* + * copy back arglist + */ + + ucp = USRSTACK - nc - NBPW; + ap = ucp - na*NBPW - 3*NBPW; + u.u_ar0[SP] = ap; + (void) suword((caddr_t)ap, na-ne); + nc = 0; + for (;;) { + ap += NBPW; + if (na==ne) { + (void) suword((caddr_t)ap, 0); + ap += NBPW; + } + if (--na < 0) + break; + (void) suword((caddr_t)ap, ucp); + do { + if ((nc&BMASK) == 0) { + if (bp) + brelse(bp); + bp = bread(argdev, + (daddr_t)(dbtofsb(bno)+(nc>>BSHIFT))); + bp->b_flags |= B_AGE; /* throw away */ + bp->b_flags &= ~B_DELWRI; /* cancel io */ + cp = bp->b_un.b_addr; + } + (void) subyte((caddr_t)ucp++, (c = *cp++)); + nc++; + } while(c&0377); + } + (void) suword((caddr_t)ap, 0); + (void) suword((caddr_t)ucp, 0); + setregs(); +bad: + if (bp) + brelse(bp); + if (bno) + mfree(argmap, ctod(clrnd((int) btoc(NCARGS))), bno); + iput(ip); +} + +/* + * Read in and set up memory for executed file. + */ +getxfile(ip, nargc) +register struct inode *ip; +{ + register size_t ts, ds, ss; + int pagi = 0; + + /* + * read in first few bytes + * of file for segment + * sizes: + * ux_mag = 407/410/413 + * 407 is plain executable + * 410 is RO text + * 413 is demand paged RO text + */ + + u.u_base = (caddr_t)&u.u_exdata; + u.u_count = sizeof(u.u_exdata); + u.u_offset = 0; + u.u_segflg = 1; + readi(ip); + u.u_segflg = 0; + if(u.u_error) + goto bad; + if (u.u_count!=0) { + u.u_error = ENOEXEC; + goto bad; + } + switch (u.u_exdata.ux_mag) { + + case 0407: + u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; + u.u_exdata.ux_tsize = 0; + break; + + case 0413: + pagi = SPAGI; + /* fall into ... */ + + case 0410: + if (u.u_exdata.ux_tsize == 0) { + u.u_error = ENOEXEC; + goto bad; + } + break; + + default: + u.u_error = ENOEXEC; + goto bad; + } + if(u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) { + register struct file *fp; + + for (fp = file; fp < &file[NFILE]; fp++) + if (fp->f_inode == ip && (fp->f_flag&FWRITE)) { + u.u_error = ETXTBSY; + goto bad; + } + } + + /* + * find text and data sizes + * try them out for possible + * exceed of max sizes + */ + + ts = clrnd(btoc(u.u_exdata.ux_tsize)); + ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); + ss = clrnd(SSIZE + btoc(nargc)); + if (chksize(ts, ds, ss)) + goto bad; + u.u_cdmap = zdmap; + u.u_csmap = zdmap; + if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) + goto bad; + + /* + * At this point, committed to the new image! + * Release virtual memory resources of old process, and + * initialize the virtual memory of the new process. + * If we resulted from vfork(), instead wakeup our + * parent who will set SVFDONE when he has taken back + * our resources. + */ + u.u_prof.pr_scale = 0; + if ((u.u_procp->p_flag & SVFORK) == 0) + vrelvm(); + else { + u.u_procp->p_flag &= ~SVFORK; + u.u_procp->p_flag |= SKEEP; + wakeup((caddr_t)u.u_procp); + while ((u.u_procp->p_flag & SVFDONE) == 0) + sleep((caddr_t)u.u_procp, PZERO - 1); + u.u_procp->p_flag &= ~(SVFDONE|SKEEP); + } + u.u_procp->p_flag &= ~(SPAGI|SANOM|SUANOM|SNUSIG); + u.u_procp->p_flag |= pagi; + u.u_dmap = u.u_cdmap; + u.u_smap = u.u_csmap; + vgetvm(ts, ds, ss); + + if (pagi == 0) { + /* + * Read in data segment. + */ + u.u_base = (char *)ctob(ts); + u.u_offset = sizeof(u.u_exdata)+u.u_exdata.ux_tsize; + u.u_count = u.u_exdata.ux_dsize; + readi(ip); + } + xalloc(ip, pagi); + if (pagi && u.u_procp->p_textp) + vinifod((struct fpte *)dptopte(u.u_procp, 0), + PG_FTEXT, u.u_procp->p_textp->x_iptr, + 1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize)); + + /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ + mtpr(TBIA, 0); + + /* + * set SUID/SGID protections, if no tracing + */ + if ((u.u_procp->p_flag&STRC)==0) { + if(ip->i_mode&ISUID) + if(u.u_uid != 0) { + u.u_uid = ip->i_uid; + u.u_procp->p_uid = ip->i_uid; + } + if(ip->i_mode&ISGID) + u.u_gid = ip->i_gid; + } else + psignal(u.u_procp, SIGTRAP); + u.u_tsize = ts; + u.u_dsize = ds; + u.u_ssize = ss; +bad: + return; +} + +/* + * Clear registers on exec + */ +setregs() +{ + register int (**rp)(); + register i; + long sigmask; + + for(rp = &u.u_signal[0], sigmask = 1L; rp < &u.u_signal[NSIG]; + sigmask <<= 1, rp++) { + switch (*rp) { + + case SIG_IGN: + case SIG_DFL: + case SIG_HOLD: + continue; + + default: + /* + * Normal or deferring catch; revert to default. + */ + (void) spl6(); + *rp = SIG_DFL; + if ((int)*rp & 1) + u.u_procp->p_siga0 |= sigmask; + else + u.u_procp->p_siga1 &= ~sigmask; + if ((int)*rp & 2) + u.u_procp->p_siga1 |= sigmask; + else + u.u_procp->p_siga1 &= ~sigmask; + (void) spl0(); + continue; + } + } +/* + for(rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) + *rp++ = 0; +*/ + u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */ + for(i=0; irval & 0377) << 8); +} + +/* + * Release resources. + * Save u. area for parent to look at. + * Enter zombie state. + * Wake up parent and init processes, + * and dispose of children. + */ +exit(rv) +{ + register int i; + register struct proc *p, *q; + register struct file *f; + register int x; + +#ifdef PGINPROF + vmsizmon(); +#endif + p = u.u_procp; + p->p_flag &= ~(STRC|SULOCK); + p->p_flag |= SWEXIT; + p->p_clktim = 0; + (void) spl6(); + if ((int)SIG_IGN & 1) + p->p_siga0 = ~0; + else + p->p_siga0 = 0; + if ((int)SIG_IGN & 2) + p->p_siga1 = ~0; + else + p->p_siga1 = 0; + (void) spl0(); + p->p_cpticks = 0; + p->p_pctcpu = 0; + for(i=0; ip_flag & SVFORK) == 0) + vrelvm(); + else { + p->p_flag &= ~SVFORK; + wakeup((caddr_t)p); + while ((p->p_flag & SVFDONE) == 0) + sleep((caddr_t)p, PZERO - 1); + p->p_flag &= ~SVFDONE; + } + for(i=0; ip_stat = SZOMB; + noproc = 1; + i = PIDHASH(p->p_pid); + x = p - proc; + if (pidhash[i] == x) + pidhash[i] = p->p_idhash; + else { + for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) + if (proc[i].p_idhash == x) { + proc[i].p_idhash = p->p_idhash; + goto done; + } + panic("exit"); + } + if (p->p_pid == 1) + panic("init died"); +done: + ((struct xproc *)p)->xp_xstat = rv; /* overlay */ + ((struct xproc *)p)->xp_vm = u.u_vm; /* overlay */ + vmsadd(&((struct xproc *)p)->xp_vm, &u.u_cvm); + for(q = &proc[0]; q < &proc[NPROC]; q++) + if(q->p_pptr == p) { + q->p_pptr = &proc[1]; + q->p_ppid = 1; + wakeup((caddr_t)&proc[1]); + /* + * Traced processes are killed + * since their existence means someone is screwing up. + * Stopped processes are sent a hangup and a continue. + * This is designed to be ``safe'' for setuid + * processes since they must be willing to tolerate + * hangups anyways. + */ + if (q->p_flag&STRC) { + q->p_flag &= ~STRC; + psignal(q, SIGKILL); + } else if (q->p_stat == SSTOP) { + psignal(q, SIGHUP); + psignal(q, SIGCONT); + } + /* + * Protect this process from future + * tty signals, clear TSTP/TTIN/TTOU if pending, + * and set SDETACH bit on procs. + */ + (void) spgrp(q, -1); + } + wakeup((caddr_t)p->p_pptr); + psignal(p->p_pptr, SIGCHLD); + swtch(); +} + +wait() +{ + struct vtimes vm; + struct vtimes *vp; + + if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { + wait1(0, (struct vtimes *)0); + return; + } + vp = (struct vtimes *)u.u_ar0[R1]; + wait1(u.u_ar0[R0], &vm); + if (u.u_error) + return; + (void) copyout((caddr_t)&vm, (caddr_t)vp, sizeof (struct vtimes)); +} + +/* + * Wait system call. + * Search for a terminated (zombie) child, + * finally lay it to rest, and collect its status. + * Look also for stopped (traced) children, + * and pass back status from them. + */ +wait1(options, vp) + register options; + struct vtimes *vp; +{ + register f; + register struct proc *p; + + f = 0; +loop: + for(p = &proc[0]; p < &proc[NPROC]; p++) + if(p->p_pptr == u.u_procp) { + f++; + if(p->p_stat == SZOMB) { + u.u_r.r_val1 = p->p_pid; + u.u_r.r_val2 = ((struct xproc *)p)->xp_xstat; + ((struct xproc *)p)->xp_xstat = 0; + if (vp) + *vp = ((struct xproc *)p)->xp_vm; + vmsadd(&u.u_cvm, &((struct xproc *)p)->xp_vm); + ((struct xproc *)p)->xp_vm = zvms; + p->p_stat = NULL; + p->p_pid = 0; + p->p_ppid = 0; + p->p_pptr = 0; + p->p_sig = 0; + p->p_siga0 = 0; + p->p_siga1 = 0; + p->p_pgrp = 0; + p->p_flag = 0; + p->p_wchan = 0; + p->p_cursig = 0; + return; + } + if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && + (p->p_flag&STRC || options&WUNTRACED)) { + p->p_flag |= SWTED; + u.u_r.r_val1 = p->p_pid; + u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; + return; + } + } + if (f==0) { + u.u_error = ECHILD; + return; + } + if (options&WNOHANG) { + u.u_r.r_val1 = 0; + return; + } + if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { + u.u_eosys = RESTARTSYS; + return; + } + sleep((caddr_t)u.u_procp, PWAIT); + goto loop; +} + +/* + * fork system call. + */ +fork() +{ + + u.u_cdmap = zdmap; + u.u_csmap = zdmap; + if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { + u.u_r.r_val2 = 0; + return; + } + fork1(0); +} + +fork1(isvfork) +{ + register struct proc *p1, *p2; + register a; + + a = 0; + p2 = NULL; + for(p1 = &proc[0]; p1 < &proc[NPROC]; p1++) { + if (p1->p_stat==NULL && p2==NULL) + p2 = p1; + else { + if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) + a++; + } + } + /* + * Disallow if + * No processes at all; + * not su and too many procs owned; or + * not su and would take last slot. + */ + if (p2==NULL || (u.u_uid!=0 && (p2==&proc[NPROC-1] || a>MAXUPRC))) { + u.u_error = EAGAIN; + if (!isvfork) { + (void) vsexpand(0, &u.u_cdmap, 1); + (void) vsexpand(0, &u.u_csmap, 1); + } + goto out; + } + p1 = u.u_procp; + if(newproc(isvfork)) { + u.u_r.r_val1 = p1->p_pid; + u.u_r.r_val2 = 1; /* child */ + u.u_start = time; + u.u_acflag = AFORK; + return; + } + u.u_r.r_val1 = p2->p_pid; + +out: + u.u_r.r_val2 = 0; +} + +/* + * break system call. + * -- bad planning: "break" is a dirty word in C. + */ +sbreak() +{ + struct a { + char *nsiz; + }; + register int n, d; + + /* + * set n to new data size + * set d to new-old + */ + + n = btoc(((struct a *)u.u_ap)->nsiz); + if (!u.u_sep) + n -= ctos(u.u_tsize) * stoc(1); + if (n < 0) + n = 0; + d = clrnd(n - u.u_dsize); + if (ctob(u.u_dsize+d) > u.u_limit[LIM_DATA]) { + u.u_error = ENOMEM; + return; + } + if (chksize(u.u_tsize, u.u_dsize+d, u.u_ssize)) + return; + if (swpexpand(u.u_dsize+d, u.u_ssize, &u.u_dmap, &u.u_smap)==0) + return; + expand(d, P0BR); +} diff --git a/usr/src/sys/sys/trap.c b/usr/src/sys/sys/trap.c new file mode 100644 index 0000000000..b393671431 --- /dev/null +++ b/usr/src/sys/sys/trap.c @@ -0,0 +1,225 @@ +/* trap.c 4.2 11/9/80 */ + + +#include "../h/param.h" +#include "../h/systm.h" +#include "../h/dir.h" +#include "../h/user.h" +#include "../h/proc.h" +#include "../h/reg.h" +#include "../h/seg.h" +#include "../h/trap.h" +#include "../h/psl.h" +#include "../h/pte.h" +#include "../h/inline.h" + +#define USER 040 /* user-mode flag added to type */ + +struct sysent sysent[128]; + +/* + * Called from the trap handler when a processor trap occurs. + */ +/*ARGSUSED*/ +trap(sp, type, code, pc, psl) +unsigned code; +{ + register int *locr0 = ((int *)&psl)-PS; + register int i; + register struct proc *p; + time_t syst; + + syst = u.u_vm.vm_stime; + if (USERMODE(locr0[PS])) { + type |= USER; + u.u_ar0 = locr0; + } + switch (type) { + + default: + printf("trap type %d, code = %x\n", type, code); + panic("trap"); + + case PROTFLT + USER: /* protection fault */ + i = SIGBUS; + break; + + case PRIVINFLT + USER: /* privileged instruction fault */ + case RESADFLT + USER: /* reserved addressing fault */ + case RESOPFLT + USER: /* resereved operand fault */ + i = SIGILL; + break; + + case RESCHED + USER: /* Allow process switch */ + goto out; + + case ARITHTRAP + USER: + i = SIGFPE; + break; + + /* + * If the user SP is above the stack segment, + * grow the stack automatically. + */ + case SEGFLT + USER: /* segmentation exception */ + if(grow((unsigned)locr0[SP]) || grow(code)) + goto out; + i = SIGSEGV; + break; + + case TABLEFLT: /* allow page table faults in kernel mode */ + case TABLEFLT + USER: /* page table fault */ + panic("page table fault"); + + case PAGEFLT: /* allow page faults in kernel mode */ + case PAGEFLT + USER: /* page fault */ + i = u.u_error; + pagein(code); /* bring in page containing virtual addr */ + u.u_error = i; +/* + if (type == PAGEFLT) +*/ + return; +/* + goto out; +*/ + + case BPTFLT + USER: /* bpt instruction fault */ + case TRCTRAP + USER: /* trace trap */ + locr0[PS] &= ~PSL_T; /* turn off trace bit */ + i = SIGTRAP; + break; + + case XFCFLT + USER: /* xfc instruction fault */ + i = SIGEMT; + break; + + case COMPATFLT + USER: /* compatibility mode fault */ + u.u_cfcode = code; + i = SIGILL; + break; + } + psignal(u.u_procp, i); +out: + p = u.u_procp; + if (p->p_cursig || ISSIG(p)) + psig(); + p->p_pri = p->p_usrpri; + if (runrun) { + /* + * Since we are u.u_procp, clock will normally just change + * our priority without moving us from one queue to another + * (since the running process is not on a queue.) + * If that happened after we setrq ourselves but before we + * swtch()'ed, we might not be on the queue indicated by + * our priority. + */ + (void) spl6(); + setrq(p); + swtch(); + } + if (u.u_prof.pr_scale && (syst -= u.u_vm.vm_stime)) + addupc((caddr_t)locr0[PC], &u.u_prof, (int)-syst); + curpri = p->p_pri; +} + +/* + * Called from the trap handler when a system call occurs + */ +/*ARGSUSED*/ +syscall(sp, type, code, pc, psl) +unsigned code; +{ + register int *locr0 = ((int *)&psl)-PS; + register caddr_t params; /* known to be r10 below */ + register int i; /* known to be r9 below */ + register struct sysent *callp; + register struct proc *p; + time_t syst; + int opc; + + syst = u.u_vm.vm_stime; + if (!USERMODE(locr0[PS])) + panic("syscall"); + u.u_ar0 = locr0; + params = (caddr_t)locr0[AP] + NBPW; + u.u_error = 0; + opc = pc - 2; + if (code > 63) + opc -= 2; + callp = &sysent[code&0177]; + if (callp == sysent) { + i = fuword(params); + params += NBPW; + callp = &sysent[i&0177]; + } + if (i = callp->sy_narg * sizeof (int)) { + asm("prober $3,r9,(r10)"); /* GROT */ + asm("bnequ ok"); /* GROT */ + u.u_error = EFAULT; /* GROT */ + goto bad; /* GROT */ +asm("ok:"); /* GROT */ + asm("movc3 r9,(r10),_u+U_ARG"); /* GROT */ + } + u.u_ap = u.u_arg; + u.u_dirp = (caddr_t)u.u_arg[0]; + u.u_r.r_val1 = 0; + u.u_r.r_val2 = locr0[R1]; + if (setjmp(u.u_qsav)) { + if (u.u_error == 0 && u.u_eosys == JUSTRETURN) + u.u_error = EINTR; + } else { + u.u_eosys = JUSTRETURN; + (*(callp->sy_call))(); + } + locr0[PS] &= ~PSL_C; + if (u.u_eosys == RESTARTSYS) + pc = opc; + else if (u.u_eosys == SIMULATERTI) + dorti(); + else if (u.u_error) { +bad: + locr0[R0] = u.u_error; + locr0[PS] |= PSL_C; /* carry bit */ + } else { + locr0[R0] = u.u_r.r_val1; + locr0[R1] = u.u_r.r_val2; + } + p = u.u_procp; + if (p->p_cursig || ISSIG(p)) + psig(); + p->p_pri = p->p_usrpri; + if (runrun) { + /* + * Since we are u.u_procp, clock will normally just change + * our priority without moving us from one queue to another + * (since the running process is not on a queue.) + * If that happened after we setrq ourselves but before we + * swtch()'ed, we might not be on the queue indicated by + * our priority. + */ + (void) spl6(); + setrq(p); + swtch(); + } + if (u.u_prof.pr_scale && (syst -= u.u_vm.vm_stime)) + addupc((caddr_t)locr0[PC], &u.u_prof, (int)-syst); + curpri = p->p_pri; +} + +/* + * nonexistent system call-- set fatal error code. + */ +nosys() +{ + + u.u_error = 100; +} + +/* + * Ignored system call + */ +nullsys() +{ + +} -- 2.20.1