ptal Reference: /n/patches.lsub.org/patch/roles Date: Tue Apr 24 18:54:49 CES 2012 Signed-off-by: paurea@lsub.org --- /sys/src/nix/k10/acore.c Thu Apr 12 12:26:27 2012 +++ /sys/src/nix/k10/acore.c Tue Apr 24 18:08:30 2012 @@ -64,7 +64,7 @@ print("calling core %d... ", i); mp->icc->flushtlb = 0; snprint((char*)mp->icc->data, ICCLNSZ, "<%d>", i); - mfence(); + coherence(); mp->icc->fn = testiccfn; mwait(&mp->icc->fn); } @@ -107,7 +107,7 @@ DBG("acsched: cpu%d: fn %#p\n", m->machno, m->icc->fn); m->icc->fn(); DBG("acsched: cpu%d: idle\n", m->machno); - mfence(); + coherence(); m->icc->fn = nil; } } @@ -208,7 +208,7 @@ m->icc->note = n; fpuprocsave(m->proc); _pmcupdate(m); - mfence(); + coherence(); m->icc->fn = nil; ready(m->proc); @@ -244,7 +244,7 @@ m->cr2 = cr2get(); fpuprocsave(p); _pmcupdate(m); - mfence(); + coherence(); m->icc->fn = nil; ready(p); /* @@ -280,6 +280,7 @@ [NIXAC] "AC", [NIXTC] "TC", [NIXKC] "KC", + [NIXOC] "OC", [NIXXC] "XC", }; @@ -290,12 +291,14 @@ case NIXAC: case NIXKC: case NIXTC: + case NIXOC: case NIXXC: break; default: panic("acmodeset: bad mode %d", mode); } m->nixtype = mode; + m->nnixtype = NIXROLES; } void @@ -320,4 +323,17 @@ assert((uintptr)&mp->proc == 16); assert((uintptr)&pp->dbgreg == 24); assert((uintptr)&mp->stack == 24); +} + +void +acquiesce(void) +{ + Proc *p; + p = m->proc; + p->ac = nil; + m->icc->rc = ICCOK; + m->cr2 = cr2get(); + fpuprocsave(p); + coherence(); + ready(p); } --- /sys/src/nix/k10/apic.c Thu Apr 12 12:26:27 2012 +++ /sys/src/nix/k10/apic.c Tue Apr 24 16:53:09 2012 @@ -366,6 +366,19 @@ splx(pl); } +/* NIPI - INIT IPI, freeze processor */ +void +apicnipi(int apicno) +{ + u32int crhi; + + crhi = apicno<<24; + apicrput(Ichi, crhi); + apicrput(Iclo, DSnone|TMlevel|Lassert|MTir); + microdelay(200); + apicrput(Iclo, DSnone|TMlevel|MTir); +} + void apicsipi(int apicno, uintmem pa) { @@ -376,13 +389,10 @@ * SIPI - Start-up IPI. * To do: checks on apic validity. */ - crhi = apicno<<24; - apicrput(Ichi, crhi); - apicrput(Iclo, DSnone|TMlevel|Lassert|MTir); - microdelay(200); - apicrput(Iclo, DSnone|TMlevel|MTir); + apicnipi(apicno); millidelay(10); + crhi = apicno<<24; crlo = DSnone|TMedge|MTsipi|((u32int)pa/(4*KiB)); for(i = 0; i < 2; i++){ apicrput(Ichi, crhi); --- /sys/src/nix/k10/dat.h Fri Apr 20 17:09:28 2012 +++ /sys/src/nix/k10/dat.h Tue Apr 24 16:53:09 2012 @@ -150,7 +150,8 @@ struct NIX { ICC* icc; /* inter-core call */ - int nixtype; + int nixtype; + int nnixtype; }; /* --- /sys/src/nix/k10/fns.h Thu Apr 12 12:26:27 2012 +++ /sys/src/nix/k10/fns.h Tue Apr 24 16:53:09 2012 @@ -2,9 +2,8 @@ void intrac(Proc*); void acinit(void); int acpiinit(void); +void acquiesce(void); void actrapenable(int, char* (*)(Ureg*, void*), void*, char*); -void apicipi(int); -void apicpri(int); void acsysret(void); void actouser(void); void runacore(void); @@ -24,6 +23,7 @@ void archinit(void); void archreset(void); vlong archhz(void); +int changerole(int, int); void cgaconsputs(char*, int); void cgainit(void); void cgapost(int); @@ -142,6 +142,7 @@ void* sysexecregs(uintptr, ulong, ulong); uintptr sysexecstack(uintptr, int); void sysprocsetup(Proc*); +void tcquiesce(void); void tssrsp0(u64int); void trapenable(int, void (*)(Ureg*, void*), void*, char*); void trapinit(void); @@ -216,6 +217,7 @@ extern int apiconline(void); extern void apicpri(int); extern void apicsipi(int, uintmem); +void apicnipi(int apicno); extern void ioapicinit(int, uintmem); extern void ioapicintrinit(int, int, int, int, u32int); @@ -243,7 +245,8 @@ /* * sipi.c */ -extern void sipi(void); +extern void sipiall(void); +extern int sipicore(int); /* * debug --- /sys/src/nix/k10/main.c Thu Apr 12 12:26:28 2012 +++ /sys/src/nix/k10/main.c Tue Apr 24 16:53:09 2012 @@ -82,6 +82,8 @@ } } +static int istentacle; + void squidboy(int apicno) { @@ -96,11 +98,15 @@ m->cpumhz = 2000; m->perf.period = 1; - m->nixtype = NIXAC; + if(!istentacle){ + m->nixtype = NIXAC; + }else{ + print("TENTACLE %d stack %#p m:%#p\n", m->machno, m->stack, m); + } DBG("Hello Squidboy %d %d\n", apicno, m->machno); - vsvminit(MACHSTKSZ, m->nixtype); + vsvminit(MACHSTKSZ, NIXAC); /* * Beware the Curse of The Non-Interruptable Were-Temporary. @@ -165,6 +171,13 @@ panic("squidboy returns (type %d)", m->nixtype); } +void +tentacle(int apicno) +{ + ainc(&istentacle); + squidboy(apicno); +} + static void testiccs(void) { @@ -257,7 +270,9 @@ memset(m, 0, sizeof(Mach)); m->machno = 0; m->online = 1; - m->nixtype = NIXTC; + + acmodeset(NIXTC); + sys->machptr[m->machno] = &sys->mach; m->stack = PTR2UINT(sys->machstk); m->vsvm = sys->vsvmpage; @@ -339,7 +354,7 @@ procinit0(); mpsinit(maxcores); apiconline(); - sipi(); + sipiall(); timersinit(); kbdenable(); --- /sys/src/nix/k10/sipi.c Thu Apr 12 12:26:28 2012 +++ /sys/src/nix/k10/sipi.c Tue Apr 24 16:53:09 2012 @@ -9,8 +9,63 @@ #define SIPIHANDLER (KZERO+0x3000) +/* Soft reset a core everything should + * still be there from the original sipi. + * TODO: merge this with sipi +*/ +int +sipicore(int core) +{ + Mach *mp; + uchar nvstate; + int i, issuicide; + extern void tentacle(int); + + uintmem sipipa; + u32int *sipiptr; + + issuicide = 0; + mp = sys->machptr[core]; + if(mp == m) + issuicide = 1; + + /* should be quiescent before sipiing it */ + + sipipa = mmuphysaddr(SIPIHANDLER); + if((sipipa & (4*KiB - 1)) || sipipa > (1*MiB - 2*4*KiB)) + return -1; + + /* BUG, RACY AND DANGEROUS!!!, */ + sipiptr = UINT2PTR(SIPIHANDLER); + sipiptr[-1] = mmuphysaddr(PTR2UINT(mp->stack+MACHSTKSZ)); + + mp->splpc = PTR2UINT(tentacle); + ainc(&active.nbooting); + adec(&active.nonline); + + nvstate = nvramread(0x0f); + if(nvstate != 0){ + print("state for core %d sipied not soft reset: %ux, too early?\n", core, nvstate); + return -1; + } + + apicsipi(mp->apicno, sipipa); + + for(i = 0; i < 1000; i++){ + if(!issuicide && mp->splpc == 0) + break; + millidelay(5); + } + if (issuicide || i == 1000){ + print("timed out waiting for reboot\n"); + return -1; + } + return 0; + +} + void -sipi(void) +sipiall(void) { Apic *apic; Mach *mach; --- /sys/src/nix/k10/tcore.c Thu Apr 12 12:26:28 2012 +++ /sys/src/nix/k10/tcore.c Tue Apr 24 18:08:30 2012 @@ -84,7 +84,7 @@ void putac(Mach *m) { - mfence(); + coherence(); m->proc = nil; } @@ -110,6 +110,101 @@ */ } + +static void +roleac(Mach *mp, int role) +{ + + if(mp == nil) + return; + mp->proc = up; + runac(mp, acquiesce, 0, nil, 0); + mp->nixtype = role; + m->nnixtype = NIXROLES; + coherence(); + while(mp->icc->fn != nil){ + } + if(role == NIXOC) + apicnipi(mp->apicno); + else + sipicore(mp->machno); + mp->proc = nil; /*putac? */ +} + +void +tcquiesce(void) +{ + /* sync, suicide is not possible */ + m->nnixtype = NIXROLES; + coherence(); + while(1){ + halt(); + } +} + +int +changerole(int role, int core) +{ + int apicno, i; + Mach *mp, *w; + + /* + * Must run in a TC, is this the way? + */ + for(i = 0; i < MACHMAX; i++) + if((mp = sys->machptr[i]) != nil && mp->online && mp->nixtype == NIXTC){ + if(mp != sys->machptr[core]) + break; + } + if(i == MACHMAX) + return -1; + + w = up->wired; + procwired(up, i); + if(m != sys->machptr[0]) + sched(); + mp = sys->machptr[core]; + if(m == mp){ + up->wired = w; + print("SUICIDE IS NOT ALLOWED\n"); + return -1; + } + + apicno = mp->apicno; + mp->nnixtype = role; + switch(mp->nixtype){ + case NIXAC: + lock(&nixaclock); /* is this the right lock to keep? */ + if(mp->proc != nil){ + mp->proc->procctl = Proc_totc; + apicipi(apicno); + }else{ + roleac(mp, role); + } + unlock(&nixaclock); /* is the lock taken too long? */ + break; + case NIXTC: + mp->qexpired = 1; /* may need to wakeup idlehands */ + coherence(); + while(mp->nnixtype != NIXROLES){}; + /* fall */ + case NIXOC: + mp->nixtype = role; + mp->nnixtype = NIXROLES; + coherence(); + if(role == NIXOC) + apicnipi(mp->apicno); + else + sipicore(mp->machno); + mp->proc = nil; + break; + default: + print("don't know how to change my role\n"); + } + up->wired = w; + return 0; +} + /* * Functions starting with ac... are run in the application core. * All other functions are run by the time-sharing cores. @@ -167,7 +262,7 @@ up->psstate = 0; qunlock(&up->debug); poperror(); - mfence(); + coherence(); mp->icc->fn = func; sched(); return mp->icc->rc; @@ -228,6 +323,7 @@ int rc, flush, s; char *n; uvlong t1; + Mach *ac; if(waserror()) panic("runacore: error: %s\n", up->errstr); @@ -236,6 +332,7 @@ fpusysrfork(ureg); procpriority(up, PriKproc, 1); + ac = up->ac; rc = runac(up->ac, actouser, 1, nil, 0); procpriority(up, PriNormal, 0); for(;;){ @@ -311,6 +408,9 @@ * be back in the TC */ DBG("runacore: up %#p: return\n", up); + if(ac->nnixtype != NIXROLES){ + roleac(ac, ac->nnixtype); + } } extern ACVctl *acvctl[]; --- /sys/src/nix/port/lib.h Tue Apr 24 10:39:34 2012 +++ /sys/src/nix/port/lib.h Tue Apr 24 16:53:22 2012 @@ -170,6 +170,7 @@ NIXKC, NIXAC, NIXXC, + NIXOC, NIXROLES, };