From 08116a10138b5d2a92c0cc468b988f07e29ed81d Mon Sep 17 00:00:00 2001 From: aiju Date: Sat, 18 Jun 2011 21:50:36 +0000 Subject: [PATCH 01/11] update ls manpage --- sys/man/1/ls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/man/1/ls b/sys/man/1/ls index e2f0bcc92..eff94d44b 100644 --- a/sys/man/1/ls +++ b/sys/man/1/ls @@ -10,7 +10,7 @@ ls, lc \- list contents of directory .PP .B lc [ -.B -dlmnqrstuFQT +.B -dlmnqrstuQT ] .I name ... .SH DESCRIPTION From bbfc504d45d81a41212aa4bbd0b2abff15168468 Mon Sep 17 00:00:00 2001 From: ment Date: Wed, 22 Jun 2011 00:30:09 +0200 Subject: [PATCH 02/11] boot/pbs: wrong register --- sys/src/boot/pc/pbs.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/boot/pc/pbs.s b/sys/src/boot/pc/pbs.s index 8a11b8279..5f9dcfabb 100644 --- a/sys/src/boot/pc/pbs.s +++ b/sys/src/boot/pc/pbs.s @@ -107,7 +107,7 @@ TEXT start16(SB), $0 CLR(rCX) LB(_nfats(SB), rCL) MUL(rCX) - OR(rCX, rCX) + OR(rAX, rAX) JNE _fatszok /* zero? it's FAT32 */ LW(_fatsz32hi(SB), rBX) From a3e9415aa8cdba6059c972c582e3645c4c112139 Mon Sep 17 00:00:00 2001 From: stanley lieber Date: Wed, 22 Jun 2011 10:03:37 -0500 Subject: [PATCH 03/11] fortunes: necessary additions --- sys/games/lib/fortunes | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sys/games/lib/fortunes b/sys/games/lib/fortunes index 37532fef3..717ef979f 100644 --- a/sys/games/lib/fortunes +++ b/sys/games/lib/fortunes @@ -4461,3 +4461,14 @@ Once, Doug McIlroy got mad at his terminal and smacked the keyboard. The result Alan Turing always wanted to win a McIlroy Award, but didn't qualify. No one has. In 1984, the Department of Justice broke up AT&T because they had a monopoly. On Doug McIlroy. god i'm dead +Starve before doing business with the damned Navy. -- Ben Rich +Saw comment // NEW BOOST CODE, and had a moment of panic before realizing it was vehicle boost, not C++ boost -- John Carmack +While attempting its first overseas deployment to the Kadena Air Base in Okinawa, Japan, on 11 February 2007, a group of six Raptors flying from Hickam AFB, Hawaii experienced multiple computer crashes coincident with their crossing of the 180th meridian of longitude (the International Date Line). +also, plan9front claims to include a working go compiler. what did they do? -- Russ Cox + plan 9 has a thriving and friendly community +on the internet, no one knows you're ken thompson -- sl +VEGETARYAN -- Seen on a Hipster Hitler t-shirt. +os.Open opens the in-kernel databases, called files -- Aiju on Go's stdlib lack of database access libraries. + i like how 2011 cell phones emulate 1970 modems + glenda is 19 years old, she wants to go out and have some fun, not to be locked in attic and get molested by her uncle + is he building the GNU ark? two of each feature .. From 81d393942d8834b6e071ab0957b655a99e737486 Mon Sep 17 00:00:00 2001 From: aiju Date: Fri, 24 Jun 2011 15:10:22 +0200 Subject: [PATCH 04/11] updated 5e --- sys/src/cmd/5e/5e.c | 30 ++- sys/src/cmd/5e/arm.c | 32 ++-- sys/src/cmd/5e/dat.h | 19 +- sys/src/cmd/5e/fns.h | 12 +- sys/src/cmd/5e/fs.c | 437 ++++++++++++++++++++++++++++++++++++++++++ sys/src/cmd/5e/mkfile | 2 +- sys/src/cmd/5e/proc.c | 125 +++++++++--- sys/src/cmd/5e/seg.c | 28 +-- sys/src/cmd/5e/sys.c | 54 +++--- 9 files changed, 645 insertions(+), 94 deletions(-) create mode 100644 sys/src/cmd/5e/fs.c diff --git a/sys/src/cmd/5e/5e.c b/sys/src/cmd/5e/5e.c index 3aac578d1..b2f23674c 100644 --- a/sys/src/cmd/5e/5e.c +++ b/sys/src/cmd/5e/5e.c @@ -4,9 +4,8 @@ #include "dat.h" #include "fns.h" -Process **PP; - -static int nflag; +int nflag, pflag, bflag; +Ref nproc; void dump(void) @@ -37,23 +36,44 @@ cleanup(void) if(P == nil) return; + remproc(P); + decref(&nproc); freesegs(); fddecref(P->fd); + if(P->path != nil && decref(P->path) == 0) + free(P->path); free(P); } static void usage(void) { - fprint(2, "usage: 5e [ -n ] text [ args ]\n"); + fprint(2, "usage: 5e [-npb] text [...]\n"); exits(nil); } +void +suicide(char *fmt, ...) +{ + va_list va; + char buf[1024]; + + va_start(va, fmt); + vsnprint(buf, sizeof(buf), fmt, va); + va_end(va); + fprint(2, "%s\n", buf); + if(!bflag) + exits(buf); + abort(); +} + void main(int argc, char **argv) { ARGBEGIN { case 'n': nflag++; break; + case 'p': pflag++; break; + case 'b': bflag++; break; default: usage(); } ARGEND; if(argc < 1) @@ -65,6 +85,8 @@ main(int argc, char **argv) atexit(cleanup); if(nflag) adjustns(); + if(pflag) + initfs("armproc", "/proc"); initproc(); if(loadtext(argv[0], argc, argv) < 0) sysfatal("%r"); diff --git a/sys/src/cmd/5e/arm.c b/sys/src/cmd/5e/arm.c index fcaab3fb4..507c46361 100644 --- a/sys/src/cmd/5e/arm.c +++ b/sys/src/cmd/5e/arm.c @@ -22,7 +22,7 @@ enum { static void invalid(u32int instr) { - sysfatal("undefined instruction %8ux @ %8ux", instr, P->R[15] - 4); + suicide("undefined instruction %8ux @ %8ux", instr, P->R[15] - 4); } static u32int @@ -81,7 +81,7 @@ single(u32int instr) addr = *Rn; if(instr & fP) addr += offset; - targ = vaddr(addr, &seg); + targ = vaddr(addr, 4, &seg); switch(instr & (fB | fL)) { case 0: *(u32int*) targ = *Rd; @@ -120,7 +120,7 @@ swap(u32int instr) Rn = P->R + ((instr >> 16) & 15); if(Rm == P->R + 15 || Rd == P->R + 15 || Rn == P->R + 15) invalid(instr); - targ = (u32int *) vaddr(*Rn, &seg); + targ = (u32int *) vaddr(*Rn, 4, &seg); lock(&seg->lock); if(instr & fB) { tmp = *(u8int*) targ; @@ -256,11 +256,11 @@ halfword(u32int instr) if(instr & fP) target += offset; switch(instr & (fSg | fH | fL)) { - case fSg: *(u8int*) vaddr(target, &seg) = *Rd; break; - case fSg | fL: *Rd = (long) *(char*) vaddr(target, &seg); break; - case fH: case fSg | fH: *(u16int*) vaddr(target, &seg) = *Rd; break; - case fH | fL: *Rd = *(u16int*) vaddr(target, &seg); break; - case fH | fL | fSg: *Rd = (long) *(short*) vaddr(target, &seg); break; + case fSg: *(u8int*) vaddr(target, 1, &seg) = *Rd; break; + case fSg | fL: *Rd = (long) *(char*) vaddr(target, 1, &seg); break; + case fH: case fSg | fH: *(u16int*) vaddr(target, 2, &seg) = *Rd; break; + case fH | fL: *Rd = *(u16int*) vaddr(target, 2, &seg); break; + case fH | fL | fSg: *Rd = (long) *(short*) vaddr(target, 2, &seg); break; } segunlock(seg); if(!(instr & fP)) @@ -289,9 +289,9 @@ block(u32int instr) if(instr & fP) targ += 4; if(instr & fL) - P->R[i] = *(u32int*) vaddr(targ, &seg); + P->R[i] = *(u32int*) vaddr(targ, 4, &seg); else - *(u32int*) vaddr(targ, &seg) = P->R[i]; + *(u32int*) vaddr(targ, 4, &seg) = P->R[i]; segunlock(seg); if(!(instr & fP)) targ += 4; @@ -303,9 +303,9 @@ block(u32int instr) if(instr & fP) targ -= 4; if(instr & fL) - P->R[i] = *(u32int*) vaddr(targ, &seg); + P->R[i] = *(u32int*) vaddr(targ, 4, &seg); else - *(u32int*) vaddr(targ, &seg) = P->R[i]; + *(u32int*) vaddr(targ, 4, &seg) = P->R[i]; segunlock(seg); if(!(instr & fP)) targ -= 4; @@ -382,7 +382,7 @@ singleex(u32int instr) if(Rd == P->R + 15 || Rn == P->R + 15) invalid(instr); if(instr & fS) { - targ = vaddr(*Rn, &seg); + targ = vaddr(*Rn, 4, &seg); lock(&seg->lock); *Rd = *targ; segunlock(seg); @@ -390,11 +390,11 @@ singleex(u32int instr) Rm = P->R + (instr & 15); if(Rm == P->R + 15) invalid(instr); - targ = vaddr(*Rn, &seg); + targ = vaddr(*Rn, 4, &seg); if(canlock(&seg->lock)) { *Rd = 1; } else { - *targ = *Rd; + *targ = *Rm; unlock(&seg->lock); *Rd = 0; } @@ -408,7 +408,7 @@ step(void) u32int instr; Segment *seg; - instr = *(u32int*) vaddr(P->R[15], &seg); + instr = *(u32int*) vaddr(P->R[15], 4, &seg); segunlock(seg); if(fulltrace) { print("%d ", P->pid); diff --git a/sys/src/cmd/5e/dat.h b/sys/src/cmd/5e/dat.h index d8356f07d..63499bc97 100644 --- a/sys/src/cmd/5e/dat.h +++ b/sys/src/cmd/5e/dat.h @@ -4,8 +4,9 @@ typedef struct Fdtable Fdtable; typedef struct Fd Fd; enum { - STACKTOP = 0x80000000UL, - STACKSIZE = 0x10000, + STACKSIZE = 0x100000, + + NAMEMAX = 27, FDBLOCK = 16, SEGNUM = 8, @@ -25,17 +26,23 @@ enum { }; struct Process { - Segment* S[SEGNUM]; + Segment *S[SEGNUM]; u32int R[16]; /* general purpose registers / PC (R15) */ u32int CPSR; /* status register */ char errbuf[ERRMAX]; + char name[NAMEMAX+1]; + Ref *path; /* Ref + string data */ Fd *fd; int pid; + Process *prev, *next; }; extern void **_privates; extern int _nprivates; #define P (*(Process**)_privates) +extern Ref nproc; +extern Process plist; +extern Lock plistlock; enum { SEGFLLOCK = 1, @@ -44,16 +51,16 @@ enum { struct Segment { Ref; int flags; - RWLock rw; /* lock for SEGLOCK segments */ + RWLock rw; /* lock for SEGFLLOCK segments */ Lock lock; /* atomic accesses */ u32int start, size; void *data; - Ref *ref; + Ref *dref; }; struct Fd { RWLock; - Ref ref; + Ref; u8int *fds; int nfds; }; diff --git a/sys/src/cmd/5e/fns.h b/sys/src/cmd/5e/fns.h index 7ae97eae8..a28f5f433 100644 --- a/sys/src/cmd/5e/fns.h +++ b/sys/src/cmd/5e/fns.h @@ -4,8 +4,8 @@ void *erealloc(void *, u32int); void initproc(void); int loadtext(char *, int, char **); Segment *newseg(u32int, u32int, int); -void *vaddr(u32int, Segment **); -void *vaddrnol(u32int); +void *vaddr(u32int, u32int, Segment **); +void *vaddrnol(u32int, u32int); void step(void); void syscall(void); void cherrstr(char *, ...); @@ -20,4 +20,10 @@ void cleanup(void); void segunlock(Segment *); void *copyifnec(u32int, int, int *); void *bufifnec(u32int, int, int *); -void copyback(u32int, int, void *); \ No newline at end of file +void copyback(u32int, int, void *); +void initfs(char *, char *); +void suicide(char *, ...); +void fdclear(Fd *); +void addproc(Process *); +void remproc(Process *); +Process *findproc(int); diff --git a/sys/src/cmd/5e/fs.c b/sys/src/cmd/5e/fs.c new file mode 100644 index 000000000..c14e6231d --- /dev/null +++ b/sys/src/cmd/5e/fs.c @@ -0,0 +1,437 @@ +#include +#include +#include +#include +#include <9p.h> +#include "dat.h" +#include "fns.h" + +static char *luser; +extern int pflag; + +enum +{ + Qdir, + Qtrace, + Qargs, + Qctl, + Qfd, + Qfpregs, + Qkregs, + Qmem, + Qnote, + Qnoteid, + Qnotepg, + Qns, + Qproc, + Qregs, + Qsegment, + Qstatus, + Qtext, + Qwait, + Qprofile, + Qsyscall, + NQid, +}; + +typedef struct Aux Aux; +typedef struct Dirtab Dirtab; +struct Dirtab { + char name[28]; + Qid qid; + vlong length; + long perm; +}; +struct Aux { + Process *p; + int fd; + Dirtab *d; +}; + +Dirtab procdir[] = +{ + "args", {Qargs}, 0, 0660, + "ctl", {Qctl}, 0, 0600, + "fd", {Qfd}, 0, 0444, + "fpregs", {Qfpregs}, 0, 0400, + "kregs", {Qkregs}, 18 * 4, 0400, + "mem", {Qmem}, 0, 0400, + "note", {Qnote}, 0, 0000, + "noteid", {Qnoteid}, 0, 0664, + "notepg", {Qnotepg}, 0, 0000, + "ns", {Qns}, 0, 0444, + "proc", {Qproc}, 0, 0400, + "regs", {Qregs}, 18 * 4, 0400, + "segment", {Qsegment}, 0, 0444, + "status", {Qstatus}, 176, 0444, + "text", {Qtext}, 0, 0400, + "wait", {Qwait}, 0, 0400, + "profile", {Qprofile}, 0, 0400, + "syscall", {Qsyscall}, 0, 0400, + "", {0}, 0, 0, +}; + +static char * +readin(int pid, char *file) +{ + char *name, *buf; + int fd, rc; + + name = smprint("#p/%d/%s", pid, file); + fd = open(name, OREAD); + if(fd < 0) + return nil; + buf = malloc(1024); + rc = read(fd, buf, 1023); + if(rc < 0) + return nil; + buf[rc] = 0; + free(name); + close(fd); + return buf; +} + +static int +calcmem(Process *p) +{ + int i, r; + + r = 0; + for(i = 0; i < SEGNUM; i++) { + if(i == SEGSTACK) + continue; + if(p->S[i] == nil) + continue; + r += p->S[i]->size; + } + r = (r + 1023) / 1024; + return r; +} + +static int +copymem(Process *p, char *buf, u32int addr, int len) +{ + int i, n, r; + + r = len; + while(len > 0) { + for(i = 0; i < SEGNUM; i++) { + if(p->S[i] == nil) + continue; + if(p->S[i]->start <= addr && p->S[i]->start + p->S[i]->size > addr) + break; + } + if(i == SEGNUM) { + werrstr("bad arg in syscall"); + return -1; + } + n = p->S[i]->start + p->S[i]->size - addr; + if(n > len) + n = len; + memcpy(buf, (char*)p->S[i]->data + addr - p->S[i]->start, n); + len -= n; + buf += n; + } + return r; +} + +static char * +segments(Process *p) +{ + char *r, *s; + static char *names[] = { + [SEGTEXT] "Text", + [SEGSTACK] "Stack", + [SEGDATA] "Data", + [SEGBSS] "Bss", + }; + int i; + + r = emalloc(1024); + s = r; + for(i = 0; i < SEGNUM; i++) { + if(p->S[i] == nil) + continue; + s += sprint(s, "%-7s%c %.8ux %.8ux %4ld\n", names[i], i == SEGTEXT ? 'R' : ' ', p->S[i]->start, p->S[i]->start + p->S[i]->size, p->S[i]->dref->ref); + } + return r; +} + +static void +procattach(Req *req) +{ + req->fid->qid = (Qid) {0, 0, 0x80}; + req->fid->aux = emallocz(sizeof(Aux)); + ((Aux *) req->fid->aux)->fd = -1; + req->ofcall.qid = req->fid->qid; + respond(req, nil); +} + +static char * +procwalk(Fid *fid, char *name, Qid *qid) +{ + int pid; + char buf[20]; + Dirtab *d; + Aux *a; + + a = fid->aux; + if(fid->qid.path == 0) { + pid = atoi(name); + sprint(buf, "%d", pid); + if(strcmp(buf, name) != 0 || (a->p = findproc(pid)) == nil) + return "file does not exist"; + *qid = (Qid) {pid * NQid, 0, 0x80}; + fid->qid = *qid; + return nil; + } + if((fid->qid.path % NQid) == 0) { + for(d = procdir; d->name[0] != 0; d++) + if(strcmp(d->name, name) == 0) + break; + if(d->name[0] == 0) + return "file does not exist"; + *qid = d->qid; + qid->path += fid->qid.path; + fid->qid = *qid; + a->d = d; + return nil; + } + return "the front fell off"; +} + +static char * +procclone(Fid *old, Fid *new) +{ + new->aux = emallocz(sizeof(Aux)); + memcpy(new->aux, old->aux, sizeof(Aux)); + return nil; +} + +static void +procopen(Req *req) +{ + Aux *a; + + a = req->fid->aux; + switch((int)(req->fid->qid.path % NQid)) { + case Qtext: + a->fd = open((char*)(a->p->path + 1), OREAD); + break; + default: + respond(req, nil); + return; + } + if(a->fd < 0) + responderror(req); + else + respond(req, nil); +} + +static void +procdestroyfid(Fid *fid) +{ + Aux *a; + + a = fid->aux; + free(a); +} + +static int +procgen(int n, Dir *d, void *) +{ + int i; + Process *p; + + p = &plist; + for(i = 0;; i++) { + p = p->next; + if(p == &plist) + return -1; + if(i == n) + break; + } + d->uid = estrdup9p(luser); + d->gid = estrdup9p(luser); + d->muid = estrdup9p(luser); + d->name = smprint("%d", p->pid); + d->mode = DMDIR | 0555; + d->qid = (Qid) {p->pid * NQid, 0, 0x80}; + return 0; +} + +static int +procsubgen(int n, Dir *d, void *) +{ + Dirtab *di; + + if(n >= nelem(procdir) - 1) + return -1; + + di = procdir + n; + d->uid = estrdup9p(luser); + d->gid = estrdup9p(luser); + d->muid = estrdup9p(luser); + d->name = estrdup9p(di->name); + d->mode = di->perm; + d->length = di->length; + d->qid = di->qid; + return 0; +} + +static void +procread(Req *req) +{ + Aux *a; + Process *p; + char *buf; + int rc; + + a = req->fid->aux; + if(a == nil) { + respond(req, "the front fell off"); + return; + } + if(req->fid->qid.path == 0) { + dirread9p(req, procgen, nil); + respond(req, nil); + return; + } + p = a->p; + switch((int)(req->fid->qid.path % NQid)) { + case Qdir: + dirread9p(req, procsubgen, nil); + respond(req, nil); + break; + case Qstatus: + buf = readin(p->pid, "status"); + if(buf == nil) + responderror(req); + else { + memset(buf, ' ', 27); + memcpy(buf, p->name, strlen(p->name)); + sprint(buf + 149, "%d", calcmem(p)); + buf[strlen(buf)] = ' '; + readstr(req, buf); + free(buf); + respond(req, nil); + } + break; + case Qsegment: + buf = segments(p); + readstr(req, buf); + free(buf); + respond(req, nil); + break; + case Qtext: + rc = pread(a->fd, req->ofcall.data, req->ifcall.count, req->ifcall.offset); + if(rc >= 0) { + req->ofcall.count = rc; + respond(req, nil); + } else + responderror(req); + break; + case Qmem: + rc = copymem(p, req->ofcall.data, req->ifcall.offset, req->ifcall.count); + if(rc >= 0) { + req->ofcall.count = rc; + respond(req, nil); + } else + responderror(req); + break; + case Qregs: + buf = emallocz(18 * 4); + memcpy(buf, p->R, 15 * 4); + memcpy(buf + 16 * 4, &p->CPSR, 4); + memcpy(buf + 17 * 4, p->R + 15, 4); + readbuf(req, buf, 18 * 4); + free(buf); + respond(req, nil); + break; + default: + respond(req, "the front fell off"); + } +} + +static void +writeto(Req *req, char *fmt, ...) +{ + int fd, rc; + va_list va; + char *file; + + va_start(va, fmt); + file = vsmprint(fmt, va); + va_end(va); + fd = open(file, OWRITE); + free(file); + if(fd < 0) { + responderror(req); + return; + } + rc = write(fd, req->ifcall.data, req->ifcall.count); + req->ofcall.count = rc; + if(rc < req->ifcall.count) + responderror(req); + else + respond(req, nil); + close(fd); +} + +static void +procwrite(Req *req) +{ + switch((int)(req->fid->qid.path % NQid)) { + case Qnote: + writeto(req, "#p/%lld/note", req->fid->qid.path / NQid); + break; + default: + respond(req, "the front fell off"); + } +} + +static void +procstat(Req *req) +{ + Aux *a; + Dir *d; + + d = &req->d; + a = req->fid->aux; + if(a == nil) { + respond(req, "the front fell off"); + return; + } + d->qid = req->fid->qid; + if(a->d != nil) { + d->mode = a->d->perm; + d->length = a->d->length; + d->name = strdup(a->d->name); + } else { + d->mode = 0555 | DMDIR; + if(d->qid.path != 0) + d->name = smprint("%lld", d->qid.path / NQid); + } + d->uid = strdup(luser); + d->gid = strdup(luser); + d->muid = strdup(luser); + respond(req, nil); +} + +static Srv procsrv = { + .attach = procattach, + .walk1 = procwalk, + .clone = procclone, + .destroyfid = procdestroyfid, + .open = procopen, + .read = procread, + .stat = procstat, +}; + +void +initfs(char *name, char *mtpt) +{ + luser = getuser(); + remove("/srv/armproc"); + postmountsrv(&procsrv, name, mtpt, MREPL); +} diff --git a/sys/src/cmd/5e/mkfile b/sys/src/cmd/5e/mkfile index 5fcb58784..496fa8346 100644 --- a/sys/src/cmd/5e/mkfile +++ b/sys/src/cmd/5e/mkfile @@ -1,7 +1,7 @@ pid = getpid(); P->fd = newfd(); + incref(&nproc); + plist.prev = P; + plist.next = P; + P->prev = &plist; + P->next = &plist; +} + +void +addproc(Process *p) +{ + lock(&plistlock); + p->prev = plist.prev; + p->next = &plist; + plist.prev->next = p; + plist.prev = p; + unlock(&plistlock); +} + +void +remproc(Process *p) +{ + lock(&plistlock); + p->prev->next = p->next; + p->next->prev = p->prev; + unlock(&plistlock); +} + +Process * +findproc(int pid) +{ + Process *p; + + lock(&plistlock); + for(p = plist.next; p != &plist; p = p->next) + if(p->pid == pid) + break; + unlock(&plistlock); + if(p != &plist) + return p; + return nil; +} + +static void +copyname(char *file) +{ + char *p; + + p = strrchr(file, '/'); + if(p == nil) + p = file; + else + p++; + strncpy(P->name, p, NAMEMAX); + + if(P->path != nil && decref(P->path) == 0) + free(P->path); + P->path = emallocz(5 + strlen(file)); + incref(P->path); + strcpy((char*)(P->path + 1), file); } static void @@ -21,7 +83,7 @@ initstack(int argc, char **argv) { ulong tos, sp, ap, size, i, len; - tos = STACKTOP - sizeof(Tos) * 2; + tos = mach->utop - sizeof(Tos) * 2; sp = tos; size = 8; @@ -31,22 +93,22 @@ initstack(int argc, char **argv) sp -= size; sp &= ~7; P->R[0] = tos; - P->R[1] = STACKTOP - 4; + P->R[1] = mach->utop - 4; P->R[13] = sp; - *(ulong *) vaddrnol(sp) = argc; + *(ulong *) vaddrnol(sp, 4) = argc; sp += 4; ap = sp + (argc + 1) * 4; for(i = 0; i < argc; i++) { - *(ulong *) vaddrnol(sp) = ap; + *(ulong *) vaddrnol(sp, 4) = ap; sp += 4; len = strlen(argv[i]) + 1; - memcpy(vaddrnol(ap), argv[i], len); + memcpy(vaddrnol(ap, len), argv[i], len); ap += len; } - *(ulong *) vaddrnol(sp) = 0; + *(ulong *) vaddrnol(sp, 4) = 0; - ((Tos *) vaddrnol(tos))->pid = getpid(); + ((Tos *) vaddrnol(tos, sizeof(Tos)))->pid = getpid(); } static int @@ -104,9 +166,9 @@ invalid: int loadtext(char *file, int argc, char **argv) { - int fd, i; + int fd; Fhdr fp; - Segment *text, *data, *bss, *stack; + Segment *text, *data, *bss; char buf[2]; fd = open(file, OREAD); @@ -114,21 +176,18 @@ loadtext(char *file, int argc, char **argv) if(pread(fd, buf, 2, 0) == 2 && buf[0] == '#' && buf[1] == '!') return loadscript(fd, file, argc, argv); seek(fd, 0, 0); - if(crackhdr(fd, &fp) == 0) { - werrstr("exec header invalid"); - return -1; - } - if(fp.magic != E_MAGIC) { + if(crackhdr(fd, &fp) == 0 || fp.magic != E_MAGIC) { werrstr("exec header invalid"); return -1; } + copyname(file); freesegs(); memset(P->R, 0, sizeof(P->R)); P->CPSR = 0; text = newseg(fp.txtaddr - fp.hdrsz, fp.txtsz + fp.hdrsz, SEGTEXT); data = newseg(fp.dataddr, fp.datsz, SEGDATA); bss = newseg(fp.dataddr + fp.datsz, fp.bsssz, SEGBSS); - stack = newseg(STACKTOP - STACKSIZE, STACKSIZE, SEGSTACK); + newseg(mach->utop - STACKSIZE, STACKSIZE, SEGSTACK); seek(fd, fp.txtoff - fp.hdrsz, 0); if(readn(fd, text->data, fp.txtsz + fp.hdrsz) < fp.txtsz + fp.hdrsz) sysfatal("%r"); @@ -136,19 +195,11 @@ loadtext(char *file, int argc, char **argv) if(readn(fd, data->data, fp.datsz) < fp.datsz) sysfatal("%r"); memset(bss->data, 0, bss->size); - memset(stack->data, 0, stack->size); P->R[15] = fp.entry; if(havesymbols && syminit(fd, &fp) < 0) fprint(2, "initializing symbol table: %r\n"); close(fd); - for(i = 0; i < P->fd->nfds * 8; i++) - if(iscexec(P->fd, i)) - close(i); - wlock(P->fd); - free(P->fd->fds); - P->fd->fds = nil; - P->fd->nfds = 0; - wunlock(P->fd); + fdclear(P->fd); initstack(argc, argv); return 0; } @@ -178,7 +229,7 @@ newfd(void) Fd *fd; fd = emallocz(sizeof(*fd)); - incref(&fd->ref); + incref(fd); return fd; } @@ -201,7 +252,7 @@ copyfd(Fd *old) void fddecref(Fd *fd) { - if(decref(&fd->ref) == 0) { + if(decref(fd) == 0) { free(fd->fds); free(fd); } @@ -242,3 +293,25 @@ setcexec(Fd *fd, int n, int status) fd->fds[n / 8] |= (1 << (n % 8)); wunlock(fd); } + +void +fdclear(Fd *fd) +{ + int i, j, k; + + wlock(fd); + if(fd->nfds == 0) { + wunlock(fd); + return; + } + for(i = 0; i < fd->nfds; i++) { + j = fd->fds[i]; + for(k = 0; k < 8; k++) + if(j & (1<fds); + fd->nfds = 0; + fd->fds = nil; + wunlock(fd); +} diff --git a/sys/src/cmd/5e/seg.c b/sys/src/cmd/5e/seg.c index caa4002ac..1cde88241 100644 --- a/sys/src/cmd/5e/seg.c +++ b/sys/src/cmd/5e/seg.c @@ -13,10 +13,10 @@ newseg(u32int start, u32int size, int idx) incref(s); s->start = start; s->size = size; - s->ref = emalloc(size + sizeof(Ref)); - memset(s->ref, 0, sizeof(Ref)); - incref(s->ref); - s->data = s->ref + 1; + s->dref = emalloc(size + sizeof(Ref)); + memset(s->dref, 0, sizeof(Ref)); + incref(s->dref); + s->data = s->dref + 1; if(idx == SEGBSS) s->flags = SEGFLLOCK; P->S[idx] = s; @@ -31,8 +31,8 @@ freesegs(void) for(s = P->S; s < P->S + SEGNUM; s++) { if(*s == nil) continue; - if(decref((*s)->ref) == 0) - free((*s)->ref); + if(decref((*s)->dref) == 0) + free((*s)->dref); if(decref(*s) == 0) free(*s); *s = nil; @@ -40,7 +40,7 @@ freesegs(void) } void * -vaddr(u32int addr, Segment **seg) +vaddr(u32int addr, u32int len, Segment **seg) { Segment **ss, *s; @@ -49,23 +49,25 @@ vaddr(u32int addr, Segment **seg) continue; s = *ss; if(addr >= s->start && addr < s->start + s->size) { + if(addr + len > s->start + s->size) + break; if(s->flags & SEGFLLOCK) rlock(&s->rw); *seg = s; return (char *)s->data + (addr - s->start); } } - sysfatal("fault %.8ux @ %.8ux", addr, P->R[15]); + suicide("fault %.8ux (%d) @ %.8ux", addr, len, P->R[15]); return nil; } void * -vaddrnol(u32int addr) +vaddrnol(u32int addr, u32int len) { Segment *seg; void *ret; - ret = vaddr(addr, &seg); + ret = vaddr(addr, len, &seg); segunlock(seg); return ret; } @@ -84,7 +86,7 @@ copyifnec(u32int addr, int len, int *copied) void *targ, *ret; Segment *seg; - targ = vaddr(addr, &seg); + targ = vaddr(addr, len > 0 ? len : 0, &seg); if((seg->flags & SEGFLLOCK) == 0) { *copied = 0; return targ; @@ -104,7 +106,7 @@ bufifnec(u32int addr, int len, int *buffered) void *targ; Segment *seg; - targ = vaddr(addr, &seg); + targ = vaddr(addr, len, &seg); if((seg->flags & SEGFLLOCK) == 0) { *buffered = 0; return targ; @@ -122,7 +124,7 @@ copyback(u32int addr, int len, void *data) if(len <= 0) return; - targ = vaddr(addr, &seg); + targ = vaddr(addr, len, &seg); memmove(targ, data, len); segunlock(seg); free(data); diff --git a/sys/src/cmd/5e/sys.c b/sys/src/cmd/5e/sys.c index e88f8f1e0..daa02e0c7 100644 --- a/sys/src/cmd/5e/sys.c +++ b/sys/src/cmd/5e/sys.c @@ -9,7 +9,7 @@ static u32int arg(int n) { /* no locking necessary, since we're on the stack */ - return *(u32int*) vaddrnol(P->R[13] + 4 + 4 * n); + return *(u32int*) vaddrnol(P->R[13] + 4 + 4 * n, 4); } static u64int @@ -127,7 +127,7 @@ sysseek(void) vlong n, *ret; Segment *seg; - ret = vaddr(arg(0), &seg); + ret = vaddr(arg(0), 8, &seg); fd = arg(1); n = argv(2); type = arg(4); @@ -202,7 +202,7 @@ sysexits(void) if(arg(0) == 0) exits(nil); else - exits(vaddrnol(arg(0))); + exits(vaddrnol(arg(0), 0)); } static void @@ -218,10 +218,10 @@ sysbrk(void) sysfatal("bss length < 0, wtf?"); s = P->S[SEGBSS]; wlock(&s->rw); - s->ref = realloc(s->ref, v - s->start + 4); - if(s->ref == nil) + s->dref = realloc(s->dref, v - s->start + 4); + if(s->dref == nil) sysfatal("error reallocating"); - s->data = s->ref + 1; + s->data = s->dref + 1; if(s->size < v - s->start) memset((char*)s->data + s->size, 0, v - s->start - s->size); s->size = v - s->start; @@ -276,16 +276,17 @@ sysrfork(void) Process *p; Segment *s, *t; Fd *old; - enum { - RFORKPASS = RFENVG | RFCENVG | RFNOTEG | RFNOMNT | RFNAMEG | RFCNAMEG | RFNOWAIT | RFREND | RFFDG | RFCFDG, - RFORKHANDLED = RFPROC | RFMEM, - }; flags = arg(0); if(systrace) fprint(2, "rfork(%#o)\n", flags); - if(flags & ~(RFORKPASS | RFORKHANDLED)) - sysfatal("rfork with unhandled flags %#o", flags & ~(RFORKPASS | RFORKHANDLED)); + if((flags & (RFFDG | RFCFDG)) == (RFFDG | RFCFDG) || + (flags & (RFNAMEG | RFCNAMEG)) == (RFNAMEG | RFCNAMEG) || + (flags & (RFENVG | RFCENVG)) == (RFENVG | RFCENVG)) { + P->R[0] = -1; + cherrstr("bad arg in syscall"); + return; + } if((flags & RFPROC) == 0) { if(flags & RFFDG) { old = P->fd; @@ -297,9 +298,10 @@ sysrfork(void) P->fd = newfd(); fddecref(old); } - P->R[0] = noteerr(rfork(flags & RFORKPASS), 0); + P->R[0] = noteerr(rfork(flags), 0); return; } + incref(&nproc); p = emallocz(sizeof(Process)); memcpy(p, P, sizeof(Process)); for(i = 0; i < SEGNUM; i++) { @@ -311,15 +313,15 @@ sysrfork(void) incref(t); t->size = s->size; t->start = s->start; - t->ref = emalloc(sizeof(Ref) + s->size); - memset(t->ref, 0, sizeof(Ref)); - incref(t->ref); - t->data = t->ref + 1; + t->dref = emalloc(sizeof(Ref) + s->size); + memset(t->dref, 0, sizeof(Ref)); + incref(t->dref); + t->data = t->dref + 1; memcpy(t->data, s->data, s->size); p->S[i] = t; } else { + incref(s->dref); incref(s); - incref(s->ref); } } @@ -328,15 +330,17 @@ sysrfork(void) else if(flags & RFCFDG) p->fd = newfd(); else - incref(&P->fd->ref); + incref(P->fd); - rc = rfork(RFPROC | RFMEM | (flags & RFORKPASS)); - if(rc < 0) - sysfatal("rfork: %r"); + incref(P->path); + rc = rfork(RFMEM | flags); + if(rc < 0) /* this should NEVER happen */ + sysfatal("rfork failed wtf: %r"); if(rc == 0) { P = p; atexit(cleanup); P->pid = getpid(); + addproc(P); } P->R[0] = rc; } @@ -351,16 +355,16 @@ sysexec(void) name = arg(0); argv = arg(1); - namet = strdup(vaddr(name, &seg1)); + namet = strdup(vaddr(name, 0, &seg1)); segunlock(seg1); - argvt = vaddr(argv, &seg1); + argvt = vaddr(argv, 0, &seg1); if(systrace) fprint(2, "exec(%#ux=\"%s\", %#ux)\n", name, namet, argv); for(argc = 0; argvt[argc]; argc++) ; argvv = emalloc(sizeof(char *) * argc); for(i = 0; i < argc; i++) { - argvv[i] = strdup(vaddr(argvt[i], &seg2)); + argvv[i] = strdup(vaddr(argvt[i], 0, &seg2)); segunlock(seg2); } segunlock(seg1); From b4ae96bcb95e76293a81241bf6edebf27cab7e35 Mon Sep 17 00:00:00 2001 From: aiju Date: Sat, 25 Jun 2011 12:26:25 +0200 Subject: [PATCH 05/11] added ainc / adec prototype --- sys/include/libc.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sys/include/libc.h b/sys/include/libc.h index d6c49aaea..2c4f3b428 100644 --- a/sys/include/libc.h +++ b/sys/include/libc.h @@ -691,6 +691,9 @@ extern char* sysname(void); extern void werrstr(char*, ...); #pragma varargck argpos werrstr 1 +extern long ainc(long*); +extern long adec(long*); + extern char *argv0; #define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\ argv[0] && argv[0][0]=='-' && argv[0][1];\ From 0b22dfd1f69985aabc5af37dca8a217a1e6e54e9 Mon Sep 17 00:00:00 2001 From: aiju Date: Sat, 25 Jun 2011 16:17:20 +0200 Subject: [PATCH 06/11] 5e: added note support added wstat / fwstat / alarm --- sys/src/cmd/5e/5e.c | 18 ++++++++++ sys/src/cmd/5e/dat.h | 26 +++++++++------ sys/src/cmd/5e/fns.h | 3 ++ sys/src/cmd/5e/proc.c | 64 ++++++++++++++++++++++++++++++++++++ sys/src/cmd/5e/seg.c | 11 +++++-- sys/src/cmd/5e/sys.c | 76 +++++++++++++++++++++++++++++++++++++++++++ sys/src/cmd/5e/util.c | 3 ++ 7 files changed, 188 insertions(+), 13 deletions(-) diff --git a/sys/src/cmd/5e/5e.c b/sys/src/cmd/5e/5e.c index b2f23674c..fb589e54c 100644 --- a/sys/src/cmd/5e/5e.c +++ b/sys/src/cmd/5e/5e.c @@ -67,6 +67,19 @@ suicide(char *fmt, ...) abort(); } +int +notehandler(void *, char *note) +{ + if(strncmp(note, "sys:", 4) == 0) + return 0; + + if(strncmp(note, "emu:", 4) == 0) + exits(note); + + addnote(note); + return 1; +} + void main(int argc, char **argv) { @@ -90,9 +103,14 @@ main(int argc, char **argv) initproc(); if(loadtext(argv[0], argc, argv) < 0) sysfatal("%r"); + atnotify(notehandler, 1); for(;;) { if(ultraverbose) dump(); step(); + while((P->notein - P->noteout) % NNOTE) { + donote(P->notes[P->noteout % NNOTE], 0); + ainc(&P->noteout); + } } } diff --git a/sys/src/cmd/5e/dat.h b/sys/src/cmd/5e/dat.h index 63499bc97..153b99ee3 100644 --- a/sys/src/cmd/5e/dat.h +++ b/sys/src/cmd/5e/dat.h @@ -5,10 +5,8 @@ typedef struct Fd Fd; enum { STACKSIZE = 0x100000, - NAMEMAX = 27, - - FDBLOCK = 16, + NNOTE = 5, SEGNUM = 8, flN = 1<<31, @@ -26,15 +24,24 @@ enum { }; struct Process { - Segment *S[SEGNUM]; + Process *prev, *next; /* linked list (for fs) */ + int pid; + char name[NAMEMAX+1]; /* name for status file */ + Ref *path; /* Ref + string data */ + + Segment *S[SEGNUM]; /* memory */ u32int R[16]; /* general purpose registers / PC (R15) */ u32int CPSR; /* status register */ + char errbuf[ERRMAX]; - char name[NAMEMAX+1]; - Ref *path; /* Ref + string data */ - Fd *fd; - int pid; - Process *prev, *next; + Fd *fd; /* bitmap of OCEXEC files */ + + /* note handling */ + u32int notehandler; + int innote; + jmp_buf notejmp; + char notes[ERRMAX][NNOTE]; + long notein, noteout; }; extern void **_privates; @@ -69,4 +76,3 @@ struct Fd { #define havesymbols 0 #define ultraverbose 0 #define systrace 0 - diff --git a/sys/src/cmd/5e/fns.h b/sys/src/cmd/5e/fns.h index a28f5f433..e3966136f 100644 --- a/sys/src/cmd/5e/fns.h +++ b/sys/src/cmd/5e/fns.h @@ -27,3 +27,6 @@ void fdclear(Fd *); void addproc(Process *); void remproc(Process *); Process *findproc(int); +void donote(char *, ulong); +void addnote(char *); +void dump(void); diff --git a/sys/src/cmd/5e/proc.c b/sys/src/cmd/5e/proc.c index fa1dc9aad..2639ea696 100644 --- a/sys/src/cmd/5e/proc.c +++ b/sys/src/cmd/5e/proc.c @@ -181,6 +181,7 @@ loadtext(char *file, int argc, char **argv) return -1; } copyname(file); + P->notehandler = P->innote = P->notein = P->noteout = 0; freesegs(); memset(P->R, 0, sizeof(P->R)); P->CPSR = 0; @@ -315,3 +316,66 @@ fdclear(Fd *fd) fd->fds = nil; wunlock(fd); } + +/* call this from a notehandler if you don't want the front to fall off */ +void +addnote(char *msg) +{ + int new; + + new = P->notein + 1; + if((new - P->noteout) % NNOTE == 0) + return; + + strncpy(P->notes[P->notein % NNOTE], msg, ERRMAX - 1); + P->notein = new; +} + +/* the following code is not for the weak of heart */ +void +donote(char *msg, ulong type) +{ + int rc; + u32int *ureg, *sp, uregp, msgp; + char *msgb; + + if(P->notehandler == 0) + exits(msg); + + uregp = P->R[13] - 18 * 4; + ureg = vaddrnol(uregp, 18 * 4); + memcpy(ureg, P->R, 15 * 4); + ureg[15] = type; + ureg[16] = P->CPSR; + ureg[17] = P->R[15]; + P->R[13] = uregp; + msgp = P->R[13] -= strlen(msg) + 1; + msgb = vaddrnol(msgp, strlen(msg) + 1); + strcpy(msgb, msg); + P->R[13] -= 3 * 4; + sp = vaddrnol(P->R[13], 3 * 4); + sp[0] = 0; + sp[2] = msgp; + P->R[0] = uregp; + P->R[15] = P->notehandler; + P->innote = 1; + switch(rc = setjmp(P->notejmp) - 1) { + case -1: + for(;;) { + if(ultraverbose) + dump(); + step(); + } + case NDFLT: + exits(msg); + case NCONT: + break; + default: + sysfatal("unhandled noted argument %d", rc); + } + P->innote = 0; + ureg = vaddrnol(uregp, 18 * 4); /* just to be sure */ + memcpy(P->R, ureg, 15 * 4); + P->CPSR = ureg[16]; + P->R[15] = ureg[17]; +} diff --git a/sys/src/cmd/5e/seg.c b/sys/src/cmd/5e/seg.c index 1cde88241..66613baff 100644 --- a/sys/src/cmd/5e/seg.c +++ b/sys/src/cmd/5e/seg.c @@ -94,6 +94,7 @@ copyifnec(u32int addr, int len, int *copied) if(len < 0) len = strlen(targ) + 1; ret = emalloc(len); + setmalloctag(ret, getcallerpc(&addr)); memcpy(ret, targ, len); segunlock(seg); *copied = 1; @@ -103,7 +104,7 @@ copyifnec(u32int addr, int len, int *copied) void * bufifnec(u32int addr, int len, int *buffered) { - void *targ; + void *targ, *v; Segment *seg; targ = vaddr(addr, len, &seg); @@ -113,7 +114,9 @@ bufifnec(u32int addr, int len, int *buffered) } segunlock(seg); *buffered = 1; - return emalloc(len); + v = emalloc(len); + setmalloctag(v, getcallerpc(&addr)); + return v; } void @@ -122,8 +125,10 @@ copyback(u32int addr, int len, void *data) void *targ; Segment *seg; - if(len <= 0) + if(len <= 0) { + free(data); return; + } targ = vaddr(addr, len, &seg); memmove(targ, data, len); segunlock(seg); diff --git a/sys/src/cmd/5e/sys.c b/sys/src/cmd/5e/sys.c index daa02e0c7..0f9fb1c03 100644 --- a/sys/src/cmd/5e/sys.c +++ b/sys/src/cmd/5e/sys.c @@ -196,6 +196,46 @@ sysfstat(void) copyback(edir, P->R[0], edirt); } +static void +syswstat(void) +{ + u32int name, edir, nedir; + char *namet; + void *edirt; + int copied, copied2; + + name = arg(0); + namet = copyifnec(name, -1, &copied); + edir = arg(1); + nedir = arg(2); + edirt = copyifnec(edir, nedir, &copied2); + if(systrace) + fprint(2, "wstat(%#ux=\"%s\", %#ux, %ud)\n", name, namet, edir, nedir); + P->R[0] = noteerr(wstat(namet, edirt, nedir), nedir); + if(copied) + free(namet); + if(copied2) + free(edirt); +} + +static void +sysfwstat(void) +{ + u32int fd, edir, nedir; + void *edirt; + int copied; + + fd = arg(0); + edir = arg(1); + nedir = arg(2); + edirt = copyifnec(edir, nedir, &copied); + if(systrace) + fprint(2, "fwstat(%d, %#ux, %d)\n", fd, edir, nedir); + P->R[0] = noteerr(fwstat(fd, edirt, nedir), nedir); + if(copied) + free(edirt); +} + static void sysexits(void) { @@ -266,6 +306,27 @@ syschdir(void) static void sysnotify(void) { + u32int handler; + + handler = arg(0); + if(systrace) + fprint(2, "notify(%#ux)\n", handler); + P->notehandler = handler; + P->R[0] = 0; +} + +static void +sysnoted(void) +{ + u32int v; + + v = arg(0); + if(systrace) + fprint(2, "noted(%d)\n", v); + if(P->innote) + longjmp(P->notejmp, v + 1); + cherrstr("the front fell off"); + P->R[0] = -1; } static void @@ -541,6 +602,17 @@ sysremove(void) free(filet); } +static void +sysalarm(void) +{ + u32int msec; + + msec = arg(0); + if(systrace) + fprint(2, "alarm(%d)\n", msec); + P->R[0] = alarm(msec); +} + void syscall(void) { @@ -556,10 +628,13 @@ syscall(void) [ERRSTR] syserrstr, [STAT] sysstat, [FSTAT] sysfstat, + [WSTAT] syswstat, + [FWSTAT] sysfwstat, [SEEK] sysseek, [CHDIR] syschdir, [FD2PATH] sysfd2path, [NOTIFY] sysnotify, + [NOTED] sysnoted, [RFORK] sysrfork, [EXEC] sysexec, [AWAIT] sysawait, @@ -571,6 +646,7 @@ syscall(void) [DUP] sysdup, [MOUNT] sysmount, [REMOVE] sysremove, + [ALARM] sysalarm, }; n = P->R[0]; diff --git a/sys/src/cmd/5e/util.c b/sys/src/cmd/5e/util.c index dc9efa424..49818f907 100644 --- a/sys/src/cmd/5e/util.c +++ b/sys/src/cmd/5e/util.c @@ -12,6 +12,7 @@ emalloc(u32int size) v = malloc(size); if(v == nil) sysfatal("%r"); + setmalloctag(v, getcallerpc(&size)); return v; } @@ -22,6 +23,7 @@ emallocz(u32int size) v = emalloc(size); memset(v, 0, size); + setmalloctag(v, getcallerpc(&size)); return v; } @@ -33,5 +35,6 @@ erealloc(void *old, u32int size) v = realloc(old, size); if(v == nil) sysfatal("%r"); + setrealloctag(v, getcallerpc(&old)); return v; } From a4436018f1dcbcd1dae39e16a8bebbb5afbf44ba Mon Sep 17 00:00:00 2001 From: aiju Date: Sat, 25 Jun 2011 20:48:25 +0200 Subject: [PATCH 07/11] 5e: added FPA support --- sys/src/cmd/5e/arm.c | 8 ++- sys/src/cmd/5e/dat.h | 3 + sys/src/cmd/5e/fns.h | 5 ++ sys/src/cmd/5e/fpa.c | 148 ++++++++++++++++++++++++++++++++++++++++++ sys/src/cmd/5e/mkfile | 2 +- sys/src/cmd/5e/proc.c | 2 + 6 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 sys/src/cmd/5e/fpa.c diff --git a/sys/src/cmd/5e/arm.c b/sys/src/cmd/5e/arm.c index 507c46361..bacdab853 100644 --- a/sys/src/cmd/5e/arm.c +++ b/sys/src/cmd/5e/arm.c @@ -19,7 +19,7 @@ enum { fH = 1<<5, }; -static void +void invalid(u32int instr) { suicide("undefined instruction %8ux @ %8ux", instr, P->R[15] - 4); @@ -467,6 +467,12 @@ step(void) syscall(); else if((instr & (7<<25)) == (4 << 25)) block(instr); + else if((instr & 0x0E000F00) == 0x0C000100) + fpatransfer(instr); + else if((instr & 0x0E000F10) == 0x0E000100) + fpaoperation(instr); + else if((instr & 0x0E000F10) == 0x0E000110) + fparegtransfer(instr); else invalid(instr); } diff --git a/sys/src/cmd/5e/dat.h b/sys/src/cmd/5e/dat.h index 153b99ee3..d904c8a7b 100644 --- a/sys/src/cmd/5e/dat.h +++ b/sys/src/cmd/5e/dat.h @@ -32,6 +32,9 @@ struct Process { Segment *S[SEGNUM]; /* memory */ u32int R[16]; /* general purpose registers / PC (R15) */ u32int CPSR; /* status register */ + + u32int FPSR; + long double F[8]; char errbuf[ERRMAX]; Fd *fd; /* bitmap of OCEXEC files */ diff --git a/sys/src/cmd/5e/fns.h b/sys/src/cmd/5e/fns.h index e3966136f..2d28c522e 100644 --- a/sys/src/cmd/5e/fns.h +++ b/sys/src/cmd/5e/fns.h @@ -30,3 +30,8 @@ Process *findproc(int); void donote(char *, ulong); void addnote(char *); void dump(void); +void resetfpa(void); +void invalid(u32int); +void fpatransfer(u32int); +void fpaoperation(u32int); +void fparegtransfer(u32int); diff --git a/sys/src/cmd/5e/fpa.c b/sys/src/cmd/5e/fpa.c new file mode 100644 index 000000000..c220de881 --- /dev/null +++ b/sys/src/cmd/5e/fpa.c @@ -0,0 +1,148 @@ +#include +#include +#include +#include +#include +#include "dat.h" +#include "fns.h" + +void +resetfpa(void) +{ + int i; + + P->FPSR = 0x81000000; + for(i = 0; i < 8; i++) + P->F[i] = 0; +} + +void +fpatransfer(u32int instr) +{ + enum { + fP = 1<<24, + fU = 1<<23, + fT1 = 1<<22, + fW = 1<<21, + fL = 1<<20, + fT0 = 1<<15, + }; + + long double *Fd; + u32int *Rn, addr; + int off; + void *targ; + Segment *seg; + + Rn = P->R + ((instr >> 16) & 15); + Fd = P->F + ((instr >> 12) & 7); + if(Rn == P->R + 15) + invalid(instr); + off = (instr & 255) * 4; + if(!(instr & fU)) + off = -off; + addr = *Rn; + if(instr & fP) + addr += off; + targ = vaddr(addr, 8, &seg); + switch(instr & (fT0 | fT1 | fL)) { + case 0: *(float *) targ = *Fd; break; + case fL: *Fd = *(float *) targ; break; + case fT0: *(double *) targ = *Fd; break; + case fT0 | fL: *Fd = *(double *) targ; break; + default: invalid(instr); + } + segunlock(seg); + if(!(instr & fP)) + addr += off; + if(instr & fW) + *Rn = addr; +} + +static long double +fpasecop(u32int instr) +{ + switch(instr & 15) { + case 8: return 0.0; break; + case 9: return 1.0; break; + case 10: return 2.0; break; + case 11: return 3.0; break; + case 12: return 4.0; break; + case 13: return 5.0; break; + case 14: return 0.5; break; + case 15: return 10.0; break; + } + return P->F[instr & 7]; +} + +void +fpaoperation(u32int instr) +{ + long double *Fn, *Fd, op, op2, res; + int prec, opc; + + Fn = P->F + ((instr >> 16) & 7); + Fd = P->F + ((instr >> 12) & 7); + op2 = fpasecop(instr); + op = *Fn; + prec = ((instr >> 7) & 1) | ((instr >> 18) & 2); + opc = ((instr >> 20) & 15) | ((instr >> 11) & 16); + switch(opc) { + case 0: res = op + op2; break; + case 1: res = op * op2; break; + case 2: res = op - op2; break; + case 3: res = op2 - op; break; + case 4: res = op / op2; break; + case 5: res = op2 / op; break; + case 16: res = op2; break; + case 17: res = - op2; break; + case 18: res = fabs(op2); break; + case 19: res = (vlong) op2; break; + case 20: res = sqrt(op2); break; + default: sysfatal("unimplemented FPA operation %#x @ %8ux", opc, P->R[15] - 4); + } + switch(prec) { + case 0: *Fd = (float) res; break; + case 1: *Fd = (double) res; break; + case 2: *Fd = res; break; + default: invalid(instr); + } +} + +void +fparegtransfer(u32int instr) +{ + u32int *Rd; + long tmp; + long double *Fn, op, op2; + + Rd = P->R + ((instr >> 12) & 15); + Fn = P->F + ((instr >> 16) & 7); + op = fpasecop(instr); + if(Rd == P->R + 15) { + op2 = *Fn; + switch((instr >> 21) & 7) { + case 4: break; + case 5: op = - op; break; + default: invalid(instr); + } + if(op2 < op) + P->CPSR = (P->CPSR & ~FLAGS) | flN; + else if(op2 >= op) { + P->CPSR = (P->CPSR & ~FLAGS) | flC; + if(op2 == op) + P->CPSR |= flZ; + } else + P->CPSR = (P->CPSR & ~FLAGS) | flV; + return; + } + if(instr & (1<<3)) + invalid(instr); + switch((instr >> 20) & 15) { + case 0: *Fn = *(long *) Rd; break; + case 1: tmp = op; *Rd = tmp; break; + case 2: P->FPSR = *Rd; break; + case 3: *Rd = P->FPSR; break; + default: invalid(instr); + } +} diff --git a/sys/src/cmd/5e/mkfile b/sys/src/cmd/5e/mkfile index 496fa8346..6eab4fb5b 100644 --- a/sys/src/cmd/5e/mkfile +++ b/sys/src/cmd/5e/mkfile @@ -1,7 +1,7 @@ prev = &plist; P->next = &plist; + resetfpa(); } void @@ -202,6 +203,7 @@ loadtext(char *file, int argc, char **argv) close(fd); fdclear(P->fd); initstack(argc, argv); + resetfpa(); return 0; } From fb37e71a2e00a8519b7bd12328d01e389c0625bc Mon Sep 17 00:00:00 2001 From: aiju Date: Sat, 25 Jun 2011 21:41:42 +0200 Subject: [PATCH 08/11] fixed horrible python ARM bug --- sys/src/cmd/python/plan9.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/sys/src/cmd/python/plan9.c b/sys/src/cmd/python/plan9.c index 94228077e..783632423 100644 --- a/sys/src/cmd/python/plan9.c +++ b/sys/src/cmd/python/plan9.c @@ -4,14 +4,6 @@ #include #include -#if defined(T386) -#define FPINVAL (1<<0) -#elif defined(Tarm) -#define FPINVAL (1<<16) -#else -Error define FPINVAL for your arch. grep /$cputype/include/u.h -#endif - Threadarg *_threadarg; extern DL_EXPORT(int) Py_Main(int, char **); @@ -21,7 +13,14 @@ main(int argc, char **argv) { Threadarg ta; - setfcr(getfcr()&~FPINVAL); +#if defined(T386) + setfcr(getfcr()&~(1<<0)); +#elif defined(Tarm) + setfsr(getfsr()&~(1<<16)); +#else +Error define code for disabling fp exceptions for your arch. +#endif + memset(&ta, 0, sizeof ta); _threadarg = &ta; if(setjmp(ta.jb)){ From b05166304355fe3898794fea6c925aeb4d13a12f Mon Sep 17 00:00:00 2001 From: aiju Date: Sat, 25 Jun 2011 21:48:28 +0200 Subject: [PATCH 09/11] 5e: changed argument behaviour --- sys/src/cmd/5e/5e.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/sys/src/cmd/5e/5e.c b/sys/src/cmd/5e/5e.c index fb589e54c..be0f8dabd 100644 --- a/sys/src/cmd/5e/5e.c +++ b/sys/src/cmd/5e/5e.c @@ -80,6 +80,22 @@ notehandler(void *, char *note) return 1; } +static void +dotext(int argc, char **argv) +{ + char *file; + + if(**argv == '/' || **argv == '.' || **argv == '#') { + if(loadtext(*argv, argc, argv) < 0) + sysfatal("loadtext: %r"); + return; + } + file = smprint("/bin/%s", *argv); + if(loadtext(file, argc, argv) < 0) + sysfatal("loadtext: %r"); + free(file); +} + void main(int argc, char **argv) { @@ -96,13 +112,12 @@ main(int argc, char **argv) if(rfork(RFREND | RFNAMEG | RFENVG) < 0) sysfatal("rfork: %r"); atexit(cleanup); - if(nflag) + if(!nflag) adjustns(); if(pflag) initfs("armproc", "/proc"); initproc(); - if(loadtext(argv[0], argc, argv) < 0) - sysfatal("%r"); + dotext(argc, argv); atnotify(notehandler, 1); for(;;) { if(ultraverbose) From 6f8b37167d860b01d0a29525d9ba48482ba18bce Mon Sep 17 00:00:00 2001 From: aiju Date: Sun, 26 Jun 2011 22:31:39 +0200 Subject: [PATCH 10/11] added 5e(1) manpage --- sys/man/1/5e | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 sys/man/1/5e diff --git a/sys/man/1/5e b/sys/man/1/5e new file mode 100644 index 000000000..543080af0 --- /dev/null +++ b/sys/man/1/5e @@ -0,0 +1,137 @@ +.TH 5E 1 +.SH NAME +5e \- user-mode ARM emulation +.SH SYNOPSIS +.B 5e +[ +.B -npb +] +.I text +[ +.I arguments +] +.SH DESCRIPTION +.I 5e +simulates the execution of an ARM binary in a Plan 9 environment. +Unlike its predecessor +.IR 5i (1) +it supports, among others, the syscalls +.IR rfork (2) +and +.IR exec (2), +i.e. it allows execution of threaded programs, e.g. +.IR rio (1) +or +.IR catclock (1). +.PP +.I 5e +executes the specified binary +.IR text , +which is prepended by +.B /bin +if it does not begin with a slash, dot or hash sign. +Unless +.B -n +is specified, +.B /bin +is replaced by the union of +.B /arm/bin +and +.BR /rc/bin . +.PP +Unlike +.IR 5i (1), +.IR 5e (1) +does not provide built-in debugging facilities. +It +.I does +provide emulation of the +.B /proc +directory, if the +.B -p +flag is specified, to attach a proper debugger like +.IR acid (1). +There is no equivalent of the profiling facilities, no caches or TLBs are simulated, either. +.PP +.IR 5e (1) +currently has three options. +.TP +.B -n +By default, +.IR 5e (1) +replaces +.B /bin +as mentioned above and also sets the variables +.B cputype +and +.B objtype +to +.BR arm. +Supplying the +.B -n +option suppresses this behaviour. +.TP +.B -p +The +.B -p +option activates emulation of a +.B /proc +file system, which is mounted at +.B /proc +and also posted as +.BR /srv/armproc , +cf. +.IR srv (3). +.TP +.B -b +Supplying +.B -b +causes failing processes to call +.IR abort (2) +instead of +.IR sysfatal (2), +but see below. +.SH SOURCE +.B /sys/src/cmd/5e +.SH SEE ALSO +.IR 5i (1) +.SH BUGS +The host is required to be little endian and is assumed to have a floating point implementation conforming to IEEE 754. + +Broken processes are simulated in a rather unsatisfactory manner. +The +.B -b +option leaks memory. +The emulator does not post +.B sys: +notes. + +Obscure opcodes, in particular uncommon operations on R15, are not implemented. +Careless use of the +.B LDREX +and +.B STREX +instructions can lead to deadlock, however a real processor is supposed behave undefined in these cases. + +Accesses spanning segment boundaries will be treated like page faults. +Many syscalls like +.IR pread (2) +will shuffle data around (in most cases unnecessarily), if invoked on potentially shared segments of variable length, in particular the bss segment. + +FPA emulation leaves much to desire, rounding modes are ignored, all calculations are performed at extended precision. +Floating point exceptions crash the emulator. + +Several syscalls, most notably the +.IR segattach (2) +family, are not implemented (this should not be hard to fix). +The emulator notes the value of +.IR errstr (2) +only under obvious circumstances; with most syscalls only if the return value is negative. + +.B /proc +emulation is more than unsatisfactory. + +The +.I text +argument should behave more like it would if it was entered in +.IR rc (1). From 883f9aaab94bddbc21be7675e4889489ce489ec6 Mon Sep 17 00:00:00 2001 From: aiju Date: Sun, 26 Jun 2011 22:44:11 +0200 Subject: [PATCH 11/11] fixed kill --- rc/bin/kill | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rc/bin/kill b/rc/bin/kill index def927e92..e8ea70ac6 100755 --- a/rc/bin/kill +++ b/rc/bin/kill @@ -1,4 +1,8 @@ #!/bin/rc +rfork e +U=`{cat /dev/user} for(i){ - ps | sed -n '/ '^$i^'$/s%^[^ ]* *([^ ]*).*%chmod 666 /proc/\1/ctl;echo kill > /proc/\1/ctl%p' + ps | sed -n '/^'$U' .* '$i'$/s%[^ ]* *%~>/proc/% + s% *.* (.*)%/note # \1% + s%~%echo kill%p' }