M gnot/dat.h => gnot/dat.h +8 -0
@@ 223,6 223,14 @@ struct Mach
Lock alarmlock; /* access to alarm list */
void *alarm; /* alarms bound to this clock */
int fpstate; /* state of fp registers on machine */
+
+ int tlbfault;
+ int pfault;
+ int cs;
+ int syscall;
+ int spinlock;
+ int intr;
+
int stack[1];
};
M port/devcons.c => port/devcons.c +33 -2
@@ 320,6 320,7 @@ enum{
Qtime,
Quser,
Qvmereset,
+ Qsysstat,
};
Dirtab consdir[]={
@@ 334,6 335,7 @@ Dirtab consdir[]={
"time", {Qtime}, 12, 0600,
"user", {Quser}, 0, 0600,
"vmereset", {Qvmereset}, 0, 0600,
+ "sysstat", {Qsysstat}, 0, 0600,
};
#define NCONS (sizeof consdir/sizeof(Dirtab))
@@ 443,13 445,14 @@ consclose(Chan *c)
long
consread(Chan *c, void *buf, long n, ulong offset)
{
- int ch, i, j, k;
+ int ch, i, j, k, id;
ulong l;
uchar *out;
char *cbuf = buf;
char *user;
int userlen;
- char tmp[6*NUMSIZE];
+ char tmp[6*NUMSIZE], xbuf[512];
+ Mach *mp;
if(n <= 0)
return n;
@@ 532,6 535,18 @@ consread(Chan *c, void *buf, long n, ulong offset)
case Qlog:
return readlog(offset, buf, n);
+ case Qsysstat:
+ j = 0;
+ for(id = 0; id < 32; id++) {
+ if(active.machs & (1<<id)) {
+ mp = MACHP(id);
+ j += sprint(&xbuf[j], "%d %d %d %d %d %d %d %d\n",
+ id, mp->cs, mp->intr, mp->syscall, mp->pfault,
+ mp->tlbfault, mp->tlbpurge, mp->spinlock);
+ }
+ }
+
+ return readstr(offset, buf, n, xbuf);
case Qnull:
return 0;
@@ 547,7 562,9 @@ conswrite(Chan *c, void *va, long n, ulong offset)
char cbuf[64];
char buf[256];
long l, m;
+ int id;
char *a = va;
+ Mach *mp;
switch(c->qid.path){
case Qcons:
@@ 601,7 618,21 @@ conswrite(Chan *c, void *va, long n, ulong offset)
error(Eperm);
vmereset();
break;
+ case Qsysstat:
+ for(id = 0; id < 32; id++) {
+ if(active.machs & (1<<id)) {
+ mp = MACHP(id);
+ mp->cs = 0;
+ mp->intr = 0;
+ mp->syscall = 0;
+ mp->pfault = 0;
+ mp->tlbfault = 0;
+ mp->tlbpurge = 0;
+ mp->spinlock = 0;
+ }
+ }
+ break;
default:
error(Egreg);
}
M port/devdup.c => port/devdup.c +12 -1
@@ 61,7 61,18 @@ dupwalk(Chan *c, char *name)
void
dupstat(Chan *c, char *db)
{
- devstat(c, db, (Dirtab *)0, 0L, dupgen);
+ int fd;
+ Chan *f;
+
+ if(c->qid.path == CHDIR){
+ devstat(c, db, (Dirtab *)0, 0L, dupgen);
+ }else{
+ fd = c->qid.path;
+ SET(f);
+ if(fd<0 || NFD<=fd || (f=u->fd[fd])==0)
+ error(Ebadfd);
+ (*devtab[f->type].stat)(f, (char*)db);
+ }
}
Chan *
M port/devmnt.c => port/devmnt.c +23 -10
@@ 397,11 397,6 @@ mntclwalk(Chan *c, char *name)
Mnthdr *mh;
Chan *nc;
- if(waserror()){ /* BUG: can check type of error? */
- freechan(nc);
- nc = 0;
- goto Out;
- }
nc = newchan();
nc->type = c->type;
nc->dev = c->dev;
@@ 413,6 408,13 @@ mntclwalk(Chan *c, char *name)
nc->aux = c->aux;
nc->mchan = c->mchan;
nc->mqid = c->qid;
+ mh = 0;
+ if(waserror()){
+ close(nc);
+ if(mh)
+ mhfree(mh);
+ return 0;
+ }
m = mntdev(c, 0);
mh = mhalloc();
mh->thdr.type = Tclwalk;
@@ 420,12 422,21 @@ mntclwalk(Chan *c, char *name)
mh->thdr.newfid = nc->fid;
strcpy(mh->thdr.name, name);
mntxmit(m, mh);
- if(mh->rhdr.fid == mh->thdr.fid)
- errors("directory entry not found");
poperror();
- nc->qid = mh->rhdr.qid;
- incref(m);
- Out:
+ if(mh->rhdr.fid == mh->thdr.fid){
+ /*
+ * just free the chan, the other side has
+ * already clunked
+ */
+ freechan(nc);
+ nc = 0;
+ } else {
+ /*
+ * it worked, keep the channel
+ */
+ nc->qid = mh->rhdr.qid;
+ incref(m);
+ }
mhfree(mh);
return nc;
}
@@ 780,10 791,12 @@ mntxmit(Mnt *m, Mnthdr *mh)
print("type mismatch %d %d\n", mh->rhdr.type, mh->thdr.type+1);
error(Ebadmsg);
}
+#ifdef PHILW_HACK
if(mh->rhdr.fid != mh->thdr.fid){
print("fid mismatch %d %d type %d\n", mh->rhdr.fid, mh->thdr.fid, mh->rhdr.type);
error(Ebadmsg);
}
+#endif
/*
* Copy out on read
M port/fault.c => port/fault.c +5 -2
@@ 16,7 16,7 @@ fault(ulong addr, int read)
char *l;
Page *pg;
int zeroed = 0, head = 1;
- int i;
+ int i, touched = 0;
KMap *k, *k1;
s = seg(u->p, addr);
@@ 61,6 61,7 @@ fault(ulong addr, int read)
pte = opte;
}
if(pte->page == 0){
+ touched = 1;
if(o->chan==0 || addr>(o->va+(o->maxca-o->minca))){
/*
* Zero fill page. If we are really doing a copy-on-write
@@ 114,7 115,7 @@ fault(ulong addr, int read)
if((o->flag & OWRPERM) && (conf.copymode || !read)
&& ((head && ((o->flag&OPURE) || o->nproc>1))
|| (!head && pte->page->ref>1))){
-
+ touched = 1;
/*
* Look for the easy way out: are we the last non-modified?
*/
@@ 194,6 195,8 @@ fault(ulong addr, int read)
panic("addr %lux seg %d wrong proc in tail", addr, s-u->p->seg);
}
unlock(o);
+ if(touched == 0)
+ m->tlbfault++;
putmmu(mmuvirt, mmuphys);
return 0;
}
M port/page.c => port/page.c +2 -0
@@ 47,6 47,8 @@ struct{
PTEA *free;
}modalloc;
+extern long end;
+
/*
* Called to allocate permanent data structures, before calling pageinit().
*/
M port/proc.c => port/proc.c +8 -1
@@ 84,6 84,7 @@ sched(void)
if(u){
splhi();
+ m->cs++;
procsave(procstate, sizeof(procstate));
if(setlabel(&u->p->sched)){ /* woke up */
p = u->p;
@@ 190,6 191,7 @@ loop:
p->exiting = 0;
p->pgrp = 0;
p->fpstate = FPinit;
+ p->kp = 0;
memset(p->pidonmach, 0, sizeof p->pidonmach);
memset(p->seg, 0, sizeof p->seg);
lock(&pidalloc);
@@ 327,13 329,18 @@ postnote(Proc *p, int dolock, char *n, int flag)
int s;
Rendez *r;
+ SET(k);
+ USED(k);
+
if(dolock)
lock(&p->debug);
+
if(p != u->p){
k = kmap(p->upage);
up = (User*)VA(k);
- }else
+ }else
up = u;
+
if(flag!=NUser && (up->notify==0 || up->notified))
up->nnote = 0; /* force user's hand */
else if(up->nnote == NNOTE-1){
M port/tcpoutput.c => port/tcpoutput.c +1 -0
@@ 93,6 93,7 @@ tcp_output(Ipconv *s)
stop_timer(&tcb->acktimer);
tcb->flags &= ~FORCE;
+ tcprcvwin(s);
seg.source = s->psrc;
seg.dest = s->pdst;
M power/dat.h => power/dat.h +18 -2
@@ 18,6 18,7 @@ typedef struct Label Label;
typedef struct List List;
typedef struct Lock Lock;
typedef struct Mach Mach;
+typedef struct Softtlb Softtlb;
typedef struct Mount Mount;
typedef struct Mtab Mtab;
typedef struct Note Note;
@@ 218,10 219,16 @@ struct Envp
int chref; /* # chans from pgrp pointing here */
};
+struct Softtlb
+{
+ ulong virt;
+ ulong phys;
+};
+
struct Mach
{
- int machno; /* physical id of processor */
- int mmask; /* 1<<m->machno */
+ int machno; /* physical id of processor NB. MUST BE FIRST */
+ Softtlb *stb; /* Software tlb simulation NB. MUST BE SECOND */
ulong ticks; /* of the clock since boot time */
Proc *proc; /* current process on this processor */
Label sched; /* scheduler wakeup */
@@ 230,6 237,15 @@ struct Mach
char pidhere[NTLBPID]; /* is this pid possibly in this mmu? */
int lastpid; /* last pid allocated on this machine */
Proc *pidproc[NTLBPID]; /* process that owns this tlbpid on this mach */
+
+ int tlbfault;
+ int tlbpurge;
+ int pfault;
+ int cs;
+ int syscall;
+ int spinlock;
+ int intr;
+
int stack[1];
};
M power/devbit3.c => power/devbit3.c +2 -0
@@ 30,6 30,7 @@ enum
void
bit3send(Bit3msg *bp, ulong cmd, void *addr, ulong count)
{
+
do; while(*BIT3ADDR);
bp->cmd = cmd;
bp->addr = (ulong)addr;
@@ 38,6 39,7 @@ bit3send(Bit3msg *bp, ulong cmd, void *addr, ulong count)
wbflush();
do; while(*BIT3HOLD);
*BIT3INTR = 0x20;
+
}
void
M power/faultmips.c => power/faultmips.c +1 -0
@@ 17,6 17,7 @@ faultmips(Ureg *ur, int user, int code)
extern char *excname[];
int read;
+ m->pfault++;
addr = ur->badvaddr;
addr &= ~(BY2PG-1);
read = !(code==CTLBM || code==CTLBS);
M power/fns.h => power/fns.h +2 -0
@@ 147,6 147,7 @@ Block *pullup(Block *, int);
void purgetlb(int);
Queue *pushq(Stream*, Qinfo*);
void putmmu(ulong, ulong);
+void putstlb(ulong, ulong);
void puttlb(ulong, ulong);
void puttlbx(int, ulong, ulong);
int putb(Blist*, Block*);
@@ 207,6 208,7 @@ void userinit(void);
void validaddr(ulong, ulong, int);
void vecinit(void);
void vector80(void);
+void vector0(void);
void *vmemchr(void*, int, int);
void vmereset(void);
void wakeme(Alarm*);
M power/l.s => power/l.s +47 -0
@@ 175,6 175,7 @@ TEXT puttlb(SB), $4
NOOP
JAL splx(SB)
RET
+
index:
TLBWI
NOOP
@@ 241,6 242,52 @@ TEXT vector80(SB), $-4
MOVW $exception(SB), R26
JMP (R26)
+TEXT vector0(SB), $-4
+
+ MOVW $utlbmiss(SB), R26
+ MOVW M(TLBVIRT), R27
+ SLL $(STLBLOG-9), R27 /* delay slot fodder */
+ JMP (R26)
+
+TEXT utlbmiss(SB), $-4
+
+ SRL $(STLBLOG), R27, R26
+ XOR R26, R27
+ AND $((STLBSIZE-1)<<3), R27
+ MOVW R27, M(TLBPHYS) /* scratch register, store */
+
+ MOVW $((MACHADDR+4) & 0xffff0000), R26
+ MOVW $MPID, R27
+ MOVB 3(R27), R27
+ AND $7, R27
+ SLL $PGSHIFT, R27
+ ADDU R27, R26
+
+ MOVW M(TLBPHYS), R27 /* scratch register, load */
+ MOVW ((MACHADDR+4) & 0xffff)(R26), R26
+ ADDU R26, R27
+ MOVW 4(R27), R26
+ MOVW R26, M(TLBPHYS)
+
+ MOVW M(TLBVIRT), R26
+ MOVW (R27), R27
+ BNE R26, R27, stlbm
+
+ TLBP
+ MOVW M(EPC), R27
+ MOVW M(INDEX), R26
+ BGEZ R26, uind
+ TLBWR
+ NOOP
+ RFE (R27)
+uind:
+ TLBWI
+ NOOP
+ RFE (R27)
+stlbm:
+ MOVW $exception(SB), R26
+ JMP (R26)
+
TEXT exception(SB), $-4
MOVW M(STATUS), R26
M power/main.c => power/main.c +7 -2
@@ 8,6 8,11 @@
#include "init.h"
/*
+ * software tlb simulation
+ */
+Softtlb stlb[4][STLBSIZE];
+
+/*
* args passed by boot process
*/
int _argc; char **_argv; char **_env;
@@ 77,7 82,7 @@ machinit(void)
n = m->machno;
memset(m, 0, sizeof(Mach));
m->machno = n;
- m->mmask = 1<<m->machno;
+ m->stb = &stlb[n][0];
}
void
@@ 100,7 105,7 @@ vecinit(void)
for(size=0; size<4; size++)
*p++ = *q++;
p = (ulong*)UTLBMISS;
- q = (ulong*)vector80;
+ q = (ulong*)vector0;
for(size=0; size<4; size++)
*p++ = *q++;
}
M power/mem.h => power/mem.h +5 -0
@@ 96,6 96,11 @@
#define PTEWRITE (1<<10)
#define PTERONLY 0
#define PTEPID(n) ((n)<<6)
+#define TLBPID(n) (((n)>>6)&0x3F)
+
+/* N.B. MUST CHANGE l.s utlbmiss if you want to change this */
+#define STLBLOG 13
+#define STLBSIZE (1<<STLBLOG)
#define NTLBPID 64 /* number of pids */
#define NTLB 64 /* number of entries */
M power/mmu.c => power/mmu.c +70 -10
@@ 25,6 25,7 @@ mapstack(Proc *p)
tlbvirt = USERADDR | PTEPID(tp);
tlbphys = p->upage->pa | PTEWRITE | PTEVALID | PTEGLOBL;
puttlbx(0, tlbvirt, tlbphys);
+ putstlb(tlbvirt, tlbphys);
u = (User*)USERADDR;
}
@@ 34,19 35,44 @@ mapstack(Proc *p)
int
newtlbpid(Proc *p)
{
- int i;
+ int i, s;
Proc *sp;
-
+ char *h;
+/*
+ s = m->lastpid;
+ if(s >= NTLBPID)
+ s = 1;
+ i = s;
+ h = m->pidhere;
+ do{
+ i++;
+ if(i >= NTLBPID)
+ i = 1;
+ }while(h[i] && i != s);
+
+ if(i == s){
+ sp = m->pidproc[i];
+ if(sp){
+ if(sp->pidonmach[m->machno] == i)
+ sp->pidonmach[m->machno] = 0;
+ purgetlb(i);
+ }
+ }
+*/
i = m->lastpid+1;
if(i >= NTLBPID)
i = 1;
sp = m->pidproc[i];
if(sp){
+ if(sp->pidonmach[m->machno] == i)
+ sp->pidonmach[m->machno] = 0;
+
sp->pidonmach[m->machno] = 0;
purgetlb(i);
}
- m->pidproc[i] = p;
+
m->lastpid = i;
+ m->pidproc[i] = p;
return i;
}
@@ 68,6 94,7 @@ putmmu(ulong tlbvirt, ulong tlbphys)
p->pidonmach[m->machno] = tp;
}
tlbvirt |= PTEPID(tp);
+ putstlb(tlbvirt, tlbphys);
puttlb(tlbvirt, tlbphys);
m->pidhere[tp] = 1;
p->state = Running;
@@ 77,18 104,38 @@ putmmu(ulong tlbvirt, ulong tlbphys)
void
purgetlb(int pid)
{
+ Softtlb *entry, *etab;
+ char p[NTLBPID];
+ Proc *sp;
int i, rpid;
- if(m->pidhere[pid] == 0)
+ if(m->pidproc[pid] == 0)
return;
- memset(m->pidhere, 0, sizeof m->pidhere);
- for(i=TLBROFF; i<NTLB; i++){
- rpid = (gettlbvirt(i)>>6) & 0x3F;
- if(rpid == pid)
+
+ m->tlbpurge++;
+ m->pidproc[pid] = 0;
+ memset(p, 0, sizeof p);
+ for(i=TLBROFF; i<NTLB; i++)
+ if(TLBPID(gettlbvirt(i)) == pid)
puttlbx(i, KZERO | PTEPID(i), 0);
- else
- m->pidhere[rpid] = 1;
+ entry = m->stb;
+ etab = &entry[STLBSIZE];
+ for(; entry < etab; entry++){
+ rpid = TLBPID(entry->virt);
+ if(rpid == pid){
+ entry->phys = 0;
+ entry->virt = 0;
+ }else
+ p[rpid] = 1;
}
+ for(i = 0; i < NTLBPID; i++)
+ if(p[i] == 0){
+ sp = m->pidproc[i];
+ if(sp && sp->pidonmach[m->machno] == i)
+ sp->pidonmach[m->machno] = 0;
+ m->pidproc[i] = 0;
+ m->pidhere[i] = 0;
+ }
}
void
@@ 111,4 158,17 @@ void
invalidateu(void)
{
puttlbx(0, KZERO | PTEPID(0), 0);
+ putstlb(KZERO | PTEPID(0), 0);
+}
+
+void
+putstlb(ulong tlbvirt, ulong tlbphys)
+{
+ Softtlb *entry;
+
+ entry = &m->stb[((tlbvirt<<1) ^ (tlbvirt>>12)) & (STLBSIZE-1)];
+ entry->phys = tlbphys;
+ entry->virt = tlbvirt;
+ if(tlbphys == 0)
+ entry->virt = 0;
}
M power/trap.c => power/trap.c +4 -0
@@ 151,6 151,7 @@ trap(Ureg *ur)
sprint(buf, "sys: fp: %s FCR31 %lux", fpexcname(x), x);
else
sprint(buf, "sys: trap: %s[%d]", excname[ecode], m->machno);
+
postnote(u->p, 1, buf, NDebug);
}else{
print("%s %s pc=%lux\n", user? "user": "kernel", excname[ecode], ur->pc);
@@ 182,6 183,7 @@ intr(Ureg *ur)
ulong cause;
static int bogies;
+ m->intr++;
cause = ur->cause&(INTR5|INTR4|INTR3|INTR2|INTR1);
if(cause & (INTR2|INTR4)){
clock(ur);
@@ 237,6 239,7 @@ intr(Ureg *ur)
print("new pend %ux\n", xxx);
npend = pend |= xxx;
i = SBCCREG->flevel;
+ USED(i);
}
/*
@@ 468,6 471,7 @@ syscall(Ureg *aur)
Ureg *ur;
char *msg;
+ m->syscall++;
u->p->insyscall = 1;
ur = aur;
u->p->pc = ur->pc; /* BUG */