commit 8a44751270915a0ad6e86adf68a111dd509be9be
parent ed98fad5e2bfe95b6f631ab547df24e4d575900c
Author: Russ Cox <rsc@swtch.com>
Date: Fri, 4 Jul 2008 12:06:36 -0400
[merge]
Diffstat:
13 files changed, 327 insertions(+), 229 deletions(-)
diff --git a/src/9vx/a/dat.h b/src/9vx/a/dat.h
@@ -1,4 +1,5 @@
#include <ucontext.h>
+#include "libvx32/vx32.h"
typedef struct BIOS32si BIOS32si;
typedef struct Conf Conf;
@@ -114,12 +115,14 @@ struct Conf
* MMU stuff in proc
*/
#define NCOLOR 1
+typedef struct Uspace Uspace;
struct PMMU
{
- ulong lo; // Plan 9 VX
- ulong hi; // Plan 9 VX
struct vxproc *vxproc; // Plan 9 VX
- struct vxmmap *vxmm; // Plan 9 VX
+ struct vxmem vxmem;
+ struct vxmmap vxmm; // Plan 9 VX
+ Uspace *us;
+ uchar *uzero;
};
/*
@@ -348,7 +351,6 @@ struct DevConf
// Plan 9 VX
extern int traceprocs;
extern int tracesyscalls;
-extern uchar *uzero;
extern int doabort;
/* Pthreads-based sleep and wakeup. */
@@ -356,12 +358,16 @@ typedef struct Psleep Psleep;
typedef struct Pwaiter Pwaiter;
struct Psleep
{
+ int init;
pthread_mutex_t mutex;
- pthread_cond_t cond;
- int condinit;
Pwaiter *waiter;
- int fd[2];
- vlong nread;
- vlong nwrite;
+};
+
+struct Uspace
+{
+ Proc *p; // proc currently mapped
+ uchar *uzero;
+ ulong lo;
+ ulong hi;
};
diff --git a/src/9vx/a/fault.c b/src/9vx/a/fault.c
@@ -343,7 +343,7 @@ okaddr(ulong addr, ulong len, int write)
continue;
}
qunlock(&s->lk);
- return uzero+addr0;
+ return up->pmmu.uzero+addr0;
}
}
pprint("suicide: invalid address 0x%lux/%lud in sys call pc=0x%lux\n", addr, len, userpc());
@@ -400,7 +400,7 @@ vmemchr(void *s, int c, int n)
a += m_;
n -= m_;
if(isuaddr(a))
- uvalidaddr(a-uzero, 1, 0);
+ uvalidaddr(a-up->pmmu.uzero, 1, 0);
}
/* fits in one page */
diff --git a/src/9vx/a/sysproc.c b/src/9vx/a/sysproc.c
@@ -379,6 +379,8 @@ sysexec(ulong *arg)
/*
* Top-of-stack structure.
*/
+ uchar *uzero;
+ uzero = up->pmmu.uzero;
Tos *tos;
ulong utos;
utos = USTKTOP - sizeof(Tos);
diff --git a/src/9vx/devfs-posix.c b/src/9vx/devfs-posix.c
@@ -4,16 +4,23 @@
#include <grp.h> /* going to regret this - getgrgid is a stack smasher */
#include <sys/socket.h>
#include <sys/un.h>
+
#if defined(__FreeBSD__)
-#include <sys/disk.h>
-#include <sys/disklabel.h>
-#include <sys/ioctl.h>
+#include <sys/disk.h>
+#include <sys/disklabel.h>
+#include <sys/ioctl.h>
+#endif
+
+#if defined(__APPLE__)
+#include <sys/disk.h>
#endif
+
#if defined(__linux__)
-#include <linux/hdreg.h>
-#include <linux/fs.h>
-#include <sys/ioctl.h>
+#include <linux/hdreg.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
#endif
+
#include "lib.h"
#include "mem.h"
#include "dat.h"
@@ -907,6 +914,23 @@ disksize(int fd, struct stat *st)
return 0;
}
+#elif defined(__APPLE__)
+
+static vlong
+disksize(int fd, struct stat *st)
+{
+ uvlong bc;
+ unsigned int bs;
+
+ bs = 0;
+ bc = 0;
+ ioctl(fd, DKIOCGETBLOCKSIZE, &bs);
+ ioctl(fd, DKIOCGETBLOCKCOUNT, &bc);
+ if(bs >0 && bc > 0)
+ return bc*bs;
+ return 0;
+}
+
#else
static vlong
diff --git a/src/9vx/main.c b/src/9vx/main.c
@@ -36,7 +36,7 @@ extern Dev drawdevtab;
extern Dev fsdevtab;
extern Dev audiodevtab;
-int doabort;
+int doabort = 1; // for now
char* argv0;
char* conffile = "9vx";
Conf conf;
@@ -49,6 +49,7 @@ static Mach mach0;
extern char* localroot;
extern int tracemmu;
extern int tracekdev;
+extern int nuspace;
static int singlethread;
static void bootinit(void);
@@ -109,6 +110,9 @@ main(int argc, char **argv)
case 'S':
tracesyscalls++;
break;
+ case 'U':
+ nuspace = atoi(EARGF(usage()));
+ break;
case 'X':
vx32_debugxlate++;
break;
@@ -419,7 +423,9 @@ showexec(ulong sp)
{
ulong *a, *argv;
int i, n;
+ uchar *uzero;
+ uzero = up->pmmu.uzero;
iprint("showexec %p\n", sp);
if(sp >= USTKTOP || sp < USTKTOP-USTKSIZE)
panic("showexec: bad sp");
@@ -510,6 +516,7 @@ sigsegv(int signo, siginfo_t *info, void *v)
int read;
ulong addr, eip, esp;
ucontext_t *uc;
+ uchar *uzero;
if(m == nil)
panic("sigsegv: m == nil");
@@ -518,6 +525,8 @@ sigsegv(int signo, siginfo_t *info, void *v)
if(up == nil)
panic("sigsegv: up == nil");
+ uzero = up->pmmu.uzero;
+
uc = v;
#if defined(__APPLE__)
mcontext_t mc;
diff --git a/src/9vx/mmu.c b/src/9vx/mmu.c
@@ -30,14 +30,19 @@ int tracemmu;
static int pagefile;
static char* pagebase;
-uchar *uzero;
+
+static Uspace uspace[16];
+static Uspace *ulist[nelem(uspace)];
+int nuspace = 1;
int
isuaddr(void *v)
{
uchar *p;
+ uchar *uzero;
p = v;
+ uzero = up->pmmu.uzero;
return uzero <= p && p < uzero+USTKTOP;
}
@@ -46,7 +51,7 @@ isuaddr(void *v)
* The point is to reserve the space so that
* nothing else ends up there later.
*/
-static void
+static void*
mapzero(void)
{
int fd;
@@ -55,20 +60,16 @@ mapzero(void)
/* First try mmaping /dev/zero. Some OS'es don't allow this. */
if((fd = open("/dev/zero", O_RDONLY)) >= 0){
v = mmap(nil, USTKTOP, PROT_NONE, MAP_PRIVATE, fd, 0);
- if(v != MAP_FAILED){
- uzero = v;
- return;
- }
+ if(v != MAP_FAILED)
+ return v;
}
/* Next try an anonymous map. */
v = mmap(nil, USTKTOP, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
- if(v != MAP_FAILED){
- uzero = v;
- return;
- }
-
- panic("mapzero: cannot reserve process address space");
+ if(v != MAP_FAILED)
+ return v;
+
+ return nil;
}
void
@@ -76,8 +77,8 @@ mmuinit(void)
{
char tmp[] = "/var/tmp/9vx.pages.XXXXXX";
void *v;
-
- mapzero();
+ int i;
+
if((pagefile = mkstemp(tmp)) < 0)
panic("mkstemp: %r");
if(ftruncate(pagefile, MEMSIZE) < 0)
@@ -92,6 +93,17 @@ mmuinit(void)
panic("mmap pagefile: %r");
pagebase = v;
+ if(nuspace <= 0)
+ nuspace = 1;
+ if(nuspace > nelem(uspace))
+ nuspace = nelem(uspace);
+ for(i=0; i<nuspace; i++){
+ uspace[i].uzero = mapzero();
+ if(uspace[i].uzero == nil)
+ panic("mmap address space %d", i);
+ ulist[i] = &uspace[i];
+ }
+
conf.mem[0].base = 0;
conf.mem[0].npage = MEMSIZE / BY2PG;
@@ -128,23 +140,15 @@ kunmap(KMap *k)
}
/*
- * The process whose address space we've got mapped.
- * We cache our own copy so that entering the scheduler
- * and coming back out running the same process doesn't
- * cause unnecessary unmapping and remapping.
- */
-static Proc *mmup;
-
-/*
* Flush the current address space.
*/
static void
-mmapflush(void)
+mmapflush(Uspace *us)
{
m->flushmmu = 0;
/* Nothing mapped? */
- if(mmup == nil || mmup->pmmu.lo > mmup->pmmu.hi)
+ if(us == nil || us->lo > us->hi || us->uzero == nil)
return;
#ifdef __FreeBSD__
@@ -154,20 +158,20 @@ mmapflush(void)
* tell whether a page is mapped, so we have to remap
* something with no pages here.
*/
- if(mmap(uzero, mmup->pmmu.hi+BY2PG, PROT_NONE,
+ if(mmap(us->uzero, us->hi+BY2PG, PROT_NONE,
MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) == MAP_FAILED)
panic("mmapflush mmap: %r");
- mmup->pmmu.lo = 0x80000000UL;
- mmup->pmmu.hi = 0;
+ us->lo = 0x80000000UL;
+ us->hi = 0;
return;
}
#endif
/* Clear only as much as got mapped. */
- if(mprotect(uzero, mmup->pmmu.hi+BY2PG, PROT_NONE) < 0)
+ if(mprotect(us->uzero, us->hi+BY2PG, PROT_NONE) < 0)
panic("mmapflush mprotect: %r");
- mmup->pmmu.lo = 0x80000000UL;
- mmup->pmmu.hi = 0;
+ us->lo = 0x80000000UL;
+ us->hi = 0;
}
/*
@@ -178,13 +182,15 @@ void
putmmu(ulong va, ulong pa, Page *p)
{
int prot;
- PMMU *pmmu;
+ Uspace *us;
if(tracemmu || (pa&~(PTEWRITE|PTEVALID)) != p->pa)
print("putmmu va %lux pa %lux p->pa %lux\n", va, pa, p->pa);
assert(p->pa < MEMSIZE && pa < MEMSIZE);
assert(up);
+ us = up->pmmu.us;
+ assert(us);
/* Map the page */
prot = PROT_READ;
@@ -192,21 +198,20 @@ putmmu(ulong va, ulong pa, Page *p)
prot |= PROT_WRITE;
pa &= ~(BY2PG-1);
va &= ~(BY2PG-1);
- if(mmap(uzero+va, BY2PG, prot, MAP_FIXED|MAP_SHARED,
+ if(mmap(us->uzero+va, BY2PG, prot, MAP_FIXED|MAP_SHARED,
pagefile, pa) == MAP_FAILED)
panic("putmmu");
/* Record high and low address range for quick unmap. */
- pmmu = &up->pmmu;
- if(pmmu->lo > va)
- pmmu->lo = va;
- if(pmmu->hi < va)
- pmmu->hi = va;
+ if(us->lo > va)
+ us->lo = va;
+ if(us->hi < va)
+ us->hi = va;
// printlinuxmaps();
}
/*
- * The memory maps have changed. Flush all cached state.
+ * The memory maps have changed for up. Flush all cached state.
*/
void
flushmmu(void)
@@ -214,9 +219,78 @@ flushmmu(void)
if(tracemmu)
print("flushmmu\n");
- if(up)
+ if(up){
vxproc_flush(up->pmmu.vxproc);
- mmapflush();
+ mmapflush(up->pmmu.us);
+ }
+}
+
+void
+usespace(Uspace *us)
+{
+ int i;
+
+ for(i=0; i<nuspace; i++)
+ if(ulist[i] == us){
+ while(i > 0){
+ ulist[i] = ulist[i-1];
+ i--;
+ }
+ ulist[0] = us;
+ break;
+ }
+}
+
+Uspace*
+getspace(Proc *p)
+{
+ Uspace *us;
+
+ us = ulist[nuspace-1];
+ if(us->p){
+ if(tracemmu)
+ print("^^^^^^^^^^ %ld %s [evict %d]\n", us->p->pid, us->p->text, us - uspace);
+ mmapflush(us);
+ }
+ us->p = p;
+ p->pmmu.vxmm.base = us->uzero;
+ p->pmmu.uzero = us->uzero;
+ p->pmmu.us = us;
+ usespace(us);
+ return us;
+}
+
+void
+takespace(Proc *p, Uspace *us)
+{
+ usespace(us);
+ if(us->p == p)
+ return;
+ if(tracemmu){
+ if(us->p)
+ print("^^^^^^^^^^ %ld %s [steal %d]\n", us->p->pid, us->p->text, us - uspace);
+ }
+ us->p = p;
+ mmapflush(us);
+}
+
+void
+putspace(Uspace *us)
+{
+ int i;
+
+ mmapflush(us);
+ us->p->pmmu.us = nil;
+ us->p->pmmu.uzero = nil;
+ us->p->pmmu.vxmm.base = nil;
+ us->p = nil;
+ for(i=0; i<nuspace; i++)
+ if(ulist[i] == us){
+ while(++i < nuspace)
+ ulist[i-1] = ulist[i];
+ ulist[i-1] = us;
+ break;
+ }
}
/*
@@ -231,15 +305,31 @@ mmuswitch(Proc *p)
* one we were just in. Also, kprocs don't count --
* only the guys on cpu0 do.
*/
- if(!p->kp && (mmup != p || p->newtlb || m->flushmmu)){
- if(0) print("^^^^^^^^^^ %ld %s\n========== %ld %s\n",
- mmup ? mmup->pid : 0, mmup? mmup->text : "",
- p->pid, p->text);
- /* No vxproc_flush - vxproc cache is okay */
- mmapflush();
+ if(p->kp)
+ return;
+
+ if(tracemmu)
+ print("mmuswitch %ld %s\n", p->pid, p->text);
+
+ if(p->pmmu.us && p->pmmu.us->p == p){
+ if(tracemmu) print("---------- %ld %s [%d]\n",
+ p->pid, p->text, p->pmmu.us - uspace);
+ usespace(p->pmmu.us);
+ if(!p->newtlb && !m->flushmmu){
+ usespace(p->pmmu.us);
+ return;
+ }
+ mmapflush(p->pmmu.us);
p->newtlb = 0;
- mmup = p;
+ return;
}
+
+ if(p->pmmu.us == nil)
+ getspace(p);
+ else
+ takespace(p, p->pmmu.us);
+ if(tracemmu) print("========== %ld %s [%d]\n",
+ p->pid, p->text, p->pmmu.us - uspace);
}
/*
@@ -250,11 +340,16 @@ mmurelease(Proc *p)
{
if(p->kp)
return;
+ if(tracemmu)
+ print("mmurelease %ld %s\n", p->pid, p->text);
if(p->pmmu.vxproc)
vxproc_flush(p->pmmu.vxproc);
- if(p == mmup || m->flushmmu){
- mmapflush();
- mmup = nil;
+ if(p->pmmu.us){
+ if(tracemmu)
+ print("^^^^^^^^^^ %ld %s [release %d]\n", p->pid, p->text, p->pmmu.us - uspace);
+ putspace(p->pmmu.us);
+ if(m->flushmmu)
+ mmapflush(p->pmmu.us);
}
}
diff --git a/src/9vx/osx/screen.c b/src/9vx/osx/screen.c
@@ -316,7 +316,7 @@ mouseevent(EventRef event)
return eventNotHandledErr;
}
- mousetrack(osx.xy.x, osx.xy.y, osx.buttons|osx.kbuttons, msec());
+ mousetrack(osx.xy.x, osx.xy.y, osx.buttons|osx.kbuttons|wheel, msec());
return noErr;
}
@@ -407,6 +407,15 @@ kbdevent(EventRef event)
k = keycvt[code];
if(k >= 0)
latin1putc(k, kputc);
+ else{
+ UniChar uc;
+ OSStatus s;
+
+ s = GetEventParameter(event, kEventParamKeyUnicodes,
+ typeUnicodeText, nil, sizeof uc, nil, &uc);
+ if(s == noErr)
+ kputc(uc);
+ }
break;
case kEventRawKeyModifiersChanged:
@@ -501,6 +510,7 @@ fullscreen(void)
{
static Ptr restore;
static WindowRef oldwindow;
+ GDHandle device;
if(osx.isfullscreen){
EndFullScreen(restore, 0);
@@ -510,7 +520,8 @@ fullscreen(void)
}else{
HideWindow(osx.window);
oldwindow = osx.window;
- BeginFullScreen(&restore, 0, 0, 0, &osx.window, 0, 0);
+ GetWindowGreatestAreaDevice(osx.window, kWindowTitleBarRgn, &device, nil);
+ BeginFullScreen(&restore, device, 0, 0, &osx.window, 0, 0);
osx.isfullscreen = 1;
osx.fullscreentime = msec();
}
diff --git a/src/9vx/sched.c b/src/9vx/sched.c
@@ -61,7 +61,7 @@ noidlehands(void)
if(m->machno == 0)
return;
plock(&idling);
- idlewakeup++;
+ idlewakeup = 1;
pwakeup(&idling);
punlock(&idling);
}
@@ -154,7 +154,8 @@ runproc(void)
kprocq.tail = nil;
kprocq.n--;
if(traceprocs)
- iprint("cpu%d: runproc %ld %s [%d %d]\n", m->machno, p->pid, p->text, kprocq.n, nrunproc);
+ iprint("cpu%d: runproc %ld %s [%d %d]\n",
+ m->machno, p->pid, p->text, kprocq.n, nrunproc);
unlock(&kprocq.lk);
punlock(&run);
return p;
@@ -162,48 +163,8 @@ runproc(void)
/*
* Host OS process sleep and wakeup.
- * This is complicated.
- *
- * Ideally, we'd just use a single pthread_cond_t, have everyone
- * pthread_cond_wait on it, and use pthread_cond_signal
- * to wake people up. Unfortunately, that fails miserably
- * on OS X: sometimes the wakeups just plain get missed.
- * Perhaps it has something to do with all the signals that
- * are flying around.
- *
- * To work around the OS X pthreads problems, there is a
- * second implementation turned on by #defining PIPES to 1.
- * This implementation uses a pipe and reads and writes bytes
- * from the pipe to implement sleep and wakeup. Perhaps not
- * surprisingly, the naive implementation of this hangs:
- * reads miss writes. Instead, the actual implementation uses
- * select to poll whether the read would succeed, and once a
- * second it tries the read even if select doesn't think it will.
- * This timeout lets us make progress when an event gets missed
- * (happens only rarely). This is enough to get things going on
- * OS X.
- *
- * On my Athlon 64 running Linux,
- * time to run mk -a in /sys/src/9/pc:
- *
- * 90s default implementation (one pthread_cond_t)
- * 85s WAITERS (pthread_cond_t for each waiter)
- * 88s PIPES
- *
- * I implemented per-thread pthread_cond_t's to see if they
- * were any faster on non-OS X systems, but I can't see any
- * difference. Running the WAITERS version on OS X causes
- * mysterious crashes. I'm thoroughly confused.
*/
-#define PIPES 0
-#define WAITERS 1
-
-#ifdef __APPLE__
-#undef PIPES
-#define PIPES 1
-#undef WAITERS
-#define WAITERS 0
-#endif
+static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER;
struct Pwaiter
{
@@ -215,78 +176,59 @@ struct Pwaiter
void
plock(Psleep *p)
{
- pthread_mutex_lock(&p->mutex);
- if(!p->condinit){
- p->condinit = 1;
- pthread_cond_init(&p->cond, nil);
- }
-#if PIPES
- if(p->fd[1] == 0){
- pipe(p->fd);
- fcntl(p->fd[0], F_SETFL, fcntl(p->fd[0], F_GETFL)|O_NONBLOCK);
+ int r;
+
+ if(!p->init){
+ if((r = pthread_mutex_lock(&initmutex)) != 0)
+ panic("pthread_mutex_lock initmutex: %d", r);
+ if(!p->init){
+ p->init = 1;
+ pthread_mutex_init(&p->mutex, nil);
+ }
+ if((r = pthread_mutex_unlock(&initmutex)) != 0)
+ panic("pthread_mutex_unlock initmutex: %d", r);
}
-#endif
+ if((r = pthread_mutex_lock(&p->mutex)) != 0)
+ panic("pthread_mutex_lock: %d", r);
}
void
punlock(Psleep *p)
{
- pthread_mutex_unlock(&p->mutex);
+ int r;
+
+ if((r = pthread_mutex_unlock(&p->mutex)) != 0)
+ panic("pthread_mutex_unlock: %d", r);
}
void
psleep(Psleep *p)
{
-#if PIPES
- p->nread++;
- punlock(p);
- char c;
- while(read(p->fd[0], &c, 1) < 1){
- struct pollfd pfd;
- pfd.fd = p->fd[0];
- pfd.events = POLLIN;
- pfd.revents = 0;
- poll(&pfd, 1, 1000);
- }
- plock(p);
-#elif WAITERS
+ int r;
Pwaiter w;
+
memset(&w, 0, sizeof w);
pthread_cond_init(&w.cond, nil);
w.next = p->waiter;
p->waiter = &w;
while(!w.awake)
- pthread_cond_wait(&w.cond, &p->mutex);
+ if((r = pthread_cond_wait(&w.cond, &p->mutex)) != 0)
+ panic("pthread_cond_wait: %d", r);
pthread_cond_destroy(&w.cond);
-#else
- pthread_cond_wait(&p->cond, &p->mutex);
-#endif
}
void
pwakeup(Psleep *p)
{
-#if PIPES
- char c = 0;
- int nbad = 0;
- if(p->nwrite < p->nread){
- p->nwrite++;
- while(write(p->fd[1], &c, 1) < 1){
- if(++nbad%100 == 0)
- iprint("pwakeup: write keeps failing\n");
- }
- }
-#elif WAITERS
+ int r;
Pwaiter *w;
w = p->waiter;
if(w){
p->waiter = w->next;
w->awake = 1;
- pthread_cond_signal(&w->cond);
+ if((r = pthread_cond_signal(&w->cond)) != 0)
+ panic("pthread_cond_signal: %d", r);
}
-#else
- pthread_cond_signal(&p->cond);
-#endif
}
diff --git a/src/9vx/stub.c b/src/9vx/stub.c
@@ -276,18 +276,19 @@ _tas(void *x)
int
lock(Lock *lk)
{
- int i, printed;
+ int i, j, printed;
for(i=0; i<1000; i++){
if(canlock(lk))
return 1;
sched_yield();
}
- for(i=0; i<100; i++){
- if(canlock(lk))
- return 1;
- microdelay(10);
- }
+ for(j=10; j<=1000; j*=10)
+ for(i=0; i<10; i++){
+ if(canlock(lk))
+ return 1;
+ microdelay(j);
+ }
printed = 0;
for(;;){
if(canlock(lk))
@@ -295,7 +296,7 @@ lock(Lock *lk)
if(!printed++)
iprint("cpu%d deadlock? %p caller=%p\n",
m->machno, lk, getcallerpc(&lk));
- microdelay(1000000);
+ microdelay(10000);
}
return 0;
}
@@ -497,11 +498,14 @@ panic(char *fmt, ...)
buf[n] = '\n';
write(2, buf, n+1);
if(doabort){
-#ifndef __APPLE__
- abort();
-#endif
+#ifdef __APPLE__
+ fprint(2, "sleeping, so you can attach gdb to pid %d\n", (int)getpid());
for(;;)
microdelay(1000000);
+#else
+ fprint(2, "aborting, to dump core.\n");
+ abort();
+#endif
}
exit(0);
}
diff --git a/src/9vx/term.c b/src/9vx/term.c
@@ -208,6 +208,7 @@ termscroll(void)
r1.min.y += dy;
memimagedraw(term.screen, r0, term.screen, r1.min,
memopaque, ZP, S);
+ r1.min.y = r0.max.y;
memimagedraw(term.screen, r1, term.bg, ZP, memopaque, ZP, S);
addflush(r0);
addflush(r1);
diff --git a/src/9vx/trap.c b/src/9vx/trap.c
@@ -30,7 +30,7 @@ kexit(Ureg *ureg)
Tos *tos;
/* precise time accounting, kernel exit */
- tos = (Tos*)(uzero+USTKTOP-sizeof(Tos));
+ tos = (Tos*)(up->pmmu.uzero+USTKTOP-sizeof(Tos));
cycles(&t);
tos->kcycles += t - up->kentry;
tos->pcycles = up->pcycles;
@@ -90,7 +90,7 @@ trap(Ureg *ureg)
case VXTRAP_SOFT+0x40: /* int $0x40 - system call */
if(tracesyscalls){
- ulong *sp = (ulong*)(uzero + ureg->usp);
+ ulong *sp = (ulong*)(up->pmmu.uzero + ureg->usp);
print("%d [%s] %s %#lux %08lux %08lux %08lux %08lux\n",
up->pid, up->text,
sysctab[ureg->ax], sp[0], sp[1], sp[2], sp[3]);
@@ -262,7 +262,7 @@ syscall(Ureg *ureg)
up->psstate = 0;
if(scallnr == NOTED)
- noted(ureg, *(ulong*)(uzero + sp+BY2WD));
+ noted(ureg, *(ulong*)(up->pmmu.uzero + sp+BY2WD));
if(scallnr!=RFORK && (up->procctl || up->nnote)){
splhi();
@@ -335,6 +335,8 @@ notify(Ureg* ureg)
pexit("Suicide", 0);
}
+ uchar *uzero;
+ uzero = up->pmmu.uzero;
upureg = (void*)(uzero + sp);
memmove(upureg, ureg, sizeof(Ureg));
*(ulong*)(uzero + sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
@@ -383,6 +385,8 @@ noted(Ureg* ureg, ulong arg0)
pexit("Suicide", 0);
}
+ uchar *uzero;
+ uzero = up->pmmu.uzero;
oureg = up->ureg;
nureg = (Ureg*)(uzero + up->ureg);
@@ -442,11 +446,11 @@ execregs(ulong entry, ulong ssize, ulong nargs)
up->fpstate = FPinit;
fpoff();
- sp = (ulong*)(uzero + USTKTOP - ssize);
+ sp = (ulong*)(up->pmmu.uzero + USTKTOP - ssize);
*--sp = nargs;
ureg = up->dbgreg;
- ureg->usp = (uchar*)sp - uzero;
+ ureg->usp = (uchar*)sp - up->pmmu.uzero;
//showexec(ureg->usp);
ureg->pc = entry;
return USTKTOP-sizeof(Tos); /* address of kernel/user shared data */
diff --git a/src/9vx/vx32.c b/src/9vx/vx32.c
@@ -17,7 +17,6 @@
#include "u.h"
#include <pthread.h>
#include <sys/mman.h>
-#include "libvx32/vx32.h"
#include "lib.h"
#include "mem.h"
#include "dat.h"
@@ -50,47 +49,6 @@ vx32sysr1(void)
}
/*
- * Vxnewproc is called at the end of newproc
- * to fill in vx32-specific entries in the Proc struct
- * before it gets used.
- */
-void
-vxnewproc(Proc *p)
-{
- PMMU *pm;
-
- pm = &p->pmmu;
-
- /*
- * Kernel procs don't need vxprocs; if this proc
- * already has one, take it away. Also, give
- * kernel procs very large stacks so they can call
- * into non-thread-friendly routines like x11
- * and getgrgid.
- */
- if(p->kp){
- if(pm->vxproc){
- pm->vxproc->mem = nil;
- vxproc_free(pm->vxproc);
- pm->vxproc = nil;
- }
- free(p->kstack);
- p->kstack = nil;
- p->kstack = smalloc(512*1024);
- return;
- }
-
- pm->lo = 0x80000000UL;
- pm->hi = 0;
- if(pm->vxproc == nil){
- pm->vxproc = vxproc_alloc();
- if(pm->vxproc == nil)
- panic("vxproc_alloc");
- pm->vxproc->mem = &thevxmem;
- }
-}
-
-/*
* Vx32 hooks to read, write, map, unmap, and check permissions
* on user memory. Normally these are more involved, but we're
* using the processor to do everything.
@@ -98,29 +56,21 @@ vxnewproc(Proc *p)
static ssize_t
vmread(vxmem *vm, void *data, uint32_t addr, uint32_t len)
{
- memmove(data, uzero+addr, len);
+ memmove(data, vm->mapped->base+addr, len);
return len;
}
static ssize_t
vmwrite(vxmem *vm, const void *data, uint32_t addr, uint32_t len)
{
- memmove(uzero+addr, data, len);
+ memmove(vm->mapped->base+addr, data, len);
return len;
}
-static vxmmap thevxmmap =
-{
- 1,
- (void*)-1, /* to be filled in with user0 */
- USTKTOP,
-};
-
static vxmmap*
vmmap(vxmem *vm, uint32_t flags)
{
- thevxmmap.base = uzero;
- return &thevxmmap;
+ return vm->mapped;
}
static void
@@ -131,6 +81,14 @@ vmunmap(vxmem *vm, vxmmap *mm)
static int
vmcheckperm(vxmem *vm, uint32_t addr, uint32_t len, uint32_t perm, uint32_t *out_faultva)
{
+ if(addr >= USTKTOP){
+ *out_faultva = addr;
+ return 0;
+ }
+ if(addr+len < addr || addr +len > USTKTOP){
+ *out_faultva = USTKTOP;
+ return 0;
+ }
/* All is allowed - handle faults as they happen. */
return 1;
}
@@ -164,6 +122,50 @@ static vxmem thevxmem =
vmfree,
};
+/*
+ * Vxnewproc is called at the end of newproc
+ * to fill in vx32-specific entries in the Proc struct
+ * before it gets used.
+ */
+void
+vxnewproc(Proc *p)
+{
+ PMMU *pm;
+
+ pm = &p->pmmu;
+
+ /*
+ * Kernel procs don't need vxprocs; if this proc
+ * already has one, take it away. Also, give
+ * kernel procs very large stacks so they can call
+ * into non-thread-friendly routines like x11
+ * and getgrgid.
+ */
+ if(p->kp){
+ if(pm->vxproc){
+ // vxunmap(p);
+ assert(pm->uzero == nil);
+ pm->vxproc->mem = nil;
+ vxproc_free(pm->vxproc);
+ pm->vxproc = nil;
+ }
+ free(p->kstack);
+ p->kstack = nil;
+ p->kstack = smalloc(512*1024);
+ return;
+ }
+
+ if(pm->vxproc == nil){
+ pm->vxproc = vxproc_alloc();
+ if(pm->vxproc == nil)
+ panic("vxproc_alloc");
+ pm->vxproc->mem = &pm->vxmem;
+ pm->vxmem = thevxmem;
+ pm->vxmem.mapped = &pm->vxmm;
+ memset(&pm->vxmm, 0, sizeof pm->vxmm);
+ }
+}
+
static void
setclock(int start)
{
@@ -224,7 +226,7 @@ touser(void *initsp)
* Optimization: try to fault in code page and stack
* page right now, since we're likely to need them.
*/
- if(up->pmmu.hi == 0){
+ if(up->pmmu.us->hi == 0){
fault(vp->cpu->eip, 1);
fault(vp->cpu->reg[ESP], 0);
}
@@ -267,11 +269,11 @@ touser(void *initsp)
addr = (uchar*)vp->cpu->trapva;
if(traceprocs)
print("fault %p read=%d\n", addr, read);
- if(isuaddr(addr) && fault(addr - uzero, read) >= 0)
+ if(isuaddr(addr) && fault(addr - up->pmmu.uzero, read) >= 0)
continue;
print("%ld %s: unhandled fault va=%lux [%lux] eip=%lux\n",
up->pid, up->text,
- addr - uzero, vp->cpu->trapva, vp->cpu->eip);
+ addr - up->pmmu.uzero, vp->cpu->trapva, vp->cpu->eip);
proc2ureg(vp, &u);
dumpregs(&u);
if(doabort)
diff --git a/src/BUGS b/src/BUGS
@@ -9,6 +9,4 @@ need to do a better job mapping SIGFPE back to hardware floating-point errors
---
gs spins on startup, cause unknown. (run "gs", no arguments)
-blank line inserted when kernel terminal scrolls
-
can cause sigsegv panic resizing the window, rarely