merge
This commit is contained in:
commit
fff6d18d51
18 changed files with 1177 additions and 118 deletions
|
@ -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'
|
||||
}
|
||||
|
|
|
@ -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 ..
|
||||
|
|
|
@ -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
137
sys/man/1/5e
Normal 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).
|
|
@ -10,7 +10,7 @@ ls, lc \- list contents of directory
|
|||
.PP
|
||||
.B lc
|
||||
[
|
||||
.B -dlmnqrstuFQT
|
||||
.B -dlmnqrstuQT
|
||||
]
|
||||
.I name ...
|
||||
.SH DESCRIPTION
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
148
sys/src/cmd/5e/fpa.c
Normal 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
437
sys/src/cmd/5e/fs.c
Normal 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);
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)){
|
||||
|
|
Loading…
Reference in a new issue