I merged this with some other changes I had waiting in queue. m->online is gone. mwait is changed (it has a parameter now). The name needs to change to something like waitwhile (subject to a future patch). inturmoil is gone. NIXSTABLE is gone. main has changed as a consequence to use nnixrole uniformly. The patch is quite big now. There are two new roles SC (a core has been told to stop) and QC (a core is quiescent). There is a plan to change the whole way cores are dealt with, by adding a new state to the core (busy, halting, halted, idle), and then SC and QC will probably go then, but as it is now, it is self contained. Reference: /n/patches.lsub.org/patch/roleswitching Date: Tue Jun 12 09:57:38 CES 2012 Signed-off-by: paurea@lsub.org --- /sys/src/nix/k10/acore.c Thu Apr 26 11:22:23 2012 +++ /sys/src/nix/k10/acore.c Mon Jun 11 11:18:17 2012 @@ -56,18 +56,16 @@ { Mach *mp; - if((mp = sys->machptr[i]) != nil && mp->online != 0){ - if(mp->nixtype != NIXAC){ - print("testicc: core %d is not an AC\n", i); - return; - } - print("calling core %d... ", i); - mp->icc->flushtlb = 0; - snprint((char*)mp->icc->data, ICCLNSZ, "<%d>", i); - coherence(); - mp->icc->fn = testiccfn; - mwait(&mp->icc->fn); + if((mp = sys->machptr[i]) != nil && mp->nixrole != NIXAC){ + print("testicc: core %d is not an AC\n", i); + return; } + print("calling core %d... ", i); + mp->icc->flushtlb = 0; + snprint((char*)mp->icc->data, ICCLNSZ, "<%d>", i); + coherence(); + mp->icc->fn = testiccfn; + mwait(&mp->icc->fn, 0); } /* @@ -101,7 +99,7 @@ acmmuswitch(); for(;;){ acstackok(); - mwait(&m->icc->fn); + mwait(&m->icc->fn, 0); if(m->icc->flushtlb) acmmuswitch(); DBG("acsched: cpu%d: fn %#p\n", m->machno, m->icc->fn); @@ -212,7 +210,7 @@ m->icc->fn = nil; ready(m->proc); - mwait(&m->icc->fn); + mwait(&m->icc->fn, 0); if(m->icc->flushtlb) acmmuswitch(); @@ -277,11 +275,14 @@ char *rolename[] = { - [NIXAC] "AC", [NIXTC] "TC", [NIXKC] "KC", - [NIXOC] "OC", + [NIXAC] "AC", [NIXXC] "XC", + [NIXOC] "OC", + [NIXUC] "UC", + [NIXSC] "SC", + [NIXQC] "QC", }; void @@ -293,12 +294,12 @@ case NIXTC: case NIXOC: case NIXXC: + case NIXUC: break; default: panic("acmodeset: bad mode %d", mode); } - m->nixtype = mode; - m->nnixtype = NIXROLES; + m->nixrole = mode; } void @@ -328,12 +329,13 @@ void acquiesce(void) { - Proc *p; - p = m->proc; - p->ac = nil; - m->icc->rc = ICCOK; - m->cr2 = cr2get(); - fpuprocsave(p); coherence(); - ready(p); + + m->proc = nil; + m->icc->fn = nil; + m->nixrole = NIXQC; + coherence(); + for(;;) + halt(); + } --- /sys/src/nix/k10/dat.h Thu Apr 26 11:22:23 2012 +++ /sys/src/nix/k10/dat.h Mon Jun 11 11:14:58 2012 @@ -150,8 +150,8 @@ struct NIX { ICC* icc; /* inter-core call */ - int nixtype; - int nnixtype; + int nixrole; + int nnixrole; }; /* @@ -252,7 +252,6 @@ uintptr stack; int apicno; - int online; MMMU; @@ -289,6 +288,9 @@ Lock pmclock; PmcCtr pmc[PmcMaxCtrs]; + + Lock sipilock; + Rendez sipir; MFPU; MCPU; --- /sys/src/nix/k10/fns.h Thu Apr 26 11:22:24 2012 +++ /sys/src/nix/k10/fns.h Mon Jun 11 11:15:05 2012 @@ -60,6 +60,7 @@ void* i8250alloc(int, int, int); vlong i8254hz(u32int[2][4]); void idlehands(void); +int isbooting(Mach *mp); void acidthandlers(void); void idthandlers(void); int inb(int); @@ -128,6 +129,7 @@ int pickcore(int, int); void printcpufreq(void); void putac(Mach*); +void rolestable(Mach *mp); void runapcore(int); int screenprint(char*, ...); /* debugging */ void sfence(void); @@ -227,7 +229,7 @@ * archk10.c */ extern void millidelay(int); -extern void k10mwait(void*); +extern void k10mwait(void*, int); /* * i8259.c --- /sys/src/nix/k10/ioapic.c Thu Apr 12 12:26:27 2012 +++ /sys/src/nix/k10/ioapic.c Mon Jun 11 11:15:14 2012 @@ -250,7 +250,7 @@ i = df++; if(df >= sys->nmach+1) df = 0; - if(sys->machptr[i] == nil || !sys->machptr[i]->online) + if(sys->machptr[i] == nil || sys->machptr[i]->nixrole == NIXUC) continue; i = sys->machptr[i]->apicno; if(xlapic[i].useable && xlapic[i].addr == 0) --- /sys/src/nix/k10/l32p.s Thu Apr 12 12:26:27 2012 +++ /sys/src/nix/k10/l32p.s Fri Jun 8 12:00:51 2012 @@ -79,19 +79,19 @@ * and use two 2MiB entries. */ /* - * The layout is decribed in data.h: - * _protected: start of kernel text - * - 4*KiB unused - * - 4*KiB unused - * - 4*KiB ptrpage - * - 4*KiB syspage - * - MACHSZ m - * - 4*KiB vsvmpage for gdt, tss + * The layout is decribed in dat.h: + * - MACHSTKSZ stack * - PTSZ PT for PMAPADDR unused - assumes in KZERO PD * - PTSZ PD * - PTSZ PDP * - PTSZ PML4 - * - MACHSTKSZ stack + * - 4*KiB vsvmpage for gdt, tss + * - MACHSZ m + * - 4*KiB syspage + * - 4*KiB ptrpage + * - 4*KiB unused + * - 4*KiB unused + * _protected: start of kernel text */ /* --- /sys/src/nix/k10/l64sipi.s Thu Apr 12 12:26:28 2012 +++ /sys/src/nix/k10/l64sipi.s Mon May 7 13:24:07 2012 @@ -97,13 +97,8 @@ /* * Protected mode. Welcome to 1982. * Get the local APIC ID from the memory mapped APIC; -#ifdef UseOwnPageTables * load the PDB with the page table address, which is located - * in the word immediately preceeding _real<>-KZERO(SB); - * this is also the (physical) address of the top of stack; -#else - * load the PML4 with the shared page table address; -#endif + * in the Sipi, after the handler, see sipi.c * make an identity map for the inter-segment jump below, * using the stack space to hold a temporary PDP and PD; * enable and activate long mode; @@ -125,16 +120,26 @@ MOVL $0xfee00000, BP /* apicbase */ MOVL 0x20(BP), BP /* Id */ SHRL $24, BP /* becomes RARG later */ + + MOVL BP, AX /* apicno */ + IMULL $32, AX /* [apicno] */ + MOVL $_real<>-KZERO(SB), BX + ADDL $4096, BX /* sipi */ + ADDL AX, BX /* sipi[apicno] */ //MOVL $_real<>-KZERO(SB), CX //MOVL BX, -4(CX) //_spin: JMP _spin -#ifdef UseOwnPageTables - MOVL $_real<>-KZERO(SB), AX - MOVL -4(AX), SI /* page table PML4 */ -#else - MOVL $(0x00100000+MACHSTKSZ), SI /* page table PML4 */ -#endif + + MOVL 0(BX), SI /* sipi[apicno].pml4 */ + +//MOVL $_real<>-KZERO(SB), CX +//MOVL AX, -4(CX) +//MOVL BX, -8(CX) +//MOVL DX, -12(CX) +//MOVL SI, -16(CX) +//JMP 0(PC) + MOVL SI, AX MOVL AX, CR3 /* load the mmu */ @@ -151,6 +156,7 @@ ADDL $PTSZ, AX /* PD for identity map */ MOVL DX, PDO(0)(AX) /* PDE for identity 0-[24]MiB */ + /* * Enable and activate Long Mode. From the manual: * make sure Page Size Extentions are off, and Page Global @@ -209,10 +215,15 @@ MOVQ AX, SP /* set stack */ + +//MOVQ $_real<>-KZERO(SB), CX +//MOVQ AX, -8(CX) +//JMP 0(PC) + + MOVQ DX, PML4O(0)(AX) /* zap identity map */ MOVQ SI, CR3 /* flush TLB */ -#ifndef UseOwnPageTables /* * SI still points to the base of the bootstrap * processor page tables. @@ -220,27 +231,25 @@ * but want to use the passed-in address for * setting up the stack and Mach. */ - MOVQ $_real<>(SB), AX - MOVL -4(AX), SI /* PML4 */ + + ADDQ $KZERO, BX + MOVL 0(BX), SI /* sipi[apicno].pml4 */ MOVLQZX SI, SI /* PML4-KZERO */ -#endif - MOVQ SI, AX - ADDQ $KZERO, AX /* PML4 and top of stack */ - MOVQ AX, SP /* set stack */ + MOVQ SI, AX + MOVQ 8(BX), SP /* sipi[apicno].stack */ - ADDQ $(4*PTSZ+4*KiB), AX /* PML4+PDP+PD+PT+vsvm */ - MOVQ AX, RMACH /* Mach */ + MOVQ 16(BX), RMACH /* sipi[apicno].mach */ MOVQ DX, RUSER - PUSHQ DX /* clear flags */ + PUSHQ DX /* clear flags */ POPFQ MOVLQZX RARG, RARG /* APIC ID */ PUSHQ RARG /* apicno */ - MOVQ 8(RMACH), AX /* m->splpc */ - CALL* AX /* CALL squidboy(SB) */ + MOVQ 24(BX), AX /* sipi[apicno].pc */ + CALL* AX /* CALL squidboy(SB) */ _ndnr: JMP _ndnr --- /sys/src/nix/k10/l64v.s Thu Apr 12 12:26:28 2012 +++ /sys/src/nix/k10/l64v.s Mon Jun 11 11:15:21 2012 @@ -373,18 +373,21 @@ TEXT k10mwait+0(SB),0,$16 k10mwloop: - MOVQ RARG,CX - MOVQ (CX),AX - CMPQ AX,$0 + MOVQ RARG, CX + MOVQ val+8(FP), DX + MOVQ (CX), AX + CMPQ AX, DX JNE k10mwdone MOVQ RARG, AX /* linear address to monitor */ XORQ CX, CX /* no optional extensions yet */ XORQ DX, DX /* no optional hints yet */ BYTE $0x0f; BYTE $0x01; BYTE $0xc8 /* MONITOR */ - MOVQ RARG,CX + MOVQ RARG, CX MOVQ (CX),AX - CMPQ AX,$0 + MOVQ val+8(FP), DX + CMPQ AX, DX JNE k10mwdone + XORQ DX, DX XORQ CX, CX /* optional extensions */ BYTE $0x0f; BYTE $0x01; BYTE $0xc9 /* MWAIT */ JMP k10mwloop --- /sys/src/nix/k10/lsipi.s Thu Apr 12 12:26:28 2012 +++ /sys/src/nix/k10/lsipi.s Tue May 15 11:18:04 2012 @@ -96,14 +96,8 @@ /* * Protected mode. Welcome to 1982. - * Get the local APIC ID from the memory mapped APIC; -#ifdef UseOwnPageTables - * load the PDB with the page table address, which is located - * in the word immediately preceeding _real<>-KZERO(SB); - * this is also the (physical) address of the top of stack; -#else + * Get the local APIC ID from the memory mapped APIC * load the PML4 with the shared page table address; -#endif * make an identity map for the inter-segment jump below; * enable and activate long mode; * make an inter-segment jump to the long mode code. @@ -126,12 +120,7 @@ MOVL 0x20(BP), BP /* Id */ SHRL $24, BP /* becomes RARG later */ -#ifdef UseOwnPageTables - MOVL $_real<>-KZERO(SB), AX - MOVL -4(AX), SI /* page table PML4 */ -#else MOVL $(0x00100000+MACHSTKSZ), SI /* page table PML4 */ -#endif MOVL SI, AX MOVL AX, CR3 /* load the mmu */ @@ -221,7 +210,6 @@ // MOVQ DX, PDO(0)(AX) /* zap identity map PDE */ MOVQ SI, CR3 /* flush TLB */ -#ifndef UseOwnPageTables /* * SI still points to the base of the bootstrap * processor page tables. @@ -232,7 +220,6 @@ MOVQ $_real<>(SB), AX MOVL -4(AX), SI /* PML4 */ MOVLQZX SI, SI /* PML4-KZERO */ -#endif MOVQ SI, AX ADDQ $KZERO, AX /* PML4 and top of stack */ --- /sys/src/nix/k10/main.c Thu Apr 26 11:22:24 2012 +++ /sys/src/nix/k10/main.c Mon Jun 11 12:50:13 2012 @@ -98,11 +98,8 @@ m->cpumhz = 2000; m->perf.period = 1; - if(!istentacle){ - m->nixtype = NIXAC; - }else{ + if(istentacle) print("TENTACLE %d stack %#p m:%#p\n", m->machno, m->stack, m); - } DBG("Hello Squidboy %d %d\n", apicno, m->machno); @@ -119,13 +116,13 @@ m->cpumhz = hz/1000000ll; mmuinit(); - if(!apiconline()) + if(!apiconline()){ + acmodeset(NIXUC); ndnr(); + } fpuinit(); - acmodeset(m->nixtype); m->splpc = 0; - m->online = 1; /* * CAUTION: no time sync done, etc. @@ -137,13 +134,15 @@ m->rdtsc = rdtsc(); print("cpu%d color %d role %s tsc %lld\n", - m->machno, corecolor(m->machno), rolename[m->nixtype], m->rdtsc); - switch(m->nixtype){ + m->machno, corecolor(m->machno), rolename[m->nnixrole], m->rdtsc); + + switch(m->nnixrole){ case NIXAC: acmmuswitch(); acinit(); adec(&active.nbooting); ainc(&active.nonline); /* this was commented out */ + rolestable(m); acsched(); panic("squidboy"); break; @@ -165,15 +164,17 @@ adec(&active.nbooting); ainc(&active.nonline); + rolestable(m); schedinit(); break; } - panic("squidboy returns (type %d)", m->nixtype); + panic("squidboy returns (type %d)", m->nixrole); } void tentacle(int apicno) { + //m->nixrole = m->nnixrole; ainc(&istentacle); squidboy(apicno); } @@ -187,7 +188,7 @@ /* setup arguments for all */ for(i = 0; i < MACHMAX; i++) - if((mp = sys->machptr[i]) != nil && mp->online && mp->nixtype == NIXAC) + if((mp = sys->machptr[i]) != nil && mp->nixrole == NIXAC) testicc(i); print("bootcore: all cores done\n"); } @@ -207,7 +208,7 @@ uvlong now, start; for(i = 1; i < MACHMAX; i++) - if((mp = sys->machptr[i]) != nil && mp->online){ + if((mp = sys->machptr[i]) != nil && mp->nixrole != NIXUC){ /* * Inter-core calls. A ensure *mp->iccall and mp->icargs * go into different cache lines. @@ -216,10 +217,12 @@ mp->icc->fn = nil; if(i < numtcs){ sys->nmach++; - mp->nixtype = NIXTC; + mp->nixrole = NIXTC; sys->nc[NIXTC]++; - }else + }else{ + mp->nixrole = NIXAC; sys->nc[NIXAC]++; + } ainc(&active.nbooting); } sys->epoch = rdtsc(); @@ -269,9 +272,8 @@ cgapost(sizeof(uintptr)*8); memset(m, 0, sizeof(Mach)); m->machno = 0; - m->online = 1; - acmodeset(NIXTC); + m->nnixrole = NIXTC; sys->machptr[m->machno] = &sys->mach; m->stack = PTR2UINT(sys->machstk); @@ -280,6 +282,8 @@ active.nonline = 1; active.exiting = 0; active.nbooting = 0; + + rolestable(m); asminit(); multiboot(ax, bx, 0); options(oargc, oargv); @@ -531,11 +535,10 @@ lock(&active); if(ispanic) active.ispanic = ispanic; - else if(m->machno == 0 && m->online == 0) + else if(m->machno == 0 && m->nixrole == NIXUC) active.ispanic = 0; - once = m->online; - m->online = 0; - adec(&active.nonline); + once = m->nixrole != NIXUC; + acmodeset(m->nixrole); active.exiting = 1; unlock(&active); --- /sys/src/nix/k10/pmcio.c Fri Apr 20 17:09:28 2012 +++ /sys/src/nix/k10/pmcio.c Mon Jun 11 11:15:38 2012 @@ -307,10 +307,10 @@ static int shouldipi(Mach *mp) { - if(!mp->online) + if(mp->nixrole == NIXUC) return 0; - if(mp->proc == nil && mp->nixtype == NIXAC) + if(mp->proc == nil && mp->nixrole == NIXAC) return 0; return 1; --- /sys/src/nix/k10/sipi.c Thu Apr 26 11:22:24 2012 +++ /sys/src/nix/k10/sipi.c Tue May 15 11:18:28 2012 @@ -9,10 +9,33 @@ #define SIPIHANDLER (KZERO+0x3000) -/* Soft reset a core everything should - * still be there from the original sipi. - * TODO: merge this with sipi -*/ +/* + * Parameters are passed to the bootstrap code via a vector + * in low memory indexed by the APIC number of the processor. + * The layout, size, and location have to be kept in sync + * with the handler code in l64sipi.s. + */ +typedef struct Sipi Sipi; +struct Sipi { + u32int pml4; + u32int _4_; + uintptr stack; + Mach* mach; + uintptr pc; +}; + +enum { + SipiHdlrMaxSz = 4*KiB, +}; + +enum { + INVPCMAGIC = 0x0eeebabe +}; + +/* + * the caller must make sure it has exclusive access to + * the core and it should be quiescent before sipiing it + */ int sipicore(int core) { @@ -20,39 +43,34 @@ uchar nvstate; int i, issuicide; extern void tentacle(int); - uintmem sipipa; - u32int *sipiptr; + Sipi *sipist, *sipi; + u8int *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)); + sipist = (Sipi*)(sipiptr+SipiHdlrMaxSz); + sipi = &sipist[mp->apicno]; + sipi->pc = PTR2UINT(tentacle); + mp->splpc = INVPCMAGIC; - 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); + print("nvram %d should be: %ux, sipied too early?\n", core, nvstate); return -1; } + sipipa = mmuphysaddr(SIPIHANDLER); apicsipi(mp->apicno, sipipa); - for(i = 0; i < 1000; i++){ - if(!issuicide && mp->splpc == 0) + if(!issuicide && mp->splpc != INVPCMAGIC) break; millidelay(5); } @@ -64,15 +82,17 @@ } + void sipiall(void) { Apic *apic; Mach *mach; int apicno, i; - u32int *sipiptr; + u8int *sipiptr; uintmem sipipa; u8int *alloc, *p; + Sipi *sipi, *sipist; extern void squidboy(int); /* @@ -84,8 +104,11 @@ return; sipiptr = UINT2PTR(SIPIHANDLER); memmove(sipiptr, sipihandler, sizeof(sipihandler)); + memset(sipiptr+SipiHdlrMaxSz, 0, sizeof(Sipi)*Napic); DBG("sipiptr %#p sipipa %#llux\n", sipiptr, sipipa); + sipist = (Sipi*)(sipiptr+SipiHdlrMaxSz); + /* * Notes: * The Universal Startup Algorithm described in the MP Spec. 1.4. @@ -98,7 +121,7 @@ apic = &xlapic[apicno]; if(!apic->useable || apic->addr || apic->machno == 0) continue; - + sipi = &sipist[apicno]; /* * NOTE: for now, share the page tables with the * bootstrap processor, until the lsipi code is worked out, @@ -110,8 +133,11 @@ memset(alloc, 0, MACHSTKSZ+4*PTSZ+4*KiB+MACHSZ); p = alloc+MACHSTKSZ; - sipiptr[-1] = mmuphysaddr(PTR2UINT(p)); - DBG("p %#p sipiptr[-1] %#ux\n", p, sipiptr[-1]); + sipi->pml4 = cr3get(); + + + DBG("sipi %#p pml4 %#ux\n", sipi, sipi->pml4); + sipi->stack = PTR2UINT(p); p += 4*PTSZ+4*KiB; @@ -122,12 +148,14 @@ * back into the INIT state? */ mach = (Mach*)p; + sipi->mach = mach; mach->machno = apic->machno; /* NOT one-to-one... */ mach->splpc = PTR2UINT(squidboy); + sipi->pc = mach->splpc; mach->apicno = apicno; mach->stack = PTR2UINT(alloc); mach->vsvm = alloc+MACHSTKSZ+4*PTSZ; -//OH OH mach->pml4 = (PTE*)(alloc+MACHSTKSZ); + mach->pml4 = m->pml4; /* not really needed any more? */ p = KADDR(0x467); *p++ = sipipa; --- /sys/src/nix/k10/tcore.c Thu Apr 26 11:22:24 2012 +++ /sys/src/nix/k10/tcore.c Mon Jun 11 13:01:16 2012 @@ -37,17 +37,20 @@ if(core >= MACHMAX) error("no such core"); mp = sys->machptr[core]; - if(mp == nil || mp->online == 0 || mp->proc != nil) + if(mp == nil || mp->nixrole == NIXUC || mp->proc != nil) error("core not online or busy"); - if(mp->nixtype != NIXAC) + if(mp->nixrole != NIXAC) error("core is not an AC"); Found: mp->proc = p; }else{ for(i = 0; i < MACHMAX; i++) - if((mp = sys->machptr[i]) != nil && mp->online && mp->nixtype == NIXAC) + if((mp = sys->machptr[i]) != nil && mp->nixrole == NIXAC){ + if(isbooting(mp)) + continue; if(mp->proc == nil) goto Found; + } error("not enough cores"); } unlock(&nixaclock); @@ -111,92 +114,125 @@ } + 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; + /* wake it up... */ + mp->nixrole = NIXSC; + mp->icc->fn = acquiesce; coherence(); - while(mp->icc->fn != nil){ + while(mp->icc->fn == acquiesce){ + mwait(&mp->nixrole, NIXSC); } - if(role == NIXOC) + if(role == NIXOC){ + mp->nixrole = role; apicnipi(mp->apicno); - else + }else sipicore(mp->machno); - mp->proc = nil; /*putac? */ } + void tcquiesce(void) { /* sync, suicide is not possible */ - m->nnixtype = NIXROLES; + m->proc = nil; + m->icc->fn = nil; + + /* signal we are done */ + m->nixrole= NIXQC; coherence(); - while(1){ + wakeup(&m->sipir); + for(;;) halt(); - } +} + +void +rolestable(Mach *mp) +{ + mp->nixrole = mp->nnixrole; + coherence(); } int +isbooting(Mach *mp) +{ + return mp->nixrole == NIXQC || mp->nixrole == NIXSC; +} + +static int +donequiesce(void *x) +{ + Mach *mp; + mp = (Mach *)x; + return mp->nixrole == NIXQC; +} + +/* + * what should happen if you are wired and the core dissapears? + * for now, this is for testing and it executes in the context of + * a process (it shouldn't) + */ +int changerole(int role, int core) { - int apicno, i; - Mach *mp, *w; + int apicno; + Mach *mp, *mpc, *w; /* - * Must run in a TC, is this the way? + * 1 *has* to be a TC. */ - 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) + mpc = sys->machptr[1]; + if(core == 1 || core >= MACHMAX || !mpc->nixrole == NIXTC) return -1; - w = up->wired; - procwired(up, i); - if(m != sys->machptr[0]) + procwired(up, 1); + if(m != mpc) sched(); mp = sys->machptr[core]; - if(m == mp){ - up->wired = w; - print("SUICIDE IS NOT ALLOWED\n"); + + lock(&mp->sipilock); + apicno = mp->apicno; + if(isbooting(mp) && mp->nixrole != NIXOC){ + print("core is already rebooting, nnixrole %#ux\n", mp->nnixrole); + unlock(&mp->sipilock); return -1; } - - apicno = mp->apicno; - mp->nnixtype = role; - switch(mp->nixtype){ + mp->nnixrole = role; + unlock(&mp->sipilock); + switch(mp->nixrole){ case NIXAC: - lock(&nixaclock); /* is this the right lock to keep? */ + lock(&nixaclock); /* so noone reassigns the core */ if(mp->proc != nil){ mp->proc->procctl = Proc_totc; + unlock(&nixaclock); apicipi(apicno); }else{ + unlock(&nixaclock); roleac(mp, role); } - unlock(&nixaclock); /* is the lock taken too long? */ break; case NIXTC: - mp->qexpired = 1; /* may need to wakeup idlehands */ + mp->nixrole = NIXSC; + mp->qexpired = 1; coherence(); - while(mp->nnixtype != NIXROLES){}; + /* when idlehands sleeps, this needs to send a wake it up IPI? */ + //this breaks the core now... (ipi a TC?) apicipi(mp->apicno); + sleep(&mp->sipir, donequiesce, mp); + /* fall */ case NIXOC: - mp->nixtype = role; - mp->nnixtype = NIXROLES; + mp->nnixrole = role; coherence(); - if(role == NIXOC) + if(role == NIXOC){ + mp->proc = nil; + mp->nixrole = NIXOC; apicnipi(mp->apicno); - else + }else sipicore(mp->machno); - mp->proc = nil; break; default: print("don't know how to change my role\n"); @@ -229,7 +265,7 @@ if (n > sizeof(mp->icc->data)) panic("runac: args too long"); - if(mp->online == 0) + if(mp->nixrole == NIXUC) panic("Bad core"); if(mp->proc != nil && mp->proc != up) panic("runapfunc: mach is busy with another proc?"); @@ -252,16 +288,11 @@ mp->icc->rc = ICCOK; DBG("runac: exotic proc on cpu%d\n", mp->machno); - if(waserror()){ - qunlock(&up->debug); - nexterror(); - } qlock(&up->debug); up->nicc++; up->state = Exotic; up->psstate = 0; qunlock(&up->debug); - poperror(); coherence(); mp->icc->fn = func; sched(); @@ -408,8 +439,8 @@ * be back in the TC */ DBG("runacore: up %#p: return\n", up); - if(ac->nnixtype != NIXROLES){ - roleac(ac, ac->nnixtype); + if(isbooting(ac)){ + roleac(ac, ac->nnixrole); } } --- /sys/src/nix/k10/trap.c Thu Apr 12 12:26:28 2012 +++ /sys/src/nix/k10/trap.c Fri Jun 8 12:00:51 2012 @@ -293,7 +293,7 @@ else mp = m; tos->core = mp->machno; - tos->nixtype = mp->nixtype; + tos->nixtype = mp->nixrole; _pmcupdate(m); /* * The process may change its core. @@ -336,7 +336,7 @@ m->perf.intrts = perfticks(); user = userureg(ureg); - if(user && (m->nixtype == NIXTC)){ + if(user && (m->nixrole == NIXTC)){ up->dbgreg = ureg; cycles(&up->kentry); } --- /sys/src/nix/k10/vsvm.c Thu Apr 12 12:26:28 2012 +++ /sys/src/nix/k10/vsvm.c Fri Jun 8 12:00:51 2012 @@ -146,7 +146,7 @@ } void -vsvminit(int size, int nixtype) +vsvminit(int size, int nixrole) { Sd *sd; u64int r; @@ -166,7 +166,7 @@ tssinit(m->stack+size); gdtput(sizeof(gdt64)-1, PTR2UINT(m->gdt), SSEL(SiCS, SsTIGDT|SsRPL0)); - if(nixtype != NIXAC) + if(nixrole != NIXAC) idtput(sizeof(idt64)-1, PTR2UINT(idt64)); else idtput(sizeof(acidt64)-1, PTR2UINT(acidt64)); @@ -182,7 +182,7 @@ r = ((u64int)SSEL(SiU32CS, SsRPL3))<<48; r |= ((u64int)SSEL(SiCS, SsRPL0))<<32; wrmsr(Star, r); - if(nixtype != NIXAC) + if(nixrole != NIXAC) wrmsr(Lstar, PTR2UINT(syscallentry)); else wrmsr(Lstar, PTR2UINT(acsyscallentry)); --- /sys/src/nix/port/devcons.c Thu Apr 12 12:26:28 2012 +++ /sys/src/nix/port/devcons.c Mon Jun 11 11:15:57 2012 @@ -103,6 +103,21 @@ CMpanic, "panic", 0, }; +/* role debugging */ +enum +{ + CMoc, + CMac, + CMtc, +}; + +Cmdtab rolemsg[] = +{ + CMoc, "oc", 2, + CMac, "ac", 2, + CMtc, "tc", 2, +}; + /* To keep the rest of the kernel unware of new consdevs for now */ static void kprintputs(char *s, int n) @@ -948,7 +963,7 @@ bp = b; e = bp + n; for(id = 0; id < MACHMAX; id++) - if((mp = sys->machptr[id]) != nil && mp->online){ + if((mp = sys->machptr[id]) != nil && mp->nixrole != NIXUC){ readnum(0, bp, NUMSIZE, mp->machno, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->cs, NUMSIZE); @@ -975,7 +990,7 @@ bp += NUMSIZE; readnum(0, bp, NUMSIZE, 0, NUMSIZE); /* sched # */ bp += NUMSIZE; - bp = strecpy(bp, e, rolename[mp->nixtype]); + bp = strecpy(bp, e, rolename[mp->nixrole]); *bp++ = '\n'; } if(waserror()){ @@ -1038,6 +1053,25 @@ return -1; /* never reached */ } +/* role debugging */ +static int +cmrole(int cm) +{ + switch(cm) { + case CMtc: + return NIXTC; + break; + case CMoc: + return NIXOC; + case CMac: + return NIXAC; + break; + } + return NIXAC; +} + + + static long conswrite(Chan *c, void *va, long n, vlong off) { @@ -1045,7 +1079,7 @@ long l, bp; char *a; Mach *mp; - int i; + int i, core, role; ulong offset; Cmdbuf *cb; Cmdtab *ct; @@ -1141,7 +1175,7 @@ case Qsysstat: for(i = 0; i < MACHMAX; i++) - if((mp = sys->machptr[i]) != nil && mp->online){ + if((mp = sys->machptr[i]) != nil && mp->nixrole != NIXUC){ mp = sys->machptr[i]; mp->cs = 0; mp->intr = 0; @@ -1180,13 +1214,25 @@ break; case Qdebug: - if(n >= sizeof(buf)) - n = sizeof(buf)-1; - strncpy(buf, a, n); - buf[n] = 0; - if(n > 0 && buf[n-1] == '\n') - buf[n-1] = 0; - error(Ebadctl); + /* role debugging for now */ + if(!iseve()) + error(Eperm); + cb = parsecmd(a, n); + if(waserror()) { + free(cb); + nexterror(); + } + if(cb->nf != 2) + error(Ecmdargs); + core = strtoul(cb->f[1], 0, 0); + + ct = lookupcmd(cb, rolemsg, nelem(rolemsg)); + role = cmrole(ct->index); + l = changerole(role, core); + if(l < 0) + error(Ebadarg); + poperror(); + free(cb); break; default: print("conswrite: %#llux\n", c->qid.path); --- /sys/src/nix/port/devpmc.c Thu Apr 12 12:26:28 2012 +++ /sys/src/nix/port/devpmc.c Mon Jun 11 11:16:03 2012 @@ -115,7 +115,7 @@ ncores = 0; nr = pmcnregs(); for(i = 0; i < MACHMAX; i++) - if((mp = sys->machptr[i]) != nil && mp->online){ + if((mp = sys->machptr[i]) != nil && mp->nixrole != NIXUC){ ncores++; for(j = 0; j < nr; j++) pmcnull(&mp->pmc[j]); --- /sys/src/nix/port/lib.h Fri Jun 8 11:35:42 2012 +++ /sys/src/nix/port/lib.h Mon Jun 11 12:54:55 2012 @@ -166,11 +166,14 @@ */ enum { - NIXTC = 0, - NIXKC, - NIXAC, - NIXXC, - NIXOC, + NIXTC = 0, /* time shared */ + NIXKC, /* kernel */ + NIXAC, /* application */ + NIXXC, /* exclusive */ + NIXOC, /* offline */ + NIXUC, /* uninitalized */ + NIXSC, /* stopping */ + NIXQC, /* quiescent */ NIXROLES, }; --- /sys/src/nix/port/portclock.c Thu Apr 12 12:26:29 2012 +++ /sys/src/nix/port/portclock.c Mon Jun 11 11:16:18 2012 @@ -166,7 +166,7 @@ if(kproftimer != nil) kproftimer(pc); - if(m->online == 0) + if(m->nixrole == NIXUC) return; if(active.exiting) { --- /sys/src/nix/port/portfns.h Fri Jun 8 11:35:45 2012 +++ /sys/src/nix/port/portfns.h Mon Jun 11 11:16:25 2012 @@ -193,7 +193,7 @@ ulong ms2tk(ulong); void mul64fract(uvlong*, uvlong, uvlong); void muxclose(Mnt*); -void (*mwait)(void *); +void (*mwait)(void *, int); Chan* namec(char*, int, int, int); void nameerror(char*, char*); Chan* newchan(void); @@ -240,7 +240,7 @@ void* phystag(uintmem); void pio(Segment*, uintptr, ulong, Page**, int); #define poperror() up->nerrlab-- -void portmwait(void*); +void portmwait(void*, int); int postnote(Proc*, int, char*, int); int pprint(char*, ...); int preempted(void); --- /sys/src/nix/port/proc.c Fri Jun 8 11:35:49 2012 +++ /sys/src/nix/port/proc.c Mon Jun 11 12:36:41 2012 @@ -251,6 +251,11 @@ /* unless preempted, get to run */ if(m->qexpired && anyready()) up->delaysched++; + + /* BUG, not enough if the number of cores can change */ + if(isbooting(m) && sys->nmach > AMPmincores) + sched(); + } /* @@ -570,9 +575,11 @@ for(rr = 0; rr < 2; rr++) for(i = 0; i < MACHMAX; i++){ j = pickcore(p->color, i); - if((mp = sys->machptr[j]) != nil && mp->online && mp->nixtype == NIXTC){ + if((mp = sys->machptr[j]) != nil && mp->nixrole == NIXTC){ if(mp == m) continue; + if(isbooting(mp)) + continue; /* * Caution here: mp->proc can change, even die. */ @@ -658,9 +665,12 @@ }else{ for(i = 0; i < MACHMAX; i++){ j = pickcore(p->color, i); - if((mp = sys->machptr[j]) != nil && mp->online && mp->nixtype == NIXTC) + if((mp = sys->machptr[j]) != nil && mp->nixrole == NIXTC){ + if(isbooting(mp)) + continue; if(mp != m && mp->proc == nil) break; + } } if(i == MACHMAX){ preemptfor(p); @@ -703,6 +713,8 @@ * time around the loop affinity goes down. */ spllo(); + if(isbooting(m)) + tcquiesce(); for(i = 0;; i++){ /* * find the highest priority target process that this @@ -719,6 +731,8 @@ /* waste time or halt the CPU */ idlehands(); + if(isbooting(m)) + tcquiesce(); /* remember how much time we're here */ now = perfticks(); m->perf.inidle += now-start; @@ -768,8 +782,15 @@ if(m->machno != 0){ do{ spllo(); - while(m->proc == nil) + while(m->proc == nil){ + if(isbooting(m)){ + coherence(); + if(m->proc != nil) + break; + tcquiesce(); + } idlehands(); + } now = perfticks(); m->perf.inidle += now-start; start = now; @@ -1011,7 +1032,6 @@ * here when the process is awakened */ procrestore(up); - spllo(); } else { /* * here to go to sleep (i.e. stop Running) @@ -1539,7 +1559,7 @@ if(p->seg[ns] == s){ p->newtlb = 1; for(nm = 0; nm < MACHMAX; nm++) - if((mp = sys->machptr[nm]) != nil && mp->online) + if((mp = sys->machptr[nm]) != nil && mp->nixrole != NIXUC) if(mp->proc == p){ mp->mmuflush = 1; nwait++; @@ -1561,7 +1581,7 @@ * using this segment. */ for(i = 0; i < MACHMAX; i++) - if((mp = sys->machptr[i]) != nil && mp->online) + if((mp = sys->machptr[i]) != nil && mp->nixrole != NIXUC) if(mp != m) while(mp->mmuflush) sched(); @@ -1687,6 +1707,8 @@ * the process gets moved back to a TC.) */ spllo(); + if(p->ac == nil) + getac(p, -1); runacore(); return; --- /sys/src/nix/port/taslock.c Thu Apr 12 12:26:29 2012 +++ /sys/src/nix/port/taslock.c Mon Jun 11 11:17:33 2012 @@ -314,10 +314,10 @@ } void -portmwait(void *value) +portmwait(void *value, int val) { - while (*(void**)value == nil) + while (*(void**)value == (void *)val) ; } -void (*mwait)(void *) = portmwait; +void (*mwait)(void *, int) = portmwait; --- /sys/src/nix/port/tcklock.c Thu Apr 12 12:26:29 2012 +++ /sys/src/nix/port/tcklock.c Mon Jun 11 11:17:39 2012 @@ -321,10 +321,10 @@ } void -portmwait(void *value) +portmwait(void *value, int val) { - while (*(void**)value == nil) + while (*(void**)value == val) ; } -void (*mwait)(void *) = portmwait; +void (*mwait)(void *, int) = portmwait;