This commit is contained in:
cinap_lenrek 2011-06-26 07:03:44 +02:00
commit fff6d18d51
18 changed files with 1177 additions and 118 deletions

View file

@ -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'
}

View file

@ -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.
<uriel> 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
<Tanami> 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.
<aiju> i like how 2011 cell phones emulate 1970 modems
<ment> 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
<aiju> is he building the GNU ark? two of each feature ..

View file

@ -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];\

137
sys/man/1/5e Normal file
View file

@ -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).

View file

@ -10,7 +10,7 @@ ls, lc \- list contents of directory
.PP
.B lc
[
.B -dlmnqrstuFQT
.B -dlmnqrstuQT
]
.I name ...
.SH DESCRIPTION

View file

@ -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)

View file

@ -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,73 @@ 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();
}
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;
}
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)
{
ARGBEGIN {
case 'n': nflag++; break;
case 'p': pflag++; break;
case 'b': bflag++; break;
default: usage();
} ARGEND;
if(argc < 1)
@ -63,14 +112,20 @@ 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)
dump();
step();
while((P->notein - P->noteout) % NNOTE) {
donote(P->notes[P->noteout % NNOTE], 0);
ainc(&P->noteout);
}
}
}

View file

@ -19,10 +19,10 @@ enum {
fH = 1<<5,
};
static void
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);
@ -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);
}

View file

@ -4,10 +4,9 @@ typedef struct Fdtable Fdtable;
typedef struct Fd Fd;
enum {
STACKTOP = 0x80000000UL,
STACKSIZE = 0x10000,
FDBLOCK = 16,
STACKSIZE = 0x100000,
NAMEMAX = 27,
NNOTE = 5,
SEGNUM = 8,
flN = 1<<31,
@ -25,17 +24,35 @@ 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 */
u32int FPSR;
long double F[8];
char errbuf[ERRMAX];
Fd *fd;
int pid;
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;
extern int _nprivates;
#define P (*(Process**)_privates)
extern Ref nproc;
extern Process plist;
extern Lock plistlock;
enum {
SEGFLLOCK = 1,
@ -44,16 +61,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;
};
@ -62,4 +79,3 @@ struct Fd {
#define havesymbols 0
#define ultraverbose 0
#define systrace 0

View file

@ -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,18 @@ void cleanup(void);
void segunlock(Segment *);
void *copyifnec(u32int, int, int *);
void *bufifnec(u32int, int, int *);
void copyback(u32int, int, void *);
void copyback(u32int, int, void *);
void initfs(char *, char *);
void suicide(char *, ...);
void fdclear(Fd *);
void addproc(Process *);
void remproc(Process *);
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);

148
sys/src/cmd/5e/fpa.c Normal file
View file

@ -0,0 +1,148 @@
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <bio.h>
#include <mach.h>
#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);
}
}

437
sys/src/cmd/5e/fs.c Normal file
View file

@ -0,0 +1,437 @@
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#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);
}

View file

@ -1,7 +1,7 @@
</$objtype/mkfile
TARG=5e
OFILES=5e.$O seg.$O proc.$O util.$O arm.$O sys.$O
OFILES=5e.$O seg.$O proc.$O util.$O arm.$O sys.$O fs.$O fpa.$O
HFILES=dat.h fns.h
BIN=/$objtype/bin

View file

@ -8,12 +8,75 @@
#include "dat.h"
#include "fns.h"
Process plist;
Lock plistlock;
void
initproc(void)
{
P = emallocz(sizeof(Process));
P->pid = getpid();
P->fd = newfd();
incref(&nproc);
plist.prev = P;
plist.next = P;
P->prev = &plist;
P->next = &plist;
resetfpa();
}
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 +84,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 +94,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 +167,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 +177,19 @@ 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);
P->notehandler = P->innote = P->notein = P->noteout = 0;
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,20 +197,13 @@ 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);
resetfpa();
return 0;
}
@ -178,7 +232,7 @@ newfd(void)
Fd *fd;
fd = emallocz(sizeof(*fd));
incref(&fd->ref);
incref(fd);
return fd;
}
@ -201,7 +255,7 @@ copyfd(Fd *old)
void
fddecref(Fd *fd)
{
if(decref(&fd->ref) == 0) {
if(decref(fd) == 0) {
free(fd->fds);
free(fd);
}
@ -242,3 +296,88 @@ 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<<k))
close(8 * i + k);
}
free(fd->fds);
fd->nfds = 0;
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];
}

View file

@ -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;
@ -92,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;
@ -101,17 +104,19 @@ 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, &seg);
targ = vaddr(addr, len, &seg);
if((seg->flags & SEGFLLOCK) == 0) {
*buffered = 0;
return targ;
}
segunlock(seg);
*buffered = 1;
return emalloc(len);
v = emalloc(len);
setmalloctag(v, getcallerpc(&addr));
return v;
}
void
@ -120,9 +125,11 @@ copyback(u32int addr, int len, void *data)
void *targ;
Segment *seg;
if(len <= 0)
if(len <= 0) {
free(data);
return;
targ = vaddr(addr, &seg);
}
targ = vaddr(addr, len, &seg);
memmove(targ, data, len);
segunlock(seg);
free(data);

View file

@ -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);
@ -196,13 +196,53 @@ 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)
{
if(arg(0) == 0)
exits(nil);
else
exits(vaddrnol(arg(0)));
exits(vaddrnol(arg(0), 0));
}
static void
@ -218,10 +258,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;
@ -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
@ -276,16 +337,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 +359,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 +374,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 +391,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 +416,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);
@ -537,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)
{
@ -552,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,
@ -567,6 +646,7 @@ syscall(void)
[DUP] sysdup,
[MOUNT] sysmount,
[REMOVE] sysremove,
[ALARM] sysalarm,
};
n = P->R[0];

View file

@ -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;
}

View file

@ -4,14 +4,6 @@
#include <u.h>
#include <lib9.h>
#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)){