From 9d669d4b3256f89b71098bfc5ee2467f27af03dc Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 15 Oct 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-10-15 --- bitsy/clock.c | 28 ++- bitsy/dat.h | 5 +- bitsy/devsac.c | 530 ++++++++++++++++++++++++++++++++++++++++++++++++ bitsy/devuart.c | 199 +++++++++++++++++- bitsy/fns.h | 14 +- bitsy/io.h | 3 +- bitsy/l.s | 27 +-- bitsy/main.c | 17 +- bitsy/mmu.c | 77 +++++-- bitsy/screen.c | 6 + bitsy/trap.c | 49 ++--- 11 files changed, 875 insertions(+), 80 deletions(-) create mode 100644 bitsy/devsac.c diff --git a/bitsy/clock.c b/bitsy/clock.c index 284f9e50fb56d24638c601e3abf48c10869e1ae7..11ef0713fbe2ee44340c8e99f077f65a71810909 100644 --- a/bitsy/clock.c +++ b/bitsy/clock.c @@ -69,8 +69,10 @@ fastticks(uvlong *hz) } static void -clockintr(Ureg*, void*) +clockintr(Ureg *ureg, void*) { + Clock0link *lp; + /* reset previous interrupt */ timerregs->ossr |= 1<<0; @@ -78,6 +80,30 @@ clockintr(Ureg*, void*) timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ; m->ticks++; + + if(m->proc) + m->proc->pc = ureg->pc; + + accounttime(); + if(kproftimer != nil) + kproftimer(ureg->pc); + + checkalarms(); + ilock(&clock0lock); + for(lp = clock0link; lp; lp = lp->link) + lp->clock(); + iunlock(&clock0lock); + + if(up == 0 || up->state != Running) + return; + + if(anyready()) + sched(); + + if((ureg->psr & PsrMask) == PsrMusr) { + (*(ulong*)(USTKTOP-BY2WD)) += TK2MS(1); + segclock(ureg->pc); + } } void diff --git a/bitsy/dat.h b/bitsy/dat.h index 32bc43dd0deeb85ad2a1694e2e6bb0b4a799326f..0cf9966ef37503f977da7ab3097ef17eb9d067d9 100644 --- a/bitsy/dat.h +++ b/bitsy/dat.h @@ -16,7 +16,7 @@ typedef struct Uart Uart; /* * parameters for sysproc.c */ -#define AOUT_MAGIC (I_MAGIC) +#define AOUT_MAGIC (E_MAGIC) struct Lock { @@ -82,6 +82,7 @@ struct PMMU { Page *l1page[Nmeg]; /* this's process' level 1 entries */ ulong l1table[Nmeg]; /* ... */ + Page *mmufree; /* free mmu pages */ }; /* @@ -167,7 +168,7 @@ struct int ispanic; /* shutdown in response to a panic */ }active; -#define MACHP(n) ((Mach*)MACHADDR) +#define MACHP(n) ((Mach *)(MACHADDR+(n)*BY2PG)) extern Mach *m; #define up (((Mach*)MACHADDR)->externup) diff --git a/bitsy/devsac.c b/bitsy/devsac.c new file mode 100644 index 0000000000000000000000000000000000000000..3ee3e104e9f7abb950d6079d3cfd59bfd51c2d95 --- /dev/null +++ b/bitsy/devsac.c @@ -0,0 +1,530 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" + +enum +{ + OPERM = 0x3, /* mask of all permission types in open mode */ + Nram = 512, + CacheSize = 20, + OffsetSize = 4, /* size in bytes of an offset */ +}; + +typedef struct SacPath SacPath; +typedef struct Sac Sac; +typedef struct SacHeader SacHeader; +typedef struct SacDir SacDir; +typedef struct Cache Cache; + +enum { + Magic = 0x5acf5, +}; + +struct SacDir +{ + char name[NAMELEN]; + char uid[NAMELEN]; + char gid[NAMELEN]; + uchar qid[4]; + uchar mode[4]; + uchar atime[4]; + uchar mtime[4]; + uchar length[8]; + uchar blocks[8]; +}; + +struct SacHeader +{ + uchar magic[4]; + uchar length[8]; + uchar blocksize[4]; + uchar md5[16]; +}; + + +struct Sac +{ + SacDir; + SacPath *path; +}; + +struct SacPath +{ + Ref; + SacPath *up; + long blocks; + int entry; + int nentry; +}; + +struct Cache +{ + long block; + ulong age; + uchar *data; +}; + +enum +{ + Pexec = 1, + Pwrite = 2, + Pread = 4, + Pother = 1, + Pgroup = 8, + Powner = 64, +}; + +static char *sacfs = "fs.sac"; +static uchar *data; +static int blocksize; +static Sac root; +static Cache cache[CacheSize]; +static ulong cacheage; + +static void sacdir(Chan *, SacDir*, char*); +static ulong getl(void *p); +static Sac *saccpy(Sac *s); +static Sac *saclookup(Sac *s, char *name); +static int sacdirread(Chan *, char *p, long off, long cnt); +static void loadblock(void *buf, uchar *offset, int blocksize); +static void sacfree(Sac*); + +static void +sacinit(void) +{ + SacHeader *hdr; + uchar *p; + char *s; + int i; + +print("sacinit\n"); + s = getconf("flash"); + if(s == nil) { + print("devsac: no flash file system\n"); + return; + } + + p = (uchar*)strtoul(s, 0, 0); + if(p == 0) { + print("devsac: bad address for flash file system\n"); + return; + } + data = tarlookup(p, sacfs, &i); + if(data == 0) { + print("devsac: could not find file: %s\n", sacfs); + return; + } + hdr = (SacHeader*)data; + if(getl(hdr->magic) != Magic) { +print("devsac: bad magic\n"); + return; + } + blocksize = getl(hdr->blocksize); + root.SacDir = *(SacDir*)(data + sizeof(SacHeader)); + p = malloc(CacheSize*blocksize); + if(p == nil) + error("allocating cache"); + for(i=0; iqid = (Qid){getl(root.qid), 0}; + c->dev = dev; + c->aux = saccpy(&root); + return c; +} + +static Chan* +sacclone(Chan *c, Chan *nc) +{ + nc = devclone(c, nc); + nc->aux = saccpy(c->aux); + return nc; +} + +static int +sacwalk(Chan *c, char *name) +{ + Sac *sac; + +//print("walk %s\n", name); + + isdir(c); + if(name[0]=='.' && name[1]==0) + return 1; + if(name[0]=='.' && name[1]=='.' && name[2]==0) + return 1; + sac = c->aux; + sac = saclookup(sac, name); + if(sac == nil) { + strncpy(up->error, Enonexist, NAMELEN); + return 0; + } + c->aux = sac; + c->qid = (Qid){getl(sac->qid), 0}; + return 1; +} + +static Chan* +sacopen(Chan *c, int omode) +{ + ulong t, mode; + Sac *sac; + static int access[] = { 0400, 0200, 0600, 0100 }; + + sac = c->aux; + mode = getl(sac->mode); + if(strcmp(up->user, sac->uid) == 0) + mode = mode; + else if(strcmp(up->user, sac->gid) == 0) + mode = mode<<3; + else + mode = mode<<6; + + t = access[omode&3]; + if((t & mode) != t) + error(Eperm); + c->offset = 0; + c->mode = openmode(omode); + c->flag |= COPEN; + return c; +} + + +static long +sacread(Chan *c, void *a, long n, vlong voff) +{ + Sac *sac; + char *buf, *buf2; + int nn, cnt, i, j; + uchar *blocks; + long length; + long off = voff; + + buf = a; + cnt = n; + if(c->qid.path & CHDIR){ + cnt = (cnt/DIRLEN)*DIRLEN; + if(off%DIRLEN) + error("i/o error"); + return sacdirread(c, buf, off, cnt); + } + sac = c->aux; + length = getl(sac->length); + if(off >= length) + return 0; + if(cnt > length-off) + cnt = length-off; + if(cnt == 0) + return 0; + n = cnt; + blocks = data + getl(sac->blocks); + buf2 = malloc(blocksize); + while(cnt > 0) { + i = off/blocksize; + nn = blocksize; + if(nn > length-i*blocksize) + nn = length-i*blocksize; + loadblock(buf2, blocks+i*OffsetSize, nn); + j = off-i*blocksize; + nn -= j; + if(nn > cnt) + nn = cnt; + memmove(buf, buf2+j, nn); + cnt -= nn; + off += nn; + buf += nn; + } + free(buf2); + return n; +} + +static long +sacwrite(Chan *, void *, long, vlong) +{ + error(Eperm); + return 0; +} + +static void +sacclose(Chan* c) +{ + Sac *sac = c->aux; + c->aux = nil; + sacfree(sac); +} + + +static void +sacstat(Chan *c, char *db) +{ + sacdir(c, c->aux, db); +} + +static Sac* +saccpy(Sac *s) +{ + Sac *ss; + + ss = malloc(sizeof(Sac)); + *ss = *s; + if(ss->path) + incref(ss->path); + return ss; +} + +static SacPath * +sacpathalloc(SacPath *p, long blocks, int entry, int nentry) +{ + SacPath *pp = malloc(sizeof(SacPath)); + pp->ref = 1; + pp->blocks = blocks; + pp->entry = entry; + pp->nentry = nentry; + pp->up = p; + return pp; +} + +static void +sacpathfree(SacPath *p) +{ + if(p == nil) + return; + if(decref(p) > 0) + return; + sacpathfree(p->up); + free(p); +} + + +static void +sacfree(Sac *s) +{ + sacpathfree(s->path); + free(s); +} + +static void +sacdir(Chan *c, SacDir *s, char *buf) +{ + Dir dir; + + memmove(dir.name, s->name, NAMELEN); + dir.qid = (Qid){getl(s->qid), 0}; + dir.mode = getl(s->mode); + dir.length = getl(s->length); + if(dir.mode &CHDIR) + dir.length *= DIRLEN; + memmove(dir.uid, s->uid, NAMELEN); + memmove(dir.gid, s->gid, NAMELEN); + dir.atime = getl(s->atime); + dir.mtime = getl(s->mtime); + dir.type = devtab[c->type]->dc; + dir.dev = c->dev; + convD2M(&dir, buf); +} + +static void +loadblock(void *buf, uchar *offset, int blocksize) +{ + long block, n; + ulong age; + int i, j; + + block = getl(offset); + if(block < 0) { + block = -block; + cacheage++; + // age has wraped + if(cacheage == 0) { + for(i=0; ipath; + if(p == nil || p->up == nil) { + sacpathfree(p); + *s = root; + return s; + } + p = p->up; + + blocks = data + p->blocks; + per = blocksize/sizeof(SacDir); + i = p->entry/per; + n = per; + if(n > p->nentry-i*per) + n = p->nentry-i*per; + buf = malloc(per*sizeof(SacDir)); + loadblock(buf, blocks + i*OffsetSize, n*sizeof(SacDir)); + s->SacDir = buf[p->entry-i*per]; + free(buf); + incref(p); + sacpathfree(s->path); + s->path = p; + return s; +} + +static int +sacdirread(Chan *c, char *p, long off, long cnt) +{ + uchar *blocks; + SacDir *buf; + int iblock, per, i, j, n, ndir; + Sac *s; + + s = c->aux; + blocks = data + getl(s->blocks); + per = blocksize/sizeof(SacDir); + ndir = getl(s->length); + off /= DIRLEN; + cnt /= DIRLEN; + if(off >= ndir) + return 0; + if(cnt > ndir-off) + cnt = ndir-off; + iblock = -1; + buf = malloc(per*sizeof(SacDir)); + for(i=off; i ndir-j*per) + n = ndir-j*per; + loadblock(buf, blocks + j*OffsetSize, n*sizeof(SacDir)); + iblock = j; + } + j *= per; + sacdir(c, buf+i-j, p); + p += DIRLEN; + } + free(buf); + return cnt*DIRLEN; +} + +static Sac* +saclookup(Sac *s, char *name) +{ + int ndir; + int i, j, k, n, per; + uchar *blocks; + SacDir *buf; + int iblock; + SacDir *sd; + + if(strcmp(name, "..") == 0) + return sacparent(s); + blocks = data + getl(s->blocks); + per = blocksize/sizeof(SacDir); + ndir = getl(s->length); + buf = malloc(per*sizeof(SacDir)); + iblock = -1; + + // linear search + for(i=0; i ndir-j*per) + n = ndir-j*per; + loadblock(buf, blocks + j*OffsetSize, n*sizeof(SacDir)); + iblock = j; + } + j *= per; + sd = buf+i-j; + k = strcmp(name, sd->name); + if(k == 0) { + s->path = sacpathalloc(s->path, getl(s->blocks), i, ndir); + s->SacDir = *sd; + free(buf); + return s; + } + } + free(buf); + return 0; +} + +static ulong +getl(void *p) +{ + uchar *a = p; + + return (a[0]<<24) | (a[1]<<16) | (a[2]<<8) | a[3]; +} + +Dev sacdevtab = { + 'C', + "sac", + + devreset, + sacinit, + sacattach, + sacclone, + sacwalk, + sacstat, + sacopen, + devcreate, + sacclose, + sacread, + devbread, + sacwrite, + devbwrite, + devremove, + devwstat, +}; diff --git a/bitsy/devuart.c b/bitsy/devuart.c index 5b2a275f8248de45c2196e08f65b6055e8ddcf6a..03b6aed570dcf5959e011c8072d7d87af6b2989e 100644 --- a/bitsy/devuart.c +++ b/bitsy/devuart.c @@ -20,9 +20,18 @@ static int uartndir; */ static char Ekinuse[] = "device in use by kernel"; +struct Uartalloc { + Lock; + Uart *elist; /* list of enabled interfaces */ +} uartalloc; + static void uartdcdhup(Uart*, int); static void uartdcdts(Uart*, int); static void uartdsrhup(Uart*, int); +static void uartenable(Uart*); +static void uartdisable(Uart*); +static void uartclock(void); +static void uartflow(void*); /* * define a Uart @@ -54,8 +63,8 @@ uartsetup(PhysUart *phys, void *regs, ulong freq, char *name) (*p->phys->baud)(p, 115200); (*p->phys->enable)(p, 0); - p->iq = qopen(4*1024, 0, p->phys->flow, p); - p->oq = qopen(4*1024, 0, p->phys->kick, p); + p->iq = qopen(4*1024, 0, uartflow, p); + p->oq = qopen(4*1024, 0, uartkick, p); if(p->iq == nil || p->oq == nil) panic("uartsetup"); @@ -66,6 +75,52 @@ uartsetup(PhysUart *phys, void *regs, ulong freq, char *name) return p; } +/* + * enable/diable uart and add/remove to list of enabled uarts + */ +static void +uartenable(Uart *p) +{ + Uart **l; + + p->hup_dsr = p->hup_dcd = 0; + p->dsr = p->dcd = 0; + + /* assume we can send */ + p->cts = 1; + + (*p->phys->enable)(p, 1); + + lock(&uartalloc); + for(l = &uartalloc.elist; *l; l = &(*l)->elist){ + if(*l == p) + break; + } + if(*l == 0){ + p->elist = uartalloc.elist; + uartalloc.elist = p; + } + p->enabled = 1; + unlock(&uartalloc); +} +static void +uartdisable(Uart *p) +{ + Uart **l; + + (*p->phys->disable)(p); + + lock(&uartalloc); + for(l = &uartalloc.elist; *l; l = &(*l)->elist){ + if(*l == p){ + *l = p->elist; + break; + } + } + p->enabled = 0; + unlock(&uartalloc); +} + static void setlength(int i) { @@ -109,6 +164,8 @@ uartreset(void) dp->perm = 0444; dp++; } + + addclock0link(uartclock); } @@ -147,7 +204,7 @@ uartopen(Chan *c, int omode) error(Ekinuse); qlock(p); if(p->opens++ == 0){ - (*p->phys->enable)(p, 1); + uartenable(p); qreopen(p->iq); qreopen(p->oq); } @@ -175,7 +232,7 @@ uartclose(Chan *c) error(Ekinuse); qlock(p); if(--(p->opens) == 0){ - (*p->phys->disable)(p); + uartdisable(p); qclose(p->iq); qclose(p->oq); p->ip = p->istage; @@ -399,6 +456,23 @@ uartdcdts(Uart *p, int n) p->dcdts = n; } +/* + * restart input if it's off + */ +static void +uartflow(void *v) +{ + Uart *p; + + p = v; + if(p->modem){ + (*p->phys->rts)(p, 1); + ilock(&p->rlock); + p->haveinput = 1; + iunlock(&p->rlock); + } +} + /* * put some bytes into the local queue to avoid calling * qconsume for every character @@ -415,3 +489,120 @@ uartstageoutput(Uart *p) p->oe = p->ostage + n; return n; } + +/* + * restart output + */ +void +uartkick(void *v) +{ + Uart *p = v; + + ilock(&p->tlock); + (*p->phys->kick)(p); + iunlock(&p->tlock); +} + +/* + * streceiveage a character at interrupt time + */ +void +uartrecv(Uart *p, char ch) +{ + /* software flow control */ + if(p->xonoff){ + if(ch == CTLS){ + p->blocked = 1; + }else if (ch == CTLQ){ + p->blocked = 0; + p->ctsbackoff = 2; /* clock gets output going again */ + } + } + + /* receive the character */ + if(p->putc) + p->putc(p->iq, ch); + else { + ilock(&p->rlock); + if(p->ip < p->ie) + *p->ip++ = ch; + p->haveinput = 1; + iunlock(&p->rlock); + } +} + +/* + * we save up input characters till clock time to reduce + * per character interrupt overhead. + * + * There's also a bit of code to get a stalled print going. + * It shouldn't happen, but it does. Obviously I don't + * understand something. Since it was there, I bundled a + * restart after flow control with it to give some hysteresis + * to the hardware flow control. This makes compressing + * modems happier but will probably bother something else. + * -- presotto + */ +static void +uartclock(void) +{ + int n; + Uart *p; + + for(p = uartalloc.elist; p; p = p->elist){ + + /* this amortizes cost of qproduce to many chars */ + if(p->haveinput){ + ilock(&p->rlock); + if(p->haveinput){ + n = p->ip - p->istage; + if(n > 0 && p->iq){ + if(n > Stagesize) + panic("uartclock"); + if(qproduce(p->iq, p->istage, n) < 0) + (*p->phys->rts)(p, 0); + else + p->ip = p->istage; + } + p->haveinput = 0; + } + iunlock(&p->rlock); + } + if(p->dohup){ + ilock(&p->rlock); + if(p->dohup){ + qhangup(p->iq, 0); + qhangup(p->oq, 0); + } + p->dohup = 0; + iunlock(&p->rlock); + } + + /* this adds hysteresis to hardware/software flow control */ + if(p->ctsbackoff){ + ilock(&p->tlock); + if(p->ctsbackoff){ + if(--(p->ctsbackoff) == 0) + (*p->phys->kick)(p); + } + iunlock(&p->tlock); + } + } +} + +/* + * configure a uart port as a console or a mouse + */ +void +uartspecial(Uart *p, int baud, Queue **in, Queue **out, int (*putc)(Queue*, int)) +{ + uartenable(p); + if(baud) + (*p->phys->baud)(p, baud); + p->putc = putc; + if(in) + *in = p->iq; + if(out) + *out = p->oq; + p->opens++; +} diff --git a/bitsy/fns.h b/bitsy/fns.h index d1001f249495a158597104e01fceba6ada507372..dc7c745685ef8b0bf54f0de082f700ffb5719155 100644 --- a/bitsy/fns.h +++ b/bitsy/fns.h @@ -1,15 +1,13 @@ #include "../port/portfns.h" +void cacheflush(void); +void cacheflushaddr(ulong); int cistrcmp(char*, char*); int cistrncmp(char*, char*, int); -void cleancache(void); -void cleanaddr(ulong); -#define clearmmucache() /* x86 doesn't have one */ void clockinit(void); #define coherence() void delay(int); void evenaddr(ulong); -void flushcache(void); void flushmmu(void); ulong getfar(void); ulong getfsr(void); @@ -28,6 +26,7 @@ void meminit(void); void mmuinit(void); void mmuenable(void); void mmudisable(void); +void mmuinvalidate(void); void noted(Ureg*, ulong); int notify(Ureg*); #define procrestore(p) @@ -40,16 +39,19 @@ void qpanic(char *, ...); void reset(void); void rs232power(int); Uart* uartsetup(PhysUart*, void*, ulong, char*); -void sa1100_uartsetup(void); +void uartspecial(Uart*, int, Queue**, Queue**, int (*)(Queue*, int)); +void sa1100_uartsetup(int); void screeninit(void); int screenprint(char*, ...); /* debugging */ -void (*screenputs)(char*, int); +void screenputs(char*, int); void setr13(int, ulong*); void touser(void*); void trapdump(char *tag); void trapinit(void); int tas(void*); int uartstageoutput(Uart*); +void uartkick(void*); +void uartrecv(Uart*, char); void vectors(void); void vtable(void); void wbflush(void); diff --git a/bitsy/io.h b/bitsy/io.h index ef46f3e213123139f59f771f9451153c30dd9ba2..fa5c8b508141c3d60550a5ceab1cb6472bfa49db 100644 --- a/bitsy/io.h +++ b/bitsy/io.h @@ -98,8 +98,7 @@ struct PhysUart { void (*enable)(Uart*, int); void (*disable)(Uart*); - void (*kick)(void*); - void (*flow)(void*); + void (*kick)(Uart*); void (*intr)(Ureg*, void*); void (*dobreak)(Uart*, int); void (*baud)(Uart*, int); diff --git a/bitsy/l.s b/bitsy/l.s index 290b307a4a3a5f4b3098fc550f6e5f7ea644f4c6..0ce9eaf7dbef3c39724c603e9b8f459b4c8e975f 100644 --- a/bitsy/l.s +++ b/bitsy/l.s @@ -35,12 +35,12 @@ _mainloop: BL _div(SB) /* hack to get _div etc loaded */ /* flush tlb's */ -TEXT flushmmu(SB), $-4 +TEXT mmuinvalidate(SB), $-4 MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x7) RET -/* clean and flush i and d caches */ -TEXT cleancache(SB), $-4 +/* write back and invalidate i and d caches */ +TEXT cacheflush(SB), $-4 /* write back any dirty data */ MOVW $0xe0000000,R0 ADD $(8*1024),R0,R1 @@ -49,7 +49,8 @@ _wbloop: CMP R0,R1 BNE _wbloop - /* flush cache contents */ + /* drain write buffer and flush i&d cache contents */ + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4 MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0 /* drain prefetch */ @@ -60,22 +61,10 @@ _wbloop: RET /* clean a single virtual address */ -TEXT cleanaddr(SB), $-4 +TEXT cacheflushaddr(SB), $-4 MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1 RET -/* flush i and d caches */ -TEXT flushcache(SB), $-4 - /* flush cache contents */ - MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0 - - /* drain prefetch */ - MOVW R0,R0 - MOVW R0,R0 - MOVW R0,R0 - MOVW R0,R0 - RET - /* drain write buffer */ TEXT wbflush(SB), $-4 MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4 @@ -111,13 +100,13 @@ TEXT putttb(SB), $-4 */ TEXT mmuenable(SB), $-4 MRC CpMMU, 0, R0, C(CpControl), C(0x0) - ORR $(CpCmmuena), R0 + ORR $(CpCmmuena|CpCwb|CpCdcache), R0 MCR CpMMU, 0, R0, C(CpControl), C(0x0) RET TEXT mmudisable(SB), $-4 MRC CpMMU, 0, R0, C(CpControl), C(0x0) - BIC $(CpCmmuena|CpCvivec), R0 + BIC $(CpCmmuena|CpCdcache|CpCwb|CpCvivec), R0 MCR CpMMU, 0, R0, C(CpControl), C(0x0) RET diff --git a/bitsy/main.c b/bitsy/main.c index b60eb6c587102ecceec1c6d7868aebcab38bd8d2..90525ddc8b4403b83e6b3811b5e5a16f870ac7b5 100644 --- a/bitsy/main.c +++ b/bitsy/main.c @@ -18,7 +18,7 @@ int noprint; void main(void) { - cleancache(); + mmuinvalidate(); /* zero out bss */ memset(edata, 0, end-edata); @@ -31,22 +31,20 @@ main(void) rs232power(1); iprint("bitsy kernel\n"); confinit(); - iprint("%d pages %lux(%lud) %lux(%lud)\n", conf.npage, conf.base0, conf.npage0, conf.base1, conf.npage1); xinit(); mmuinit(); - sa1100_uartsetup(); gpioinit(); trapinit(); - printinit(); + sa1100_uartsetup(1); + printinit(); /* from here on, print works, before this we need iprint */ clockinit(); procinit0(); initseg(); chandevreset(); -noprint = 1; pageinit(); swapinit(); userinit(); -iprint("schedinit(), death soon\n"); +//iprint("schedinit(), death soon\n"); schedinit(); } @@ -62,6 +60,7 @@ exit(int ispanic) delay(1000); iprint("it's a wonderful day to die\n"); + mmuinvalidate(); mmudisable(); f = nil; (*f)(); @@ -210,7 +209,6 @@ userinit(void) strcpy(p->text, "*init*"); strcpy(p->user, eve); - /* * Kernel Stack */ @@ -239,9 +237,7 @@ userinit(void) k = kmap(s->map[0]->pages[0]); memmove((ulong*)VA(k), initcode, sizeof initcode); kunmap(k); - cleancache(); - wbflush(); -iprint("userinit %lux[0x20] = %lux\n", VA(k), *((ulong*)(VA(k)+0x20))); +//iprint("userinit %lux[0x20] = %lux\n", VA(k), *((ulong*)(VA(k)+0x20))); ready(p); } @@ -361,6 +357,7 @@ confinit(void) conf.upages = (conf.npage*40)/100; conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG; + /* only one processor */ conf.nmach = 1; /* set up other configuration parameters */ diff --git a/bitsy/mmu.c b/bitsy/mmu.c index 4646c14cb15544cc38b5fecc5f85eeafc3f7c41e..ad7bc4d053aeca7040b347d34d8d52026fd31836 100644 --- a/bitsy/mmu.c +++ b/bitsy/mmu.c @@ -82,6 +82,7 @@ mmuinit(void) /* map zeros area */ for(o = 0; o < 128 * OneMeg; o += OneMeg) l1table[(NULLZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0 + | L1Cached | L1Buffered | ((PHYSNULL0+o)&L1SectBaseMask); /* map flash */ @@ -113,9 +114,9 @@ mmuinit(void) /* enable mmu */ wbflush(); - flushcache(); - flushmmu(); + mmuinvalidate(); mmuenable(); + cacheflush(); } /* @@ -224,7 +225,7 @@ putmmu(ulong va, ulong pa, Page*) Page *p; ulong *t; -iprint("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa); +//iprint("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa); /* always point L1 entry to L2 page, can't hurt */ p = up->l1page[va>>20]; if(p == nil){ @@ -236,47 +237,97 @@ iprint("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa); memset((uchar*)(p->va), 0, BY2PG); } l1table[va>>20] = L1PageTable | L1Domain0 | (p->pa & L1PTBaseMask); - cleanaddr((ulong)&l1table[va>>20]); -iprint("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]); + cacheflushaddr((ulong)&l1table[va>>20]); +//iprint("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]); up->l1table[va>>20] = l1table[va>>20]; t = (ulong*)p->va; /* set L2 entry */ t[(va & (OneMeg-1))>>PGSHIFT] = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)] | (pa & ~(PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)); -iprint("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]); - cleanaddr((ulong)&t[(va & (OneMeg-1))>>PGSHIFT]); +//iprint("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]); + cacheflushaddr((ulong)&t[(va & (OneMeg-1))>>PGSHIFT]); wbflush(); } /* - * this is called with palloc locked so the pagechainhead is kosher + * free up all page tables for this proc */ void -mmurelease(Proc* p) +mmuptefree(Proc *p) { Page *pg; int i; - for(i = 0; i < nelem(p->l1page); i++){ + for(i = 0; i < Nmeg; i++){ pg = p->l1page[i]; if(pg == nil) continue; + p->l1page[i] = nil; + pg->next = p->mmufree; + p->mmufree = pg; + } + memset(p->l1table, 0, sizeof(p->l1table)); +} + +/* + * this is called with palloc locked so the pagechainhead is kosher + */ +void +mmurelease(Proc* p) +{ + Page *pg, *next; + + /* write back dirty cache entries before changing map */ + cacheflush(); + + mmuptefree(p); + + for(pg = p->mmufree; pg; pg = next){ + next = pg->next; if(--pg->ref) panic("mmurelease: pg->ref %d\n", pg->ref); pagechainhead(pg); - p->l1page[i] = nil; } + if(p->mmufree && palloc.r.p) + wakeup(&palloc.r); + p->mmufree = nil; + + memset(l1table, 0, sizeof(p->l1table)); } void mmuswitch(Proc* p) { -iprint("switching to proc %d\n", p->pid); + if(p->newtlb){ + mmuptefree(p); + p->newtlb = 0; + } + + /* write back dirty cache entries before changing map */ + cacheflush(); + + /* move in new map */ memmove(l1table, p->l1table, sizeof(p->l1table)); - cleanaddr((ulong)l1table); + + /* make sure map is in memory and drain write buffer */ + cacheflushaddr((ulong)l1table); wbflush(); + + /* lose any possible stale tlb entries */ + mmuinvalidate(); +} + +void +flushmmu(void) +{ + int s; + + s = splhi(); + up->newtlb = 1; + mmuswitch(up); + splx(s); } void diff --git a/bitsy/screen.c b/bitsy/screen.c index b9bcd00f89618bb2489dd8cc01044fe91c448289..0f10c0195b2c87264ba01aa9d01fce645f44156e 100644 --- a/bitsy/screen.c +++ b/bitsy/screen.c @@ -42,3 +42,9 @@ blankscreen(int blank) { USED(blank); } + +void +screenputs(char *s, int n) +{ + USED(s, n); +} diff --git a/bitsy/trap.c b/bitsy/trap.c index ec99efd4093df21b08a2e6c2ab3307a4ab94f63c..e715c27b506f2280f890ef7679cc81509a715c64 100644 --- a/bitsy/trap.c +++ b/bitsy/trap.c @@ -131,14 +131,15 @@ faultarm(Ureg *ureg, ulong va, int user, int read) insyscall = up->insyscall; up->insyscall = 1; -peekmmu(va); +//peekmmu(va); n = fault(va, read); -iprint("fault returns %d\n", n); +//iprint("fault returns %d\n", n); if(n < 0){ if(!user){ dumpregs(ureg); - qpanic("fault: 0x%lux\n", va); + panic("fault: 0x%lux\n", va); } + dumpregs(ureg); sprint(buf, "sys: trap: fault %s va=0x%lux", read? "read" : "write", va); postnote(up, 1, buf, NDebug); @@ -152,7 +153,7 @@ iprint("fault returns %d\n", n); void trap(Ureg *ureg) { - int i; + int i, found; Vctl *v; int user; ulong va; @@ -171,18 +172,18 @@ trap(Ureg *ureg) switch(ureg->type){ default: - qpanic("unknown trap"); + panic("unknown trap"); break; case PsrMabt: /* prefetch fault */ - iprint("prefetch abort at 0x%lux\n", ureg->pc); +//iprint("prefetch abort at 0x%lux\n", ureg->pc); faultarm(ureg, ureg->pc, user, 1); break; case PsrMabt+1: /* data fault */ va = getfar(); - iprint("data fault pc 0x%lux va 0x%lux fsr 0x%lux\n", ureg->pc, va, getfsr()); +//iprint("data fault pc 0x%lux(0x%lux) va 0x%lux fsr 0x%lux\n", ureg->pc, *(ulong*)(ureg->pc), va, getfsr()); switch(getfsr() & 0xf){ case 0x0: - qpanic("vector exception at %lux\n", ureg->pc); + panic("vector exception at %lux\n", ureg->pc); break; case 0x1: case 0x3: @@ -191,10 +192,10 @@ trap(Ureg *ureg) ureg->pc, va); postnote(up, 1, buf, NDebug); } else - qpanic("kernel alignment: pc 0x%lux va 0x%lux", ureg->pc, va); + panic("kernel alignment: pc 0x%lux va 0x%lux", ureg->pc, va); break; case 0x2: - qpanic("terminal exception at %lux\n", ureg->pc); + panic("terminal exception at %lux\n", ureg->pc); break; case 0x4: case 0x6: @@ -202,12 +203,12 @@ trap(Ureg *ureg) case 0xa: case 0xc: case 0xe: - qpanic("external abort at %lux\n", ureg->pc); + panic("external abort at %lux\n", ureg->pc); break; case 0x5: case 0x7: /* translation fault, i.e., no pte entry */ - faultarm(ureg, va, user, 0); + faultarm(ureg, va, user, 1); break; case 0x9: case 0xb: @@ -216,24 +217,30 @@ trap(Ureg *ureg) sprint(buf, "sys: access violation: pc 0x%lux va 0x%lux\n", ureg->pc, va); postnote(up, 1, buf, NDebug); } else - qpanic("kernel access violation: pc 0x%lux va 0x%lux\n", ureg->pc, va); + panic("kernel access violation: pc 0x%lux va 0x%lux\n", ureg->pc, va); break; case 0xd: case 0xf: /* permission error, copy on write or real permission error */ - faultarm(ureg, va, user, 1); + faultarm(ureg, va, user, 0); break; } break; case PsrMund: /* undefined instruction */ - qpanic("undefined instruction"); + panic("undefined instruction"); break; case PsrMirq: /* device interrupt */ - for(i = 0; i < 32; i++) + for(i = 0; i < 32; i++){ + found = 0; if((1<icip){ - for(v = vctl[i]; v != nil; v = v->next) + for(v = vctl[i]; v != nil; v = v->next){ + found = 1; v->f(ureg, v->a); + } + if(!found) + iprint("interrupt %d with no handler\n", i); } + } break; } @@ -258,10 +265,8 @@ syscall(Ureg* ureg) long ret; int i, scallnr; -iprint("syscall in\n"); -dumpregs(ureg); if((ureg->psr & PsrMask) != PsrMusr) - qpanic("syscall: cs 0x%4.4uX\n", ureg->psr); + panic("syscall: cs 0x%4.4uX\n", ureg->psr); m->syscall++; up->insyscall = 1; @@ -289,9 +294,7 @@ dumpregs(ureg); up->s = *((Sargs*)(sp+BY2WD)); up->psstate = sysctab[scallnr]; -iprint("before syscall\n"); ret = systab[scallnr](up->s.args); -iprint("syscall retuns %d\n", ret); poperror(); } if(up->nerrlab){ @@ -299,7 +302,7 @@ iprint("syscall retuns %d\n", ret); for(i = 0; i < NERR; i++) print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc); - qpanic("error stack"); + panic("error stack"); } up->insyscall = 0;