all the .ed files updated, makea still needs more work - vx32 - Local 9vx git repository for patches.
       
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
 (DIR) commit 0e345fe6a6994b2df8dd744e9b0e68ce9026a293
 (DIR) parent a3985efe6946ed22480d95497c21a5fce3d8c678
 (HTM) Author: yiyus <yiyu.jgl@gmail.com>
       Date:   Wed, 21 Jul 2010 21:20:48 +0200
       
       all the .ed files updated, makea still needs more work
       
       Diffstat:
         src/9vx/a/segment.c                 |       3 +--
         src/9vx/a/segment.ed                |       3 ++-
         src/9vx/a/swap.c                    |       7 +++----
         src/9vx/a/swap.ed                   |       3 +++
         src/9vx/a/sysfile.c                 |       5 +++--
         src/9vx/a/sysfile.ed                |     176 ++++++++++++++++++++++++++++++-
         src/9vx/a/sysproc.c                 |       7 ++++---
         src/9vx/a/sysproc.ed                |     424 ++++++++++++++++++++++++++++++-
         src/9vx/a/systab.ed                 |       1 +
       
       9 files changed, 612 insertions(+), 17 deletions(-)
       ---
 (DIR) diff --git a/src/9vx/a/segment.c b/src/9vx/a/segment.c
       @@ -483,8 +483,6 @@ ibrk(ulong addr, int seg)
                        if(ns == 0 || ns == s)
                                continue;
                        if(newtop >= ns->base && newtop < ns->top) {
       -print("grow segment %d -> %p would overlap %d [%p-%p]\n",
       -        seg, newtop, i, ns->base, ns->top);
                                qunlock(&s->lk);
                                error(Esoverlap);
                        }
       @@ -648,6 +646,7 @@ segattach(Proc *p, ulong attr, char *name, ulong va, ulong len)
                        error(Ebadarg);
        
                vmemchr(name, 0, ~0);
       +
                for(sno = 0; sno < NSEG; sno++)
                        if(p->seg[sno] == nil && sno != ESEG)
                                break;
 (DIR) diff --git a/src/9vx/a/segment.ed b/src/9vx/a/segment.ed
       @@ -1,4 +1,3 @@
       -/^addphysseg/-1,/^        return/+1d
        ,s!Lock;!Lock lk;!
        ,s!lock(s)!lock(\&s->ref.lk)!g
        ,s!lock(i)!lock(\&i->ref.lk)!g
       @@ -24,3 +23,5 @@
        /^}/i
        #endif
        .
       +/validaddr/d
       +/^syssegflush/s/ulong/uint32/
 (DIR) diff --git a/src/9vx/a/swap.c b/src/9vx/a/swap.c
       @@ -67,7 +67,7 @@ putswap(Page *p)
                                swapalloc.last = idx;
                }
                if(*idx >= 254)
       -                panic("putswap %lux == %ud", p, *idx);
       +                panic("putswap %#p == %ud", p, *idx);
                unlock(&swapalloc.lk);
        }
        
       @@ -107,7 +107,7 @@ pager(void *junk)
                Proc *p, *ep;
        
                if(waserror())
       -                panic("pager: os error\n");
       +                panic("pager: os error");
        
                p = proctab(0);
                ep = &p[conf.nproc];
       @@ -115,7 +115,6 @@ pager(void *junk)
        loop:
                up->psstate = "Idle";
                sleep(&swapalloc.r, needpages, 0);
       -print("uh oh.  someone woke the pager\n");
        
                while(needpages(junk)) {
        
       @@ -335,7 +334,7 @@ executeio(void)
        
                for(i = 0; i < ioptr; i++) {
                        if(ioptr > conf.nswppo)
       -                        panic("executeio: ioptr %d > %d\n", ioptr, conf.nswppo);
       +                        panic("executeio: ioptr %d > %d", ioptr, conf.nswppo);
                        out = iolist[i];
                        k = kmap(out);
                        kaddr = (char*)VA(k);
 (DIR) diff --git a/src/9vx/a/swap.ed b/src/9vx/a/swap.ed
       @@ -7,3 +7,6 @@
        ,s;lock(out);lock(\&out->lk);g
        ,s;lock(outp);lock(\&outp->lk);g
        g/swopen/d
       +/if(!cpuserver)/;/else/c
       +                        if(!cpuserver || freebroken() == 0)
       +.
 (DIR) diff --git a/src/9vx/a/sysfile.c b/src/9vx/a/sysfile.c
       @@ -175,7 +175,7 @@ sysfd2path(uint32 *arg)
        {
                Chan *c;
                char *buf;
       -        
       +
                buf = uvalidaddr(arg[1], arg[2], 1);
        
                c = fdtochan(arg[0], -1, 0, 1);
       @@ -848,7 +848,7 @@ sseek(vlong *ret, uint32 *arg)
                default:
                        error(Ebadarg);
                }
       -        *ret = off;        /* caller translated arg[0] already */
       +        *ret = off;
                c->uri = 0;
                c->dri = 0;
                cclose(c);
       @@ -983,6 +983,7 @@ syschdir(uint32 *arg)
                return 0;
        }
        
       +        // Plan 9 VX added isk parameter.
        long
        bindmount(int ismount, int fd, int afd, char* arg0, char* arg1, ulong flag, char* spec)
        {
 (DIR) diff --git a/src/9vx/a/sysfile.ed b/src/9vx/a/sysfile.ed
       @@ -21,17 +21,189 @@
        g/^sys_/ s/ulong \*)/ulong *u)/
        /^bindmount/,/^sysbind/ s/validaddr/if(!isk) validaddr/
        /^bindmount/,/^sysbind/ s/spec = validnamedup/if(isk) kstrdup(\&spec, spec); else &/
       +g/^[a-z]/ s/ulong/uint32/g
       +/^openmode/ s/uint32/ulong/
       +/^sysfd2path/ s/^//
       +/validaddr/-1;+1c
       +        char *buf;
       +
       +        buf = uvalidaddr(arg[1], arg[2], 1);
       +.
       +/snprint/ s/(char\*)arg\[1\]/buf/
       +/^syspipe/ s/^//
       +/validaddr/-1;+1c
       +        int *ufd;
       +        
       +        ufd = uvalidaddr(arg[0], 2*BY2WD, 1);
       +.
       +/((long\*)arg\[0\])/ s/((long\*)arg\[0\])/ufd/
       +/((long\*)arg\[0\])/ s/((long\*)arg\[0\])/ufd/
       +/^sysopen/ s/^//
       +/^$/i
       +        char *name;
       +.
       +/openmode/a
       +        name = uvalidaddr(arg[0], 1, 0);
       +        c = namec(name, Aopen, arg[1], 0);
       +.
       +/if(c)/d
       +s/        //
       +/validaddr/;/c = namec/d
       +/^doread/ s/^//
       +/^{/a
       +        int dir;
       +.
       +/validaddr/;/p =/c
       +        p = uvalidaddr(arg[1], n, 1);
       +.
       +/QTDIR/;/c->umh/c
       +        dir = c->qid.type&QTDIR;
       +        if(dir && mountrockread(c, p, n, &nn)){
       +                /* do nothing: mountrockread filled buffer */
       +        }else{
       +                if(dir && c->umh)
       +.
       +/else{/;/}/c
       +                else
       +                        nn = devtab[c->type]->read(c, p, n, off);
       +        }
       +        if(dir)
       +.
       +/}else/;/nnn/c
       +        else
       +                nnn = nn;
       +.
       +/^dowrite/ s/^//
       +/^$/i
       +        uchar *p;
       +.
       +/validaddr/ s/v/p = uv/
       +/m = devtab/ s/(void\*)arg\[1\]/p/
       +/^sseek/s/(/(vlong *ret, /
       +/u\[2\]/ s/ulong/uint32/
       +/arg\[0\] = off/ s/\*(vlong\*)arg\[0\]/*ret/
       +/^sysseek/s/^//
       +/validaddr/;/sseek/c
       +        sseek(uvalidaddr(arg[0], BY2V, 1), arg);
       +.
       +/^sysoseek/s/^//
       +/^{/;/^$/s/ulong/uint32/g
       +/a\[0\]/ s/=.*/= 0;/
       +/sseek/ s/(.*)/(\&o.v, a)/
       +/^sysfstat/ s/^//
       +/^$/i
       +        uchar *p;
       +.
       +/validaddr/ s/v/p = uv/
       +/l = devtab/ s/(.*)/(c, p, l)/
       +/^sysstat/ s/^//
       +/^$/i
       +        uchar *p;
       +.
       +/validaddr/ s/v/p = uv/
       +/validaddr/ s/v/name = uv/
       +/c = namec/ s/(char\*)arg\[0\]/name/
       +/l = devtab/ s/(.*)/(c, p, l)/
       +/l = dirsetname/ s/(uchar\*)arg\[1\]/p/
       +/^syschdir/ s/^//
       +/^$/i
       +        char *name;
       +.
       +/validaddr/ s/v/name = uv/
       +/c = namec/ s/(char\*)arg\[0\]/name/
       +/^bindmount/ s/int isk, //
       +s/uint32/ulong/
       +/isk/d
       +/isk/s/if.*else //
       +/isk/d
       +/isk/d
       +/^sysbind/ s/^//
       +/return/ s/0, //
       +s/(char\*)arg\[0\]/uvalidaddr(arg[0], 1, 0)/
       +s/(char\*)arg\[1\]/uvalidaddr(arg[1], 1, 0)/
       +/^sysmount/ s/^//
       +/return/ s/0, //
       +s/(char\*)arg\[2\]/uvalidaddr(arg[2], 1, 0)/
       +s/(char\*)arg\[4\]/uvalidaddr(arg[4], 1, 0)/
       +/^sys_mount/ s/^//
       +/return/ s/0, //
       +s/(char\*)arg\[1\]/uvalidaddr(arg[1], 1, 0)/
       +s/(char\*)arg\[3\]/uvalidaddr(arg[3], 1, 0)/
       +/^sysunmount/ s/^//
       +/^$/i
       +        char *mount, *mounted;
       +.
       +/validaddr/;/cmount/c
       +        mount = uvalidaddr(arg[1], 1, 0);
       +        cmount = namec(mount, Amount, 0, 0);
       +.
       +/validaddr/ s/v/mounted = uv/
       +/cmounted/ s/(char\*)arg\[0\]/mounted/
       +/^syscreate/ s/^//
       +/^$/i
       +        char *name;
       +.
       +/validaddr/;/c = namec/c
       +        name = uvalidaddr(arg[0], 1, 0);
       +        c = namec(name, Acreate, arg[1], arg[2]);
       +.
       +/^sysremove/ s/^//
       +/^$/i
       +        char *name;
       +.
       +/validaddr/;/c = namec/c
       +        name = uvalidaddr(arg[0], 1, 0);
       +        c = namec(name, Aremove, 0, 0);
       +.
       +/^syswstat/ s/^//
       +/^$/i
       +        char *name;
       +        uchar *p;
       +.
       +/validaddr/;/return/c
       +        p = uvalidaddr(arg[1], l, 0);
       +        validstat(p, l);
       +        name = uvalidaddr(arg[0], 1, 0);
       +        c = namec(name, Aaccess, 0, 0);
       +        return wstat(c, p, l);
       +.
       +/^sysfwstat/ s/^//
       +/^$/i
       +        uchar *p;
       +.
       +/validaddr/ s/v/p = uv/
       +/validstat/ s/(uchar\*)arg\[1\]/p/
       +/return/ s/(uchar\*)arg\[1\]/p/
       +/^sys_stat/ s/^//
       +/name/ s/;/, *elem;/
       +/^$/i
       +        uchar *p;
       +.
       +/validaddr/;/namec/c
       +        p = uvalidaddr(arg[1], 116, 1);
       +        name = uvalidaddr(arg[0], 1, 0);
       +        c = namec(name, Aaccess, 0, 0);
       +.
       +/name =/;/l =/ s/name/elem/g
       +/dirsetelem/ s/elem/name/
       +/packoldstat/ s/(uchar\*)arg\[1\]/p/
       +/^sys_fstat/ s/^//
       +/^$/i
       +        uchar *p;
       +.
       +/validaddr/ s/v/p = uv/
       +/packoldstat/ s/(uchar\*)arg\[1\]/p/
        $a
        
        // Plan 9 VX additions
        long
        kbind(char *new, char *old, int flag)
        {
       -        return bindmount(1, 0, -1, -1, new, old, flag, nil);
       +        return bindmount(0, -1, -1, new, old, flag, nil);
        }
        
        long
       -syspassfd(ulong *u)
       +syspassfd(uint32 *u)
        {
                error("passfd unimplemented");
                return -1;
 (DIR) diff --git a/src/9vx/a/sysproc.c b/src/9vx/a/sysproc.c
       @@ -7,7 +7,7 @@
        #include        "fns.h"
        #include        "error.h"
        
       -#include "a.out.h"
       +#include        "a.out.h"
        
        int        shargs(char*, int, char**);
        
       @@ -644,6 +644,7 @@ sysexits(uint32 *arg)
                                }
                                poperror();
                        }
       +
                }else
                        status = nil;
                pexit(status, 1);
       @@ -1113,7 +1114,7 @@ syssemacquire(uint32 *arg)
                evenaddr(arg[0]);
                block = arg[1];
                
       -        if((s = seg(up, arg[0], 0)) == nil)        /* this can't happen if validaddr succeeded, can it? */
       +        if((s = seg(up, arg[0], 0)) == nil)
                        error(Ebadarg);
                if(*addr < 0)
                        error(Ebadarg);
       @@ -1130,7 +1131,7 @@ syssemrelease(uint32 *arg)
                evenaddr(arg[0]);
                delta = arg[1];
        
       -        if((s = seg(up, arg[0], 0)) == nil)        /* again, this can't happen! */
       +        if((s = seg(up, arg[0], 0)) == nil)
                        error(Ebadarg);
                if(delta < 0 || *addr < 0)
                        error(Ebadarg);
 (DIR) diff --git a/src/9vx/a/sysproc.ed b/src/9vx/a/sysproc.ed
       @@ -1,15 +1,16 @@
       +1i
       +#define        WANT_M
       +.
        g/"edf.h"/d
        ,s/->ref =/->ref.ref =/g
        ,s/ref(p->dot)/ref(\&p->dot->ref)/g
        ,s/ref(p->fgrp)/ref(\&p->fgrp->ref)/g
        ,s/ref(p->pgrp)/ref(\&p->pgrp->ref)/g
       -,s/ref(p->rgrp)/ref(\&p->rgrp->ref)/g
        ,s/ref(p->egrp)/ref(\&p->egrp->ref)/g
        ,s/lock(img)/lock(\&img->ref.lk)/g
        ,s/ref(img)/ref(\&img->ref)/g
        ,s/return0(void\*)/return0(void *v)/g
        ,s/(s = up->seg\[i\])/(&)/g
       -/edf.*Admitted/,/else/d
        ,s;MACHP(0)->ticks;msec();g
        /ESEG.*= newseg/a
                flushmmu();        // Needed for Plan 9 VX
       @@ -19,10 +20,427 @@ g/"edf.h"/d
        ,s;wakeup(p);wakeup(\&p->rendez);g
        ,s;lock(up->rgrp);lock(\&up->rgrp->ref.lk);g
        ,s;ref(up->rgrp);ref(\&up->rgrp->ref);g
       -/sysr1/ s/(ulong\*)/(ulong *x)/
       +/sysr1/ s/(ulong\*)/(uint32 *x)/
        /Admitted/,/        yield/c
                        yield();
        .
        /^        checkpagerefs/ c
                vx32sysr1();
        .
       +/^sysrfork/ s/ulong/uint32/
       +/^l2be/ s/long/uint32/
       +-1 s/ulong/uint32/
       +/^sysexec/ s/ulong/uint32/
       +-1i
       +static char Echanged[] = "exec arguments changed underfoot";
       +
       +.
       +/^{/+1;/^}/-1 c
       +        char *volatile elem, *volatile file, *ufile;
       +        Chan *volatile tc;
       +
       +        /*
       +         * Open the file, remembering the final element and the full name.
       +         */
       +        file = nil;
       +        elem = nil;
       +        tc = nil;
       +        if(waserror()){
       +                if(file)
       +                        free(file);
       +                if(elem)
       +                        free(elem);
       +                if(tc)
       +                        cclose(tc);
       +                nexterror();
       +        }
       +
       +        ufile = uvalidaddr(arg[0], 1, 0);
       +        file = validnamedup(ufile, 1);
       +        tc = namec(file, Aopen, OEXEC, 0);
       +        kstrdup((char**)&elem, up->genbuf);
       +
       +        /*
       +         * Read the header.  If it's a #!, fill in progarg[] with info and repeat.
       +         */
       +        int i, n, nprogarg;
       +        char *progarg[sizeof(Exec)/2+1];
       +        char *prog, *p;
       +        char line[sizeof(Exec)+1];
       +        Exec exec;
       +
       +        nprogarg = 0;
       +        n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);
       +        if(n < 2)
       +                error(Ebadexec);
       +        p = (char*)&exec;
       +        if(p[0] == '#' && p[1] == '!'){
       +                memmove(line, p, n);
       +                nprogarg = shargs(line, n, progarg);
       +                if(nprogarg == 0)
       +                        error(Ebadexec);
       +                
       +                /* The original file becomes an extra arg after #! line */
       +                progarg[nprogarg++] = file;
       +                
       +                /*
       +                 * Take the #! $0 as a file to open, and replace
       +                 * $0 with the original path's name.
       +                 */
       +                prog = progarg[0];
       +                progarg[0] = elem;
       +                cclose(tc);
       +                tc = nil;        /* in case namec errors out */
       +                tc = namec(prog, Aopen, OEXEC, 0);
       +                n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);
       +                if(n < 2)
       +                        error(Ebadexec);
       +        }
       +
       +        /* 
       +         * #! has had its chance, now we need a real binary
       +         */
       +        uint32 magic, entry, text, etext, data, edata, bss, ebss;
       +
       +        magic = l2be(exec.magic);
       +        if(n != sizeof(Exec) || l2be(exec.magic) != AOUT_MAGIC)
       +                error(Ebadexec);
       +
       +        entry = l2be(exec.entry);
       +        text = l2be(exec.text);
       +        data = l2be(exec.data);
       +        bss = l2be(exec.bss);
       +        etext = ROUND(UTZERO+sizeof(Exec)+text, BY2PG);
       +        edata = ROUND(etext + data, BY2PG);
       +        ebss = ROUND(etext + data + bss, BY2PG);
       +        
       +//iprint("entry %#lux text %#lux data %#lux bss %#lux\n", entry, text, data, bss);
       +//iprint("etext %#lux edata %#lux ebss %#lux\n", etext, edata, ebss);
       +
       +        if(entry < UTZERO+sizeof(Exec) || entry >= UTZERO+sizeof(Exec)+text)
       +                error(Ebadexec);
       +        
       +        /* many overflow possibilities */
       +        if(text >= USTKTOP || data >= USTKTOP || bss >= USTKTOP
       +        || etext >= USTKTOP || edata >= USTKTOP || ebss >= USTKTOP
       +        || etext >= USTKTOP || edata < etext || ebss < edata)
       +                error(Ebadexec);
       +
       +        /*
       +         * Copy argv into new stack segment temporarily mapped elsewhere.
       +         * Be careful: multithreaded program could be changing argv during this.
       +         * Pass 1: count number of arguments, string bytes.
       +         */
       +        int nargv, strbytes;
       +        uint32 argp, ssize, spage;
       +
       +        strbytes = 0;
       +        for(i=0; i<nprogarg; i++)
       +                strbytes += strlen(progarg[i]) + 1;
       +
       +        argp = arg[1];
       +        for(nargv=0;; nargv++, argp += BY2WD){
       +                uint32 a;
       +                char *str;
       +
       +                a = *(uint32*)uvalidaddr(argp, BY2WD, 0);
       +                if(a == 0)
       +                        break;
       +                str = uvalidaddr(a, 1, 0);
       +                n = ((char*)vmemchr(str, 0, 0x7FFFFFFF) - str) + 1;
       +                if(nprogarg > 0 && nargv == 0)
       +                        continue;        /* going to skip argv[0] on #! */
       +                strbytes += n;
       +        }
       +        if(nargv == 0)
       +                error("exec missing argv");
       +
       +        /* 
       +         * Skip over argv[0] if using #!.  Waited until now so that
       +         * string would still be checked for validity during loop.
       +         */
       +        if(nprogarg > 0){
       +                nargv--;
       +                arg[1] += BY2WD;
       +        }
       +
       +        ssize = BY2WD*((nprogarg+nargv)+1) + ROUND(strbytes, BY2WD) + sizeof(Tos);
       +
       +        /*
       +         * 8-byte align SP for those (e.g. sparc) that need it.
       +         * execregs() will subtract another 4 bytes for argc.
       +         */
       +        if((ssize+4) & 7)
       +                ssize += 4;
       +        spage = (ssize+(BY2PG-1)) >> PGSHIFT;
       +
       +        /*
       +         * Pass 2: build the stack segment, being careful not to assume
       +         * that the counts from pass 1 are still valid.
       +         */
       +        if(spage > TSTKSIZ)
       +                error(Enovmem);
       +
       +        qlock(&up->seglock);
       +        if(waserror()){
       +                if(up->seg[ESEG]){
       +                        putseg(up->seg[ESEG]);
       +                        up->seg[ESEG] = nil;
       +                }
       +                qunlock(&up->seglock);
       +                nexterror();
       +        }
       +        up->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG);
       +        flushmmu();        // Needed for Plan 9 VX  XXX really?
       +
       +        /*
       +         * Top-of-stack structure.
       +         */
       +        uchar *uzero;
       +        uzero = up->pmmu.uzero;
       +        Tos *tos;
       +        uint32 utos;
       +        utos = USTKTOP - sizeof(Tos);
       +        tos = (Tos*)(uzero + utos + TSTKTOP - USTKTOP);
       +        tos->cyclefreq = m->cyclefreq;
       +        cycles((uvlong*)&tos->pcycles);
       +        tos->pcycles = -tos->pcycles;
       +        tos->kcycles = tos->pcycles;
       +        tos->clock = 0;
       +
       +        /*
       +         * Argument pointers and strings, together.
       +         */
       +        char *bp, *ep;
       +        uint32 *targp;
       +        uint32 ustrp, uargp;
       +
       +        ustrp = utos - ROUND(strbytes, BY2WD);
       +        uargp = ustrp - BY2WD*((nprogarg+nargv)+1);
       +        bp = (char*)(uzero + ustrp + TSTKTOP - USTKTOP);
       +        ep = bp + strbytes;
       +        p = bp;
       +        targp = (uint32*)(uzero + uargp + TSTKTOP - USTKTOP);
       +        
       +        /* #! args are trusted */
       +        for(i=0; i<nprogarg; i++){
       +                n = strlen(progarg[i]) + 1;
       +                if(n  > ep - p)
       +                        error(Echanged);
       +                memmove(p, progarg[i], n);
       +                p += n;
       +                *targp++ = ustrp;
       +                ustrp += n;
       +        }
       +        
       +        /* the rest are not */
       +        argp = arg[1];
       +        for(i=0; i<nargv; i++){
       +                uint32 a;
       +                char *str;
       +                
       +                a = *(uint32*)uvalidaddr(argp, BY2WD, 0);
       +                argp += BY2WD;
       +                
       +                str = uvalidaddr(a, 1, 0);
       +                n = ((char*)vmemchr(str, 0, 0x7FFFFFFF) - str) + 1;
       +                if(n  > ep - p)
       +                        error(Echanged);
       +                memmove(p, str, n);
       +                p += n;
       +                *targp++ = ustrp;
       +                ustrp += n;
       +        }
       +
       +        if(*(uint32*)uvalidaddr(argp, BY2WD, 0) != 0)
       +                error(Echanged);        
       +        *targp = 0;
       +
       +        /*
       +         * But wait, there's more: prepare an arg copy for up->args
       +         * using the copy we just made in the temporary segment.
       +         */
       +        char *args;
       +        int nargs;
       +
       +        n = p - bp;        /* includes NUL on last arg, so must be > 0 */
       +        if(n <= 0)        /* nprogarg+nargv > 0; checked above */
       +                error(Egreg);
       +        if(n > 128)
       +                n = 128;
       +        args = smalloc(n);
       +        if(waserror()){
       +                free(args);
       +                nexterror();
       +        }
       +        memmove(args, bp, n);
       +        /* find beginning of UTF character boundary to place final NUL */
       +        while(n > 0 && (args[n-1]&0xC0) == 0x80)
       +                n--;
       +        args[n-1] = '\0';
       +        nargs = n;
       +
       +        /*
       +         * Now we're ready to commit.
       +         */
       +        free(up->text);
       +        up->text = elem;
       +        free(up->args);
       +        up->args = args;
       +        up->nargs = n;
       +        elem = nil;
       +        poperror();        /* args */
       +
       +        /*
       +         * Free old memory.  Special segments maintained across exec.
       +         */
       +        Segment *s;
       +        for(i = SSEG; i <= BSEG; i++) {
       +                putseg(up->seg[i]);
       +                up->seg[i] = nil;        /* in case of error */
       +        }
       +        for(i = BSEG+1; i< NSEG; i++) {
       +                s = up->seg[i];
       +                if(s && (s->type&SG_CEXEC)) {
       +                        putseg(s);
       +                        up->seg[i] = nil;
       +                }
       +        }
       +        
       +        /*
       +         * Close on exec
       +         */
       +        Fgrp *f;
       +        f = up->fgrp;
       +        for(i=0; i<=f->maxfd; i++)
       +                fdclose(i, CCEXEC);
       +
       +        /* Text.  Shared. Attaches to cache image if possible */
       +        /* attachimage returns a locked cache image */
       +        Image *img;
       +        Segment *ts;
       +        img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (etext-UTZERO)>>PGSHIFT);
       +        ts = img->s;
       +        up->seg[TSEG] = ts;
       +        ts->flushme = 1;
       +        ts->fstart = 0;
       +        ts->flen = sizeof(Exec)+text;
       +        unlock(&img->ref.lk);
       +
       +        /* Data. Shared. */
       +        s = newseg(SG_DATA, etext, (edata-etext)>>PGSHIFT);
       +        up->seg[DSEG] = s;
       +
       +        /* Attached by hand */
       +        incref(&img->ref);
       +        s->image = img;
       +        s->fstart = ts->fstart+ts->flen;
       +        s->flen = data;
       +
       +        /* BSS. Zero fill on demand */
       +        up->seg[BSEG] = newseg(SG_BSS, edata, (ebss-edata)>>PGSHIFT);
       +
       +        /*
       +         * Move the stack
       +         */
       +        s = up->seg[ESEG];
       +        up->seg[ESEG] = 0;
       +        up->seg[SSEG] = s;
       +        qunlock(&up->seglock);
       +        poperror();        /* seglock */
       +
       +        s->base = USTKTOP-USTKSIZE;
       +        s->top = USTKTOP;
       +        relocateseg(s, USTKTOP-TSTKTOP);
       +
       +        /*
       +         *  '/' processes are higher priority (hack to make /ip more responsive).
       +         */
       +        if(devtab[tc->type]->dc == L'/')
       +                up->basepri = PriRoot;
       +        up->priority = up->basepri;
       +        poperror();        /* tc, elem, file */
       +        cclose(tc);
       +        free(file);
       +        // elem is now up->text
       +
       +        /*
       +         *  At this point, the mmu contains info about the old address
       +         *  space and needs to be flushed
       +         */
       +        flushmmu();
       +        qlock(&up->debug);
       +        up->nnote = 0;
       +        up->notify = 0;
       +        up->notified = 0;
       +        up->privatemem = 0;
       +        procsetup(up);
       +        qunlock(&up->debug);
       +        if(up->hang)
       +                up->procctl = Proc_stopme;
       +
       +        return execregs(entry, USTKTOP - uargp, nprogarg+nargv);
       +.
       +/^syssleep/s/ulong/uint32/
       +/^sysalarm/s/ulong/uint32/
       +/^sysexits/s/ulong/uint32/
       +/status/;/if(status)/ c
       +        char *status;
       +        char *inval = "invalid exit string";
       +        char buf[ERRMAX];
       +
       +        if(arg[0]){
       +.
       +/validaddr/c
       +                        status = uvalidaddr(arg[0], 1, 0);
       +.
       +/^        }/ c
       +        }else
       +                status = nil;
       +.
       +/^sys_wait/s/ulong/uint32/
       +/validaddr(arg\[0\], sizeof(OWaitmsg), 1)/ c
       +        ow = uvalidaddr(arg[0], sizeof(OWaitmsg), 1);
       +.
       +/ow =/d
       +/^sysawait/s/ulong/uint32/
       +/ulong n/ s/ulong/uint32/
       +a
       +        char *buf;
       +.
       +/validaddr/ s/v/buf = uv/
       +/i = / s/(char\*)arg\[0\]/buf/
       +/^generrstr/ s/char \*buf/uint32 addr/
       +/^$/i
       +        char *buf;
       +.
       +/validaddr/ s/v/buf = uv/
       +s/(ulong)buf/addr/
       +/^syserrstr/s/ulong/uint32/
       +/return/s/(char\*)//
       +/^sys_errstr/s/ulong/uint32/
       +/return/s/(char\*)//
       +/^sysnotify/s/ulong/uint32/
       +/validaddr/;/up->notify/c
       +                uvalidaddr(arg[0], 1, 0);
       +        up->notify = arg[0];        /* checked again when used */
       +.
       +/^sysnoted/s/ulong/uint32/
       +/^syssegbrk/s/ulong/uint32/
       +/addr/s/ulong/uint32/
       +/^syssegattach/s/ulong/uint32/
       +/return/s/(char\*)arg\[1\]/uvalidaddr(arg[1], 1, 0)/
       +/^syssegdetach/s/ulong/uint32/
       +/addr/s/ulong/uint32/
       +/^syssegfree/s/ulong/uint32/
       +/from/s/ulong/uint32/
       +/^sysbrk_/s/ulong/uint32/
       +/^sysrendezvous/s/ulong/uint32/
       +/^syssemacquire/s/ulong/uint32/
       +/validaddr/ s/v/addr = uv/
       +/addr =/d
       +/(ulong)addr/s/(ulong)addr/arg[0]/
       +/^syssemrelease/s/ulong/uint32/
       +/validaddr/ s/v/addr = uv/
       +/addr =/d
       +/(ulong)addr/s/(ulong)addr/arg[0]/
 (DIR) diff --git a/src/9vx/a/systab.ed b/src/9vx/a/systab.ed
       @@ -1 +1,2 @@
        ,s!"/sys/src/libc/9syscall/!"!
       +/Syscall/s/ulong/uint32/