M carrera/clock.c => carrera/clock.c +6 -0
@@ 105,6 105,12 @@ clock(Ureg *ur)
unlock(&clock0lock);
}
+ if(m->flushmmu){
+ if(up)
+ flushmmu();
+ m->flushmmu = 0;
+ }
+
if(up == 0 || up->state != Running)
return;
M carrera/dat.h => carrera/dat.h +2 -0
@@ 114,6 114,8 @@ struct Mach
ulong delayloop; /* for the delay() routine */
int nrdy;
ulong fairness; /* for runproc */
+ vlong fastclock; /* last sampled value */
+ int flushmmu; /* make current proc flush it's mmu state */
int pfault;
int cs;
M pc/clock.c => pc/clock.c +6 -0
@@ 59,6 59,12 @@ clockintr(Ureg* ureg, void*)
iunlock(&clock0lock);
}
+ if(m->flushmmu){
+ if(up)
+ flushmmu();
+ m->flushmmu = 0;
+ }
+
if(up == 0 || up->state != Running)
return;
M pc/dat.h => pc/dat.h +2 -2
@@ 170,6 170,8 @@ struct Mach
int syscall;
int load;
int intr;
+ vlong fastclock; /* last sampled value */
+ int flushmmu; /* make current proc flush it's mmu state */
ulong spuriousintr;
ulong lastintr;
@@ 187,8 189,6 @@ struct Mach
vlong mtrrfix[11];
vlong mtrrvar[32]; /* 256 max. */
- vlong fastclock; /* last sampled value */
-
int stack[1];
};
M pc/etherelnk3.c => pc/etherelnk3.c +21 -10
@@ 1632,7 1632,7 @@ eepromdata(int port, int offset)
int
etherelnk3reset(Ether* ether)
{
- int an, busmaster, did, i, phyaddr, port, rxearly, rxstatus9, x, xcvr;
+ int anar, anlpar, busmaster, did, i, phyaddr, port, rxearly, rxstatus9, x, xcvr;
Block *bp, **bpp;
Adapter *ap;
uchar ea[Eaddrlen];
@@ 1757,22 1757,33 @@ else
scanphy(port);
*/
phyaddr = 24;
- an = miir(port, phyaddr, 0x04);
- an &= miir(port, phyaddr, 0x05) & 0x03E0;
- XCVRDEBUG("mii an: %uX\n", an);
+ anar = miir(port, phyaddr, 0x04);
+ anlpar = miir(port, phyaddr, 0x05) & 0x03E0;
+ anar &= anlpar;
+ miir(port, phyaddr, 0x00);
+ XCVRDEBUG("mii an: %uX r0:%uX r1:%uX\n",
+ anar, anlpar, miir(port, phyaddr, 0x00), miir(port, phyaddr, 0x01));
for(i = 0; i < ether->nopt; i++){
if(cistrcmp(ether->opt[i], "fullduplex") == 0)
- an |= 0x0100;
+ anar |= 0x0100;
else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
- an |= 0x0100;
+ anar |= 0x0100;
else if(cistrcmp(ether->opt[i], "force100") == 0)
- an |= 0x0080;
+ anar |= 0x0080;
}
- XCVRDEBUG("mii an: %uX\n", an);
- if(an & 0x380)
+ XCVRDEBUG("mii anar: %uX\n", anar);
+ if(anar & 0x0100){ /* 100BASE-TXFD */
ether->mbps = 100;
- if(an & 0x0140)
setfullduplex(port);
+ }
+ else if(anar & 0x0200) /* 100BASE-T4 */
+ ;
+ else if(anar & 0x0080) /* 100BASE-TX */
+ ether->mbps = 100;
+ else if(anar & 0x0040) /* 10BASE-TFD */
+ setfullduplex(port);
+ else /* 10BASE-T */
+ ;
break;
case xcvr100BaseTX:
M port/portfns.h => port/portfns.h +1 -0
@@ 191,6 191,7 @@ int proccounter(char *name);
void procctl(Proc*);
void procdump(void);
void procinit0(void);
+void procsegflush(Segment*);
Proc* proctab(int);
void procwired(Proc*);
void ptclone(Chan*, int, int);
M port/proc.c => port/proc.c +45 -0
@@ 921,6 921,51 @@ procdump(void)
}
}
+/*
+ * wait till all processes have flushed their mmu
+ * state about segement s
+ */
+void
+procflushseg(Segment *s)
+{
+ int i, ns, nm, nwait;
+ Proc *p;
+
+ /*
+ * tell all processes with this
+ * segment to flush their mmu's
+ */
+ nwait = 0;
+ for(i=0; i<conf.nproc; i++) {
+ p = &procalloc.arena[i];
+ if(p->state == Dead)
+ continue;
+ for(ns = 0; ns < NSEG; ns++)
+ if(p->seg[ns] == s){
+ p->newtlb = 1;
+ for(nm = 0; nm < conf.nmach; nm++){
+ if(MACHP(nm)->proc == p){
+ MACHP(nm)->flushmmu = 1;
+ nwait++;
+ }
+ }
+ break;
+ }
+ }
+
+ if(nwait == 0)
+ return;
+
+ /*
+ * wait for all processors to take a clock interrupt
+ * and flush their mmu's
+ */
+ for(nm = 0; nm < conf.nmach; nm++)
+ if(MACHP(nm) != m)
+ while(MACHP(nm)->flushmmu)
+ sched();
+}
+
void
scheddump(void)
{
M port/segment.c => port/segment.c +9 -2
@@ 460,9 460,16 @@ mfreeseg(Segment *s, ulong start, int pages)
j = 0;
}
out:
- /* wait for others to get fix their tlb's and then free the pages */
- if((s->type&SG_TYPE) == SG_SHARED){
+ /* flush this seg in all other processes */
+ i = s->type&SG_TYPE;
+ switch(i){
+ case SG_SHARED:
+ case SG_SHDATA:
+ procflushseg(s);
+ break;
}
+
+ /* free the pages */
for(pg = list; pg != nil; pg = list){
list = list->next;
putpage(pg);