/* * Rendezvous with other cores. Set roles for those that came * up online, and wait until they are initialized. * Sync TSC with them. * We assume other processors that could boot had time to * set online to 1 by now. */ static void nixsquids(void) { Mach *mp; int i; uvlong now, start; for(i = 1; i < MACHMAX; i++) if((mp = sys->machptr[i]) != nil && mp->online != 0){ /* * Inter-core calls. A ensure *mp->iccall and mp->icargs * go into different cache lines. */ mp->icc = mallocalign(sizeof *m->icc, ICCLNSZ, 0, 0); mp->icc->fn = nil; if(i < initialTCs){ conf.nmach++; mp->nixtype = NIXTC; } ainc(&active.nbooting); } sys->epoch = rdtsc(); mfence(); wrmsr(0x10, sys->epoch); m->rdtsc = rdtsc(); active.thunderbirdsarego = 1; start = fastticks2us(fastticks(nil)); do{ now = fastticks2us(fastticks(nil)); }while(active.nbooting > 0 && now - start < 1000000) ; if(active.nbooting > 0) print("cpu0: %d cores couldn't start\n", active.nbooting); active.nbooting = 0; }
ulong µs(void) { if(SystimerFreq != 1*Mhz) return fastticks2us(fastticks(nil)); return fastticks(nil); }
ulong µs(void) { if(SystimerFreq != 1*Mhz) return fastticks2us(fastticks(nil)); return ((Systimers*)SYSTIMERS)->clo; }
/* * Called in AP core context, to return from system call. */ void acsysret(void) { panic("acsysret"); #if 0 DBG("acsysret\n"); if(m->proc != nil) m->proc->actime += fastticks2us(fastticks(nil) - m->proc->actime1); _acsysret(); #endif }
/* * Rendezvous with other cores. Set roles for those that came * up online, and wait until they are initialized. * Sync TSC with them. * We assume other processors that could boot had time to * set online to 1 by now. */ static void nixsquids(void) { Mach *m = machp(); Mach *mp; int i; uint64_t now, start; /* Not AC for now :-) */ for(i = 1; i <= MACHMAX; i++) //for(i = 1; i < MACHMAX; i++) if((mp = sys->machptr[i]) != nil && mp->online){ /* * Inter-core calls. A ensure *mp->iccall and mp->icargs * go into different cache lines. */ mp->icc = mallocalign(sizeof *m->icc, ICCLNSZ, 0, 0); mp->icc->fn = nil; if(i < numtcs){ sys->nmach++; mp->nixtype = NIXTC; sys->nc[NIXTC]++; }//else //sys->nc[NIXAC]++; ainc(&active.nbooting); } sys->epoch = rdtsc(); mfence(); wrmsr(0x10, sys->epoch); m->rdtsc = rdtsc(); active.thunderbirdsarego = 1; start = fastticks2us(fastticks(nil)); do{ now = fastticks2us(fastticks(nil)); }while(active.nbooting > 0 && now - start < 1000000) ; if(active.nbooting > 0) print("cpu0: %d cores couldn't start\n", active.nbooting); active.nbooting = 0; }
ulong µs(void) { return fastticks2us(fastticks(nil)); }
/* * Entered in AP core context, upon traps (system calls go through acsyscall) * using up->dbgreg means cores MUST be homogeneous. * * BUG: We should setup some trapenable() mechanism for the AC, * so that code like fpu.c could arrange for handlers specific for * the AC, instead of doint that by hand here. * * All interrupts are masked while in the "kernel" */ void actrap(Ureg *u) { panic("actrap"); #if 0 char *n; ACVctl *v; n = nil; _pmcupdate(m); if(m->proc != nil){ m->proc->nactrap++; m->proc->actime1 = fastticks(nil); } if(u->type < nelem(acvctl)){ v = acvctl[u->type]; if(v != nil){ DBG("actrap: cpu%d: %ulld\n", machp()->machno, u->type); n = v->f(u, v->a); if(n != nil) goto Post; return; } } switch(u->type){ case IdtDF: print("AC: double fault\n"); dumpregs(u); ndnr(); case IdtIPI: m->intr++; DBG("actrap: cpu%d: IPI\n", machp()->machno); apiceoi(IdtIPI); break; case IdtTIMER: apiceoi(IdtTIMER); panic("timer interrupt in an AC"); break; case IdtPF: /* this case is here for debug only */ m->pfault++; DBG("actrap: cpu%d: PF cr2 %#ullx\n", machp()->machno, cr2get()); break; default: print("actrap: cpu%d: %ulld\n", machp()->machno, u->type); } Post: m->icc->rc = ICCTRAP; m->cr2 = cr2get(); memmove(m->proc->dbgreg, u, sizeof *u); m->icc->note = n; fpuprocsave(m->proc); _pmcupdate(m); mfence(); m->icc->fn = nil; ready(m->proc); mwait(&m->icc->fn); if(m->icc->flushtlb) acmmuswitch(); if(m->icc->fn != actrapret) acsched(); DBG("actrap: ret\n"); memmove(u, m->proc->dbgreg, sizeof *u); if(m->proc) m->proc->actime += fastticks2us(fastticks(nil) - m->proc->actime1); #endif }
/* * Move the current process to an application core. * This is performed at the end of execac(), and * we pretend to be returning to user-space, but instead we * dispatch the process to another core. * 1. We do the final bookkeeping that syscall() would do after * a return from sysexec(), because we are not returning. * 2. We dispatch the process to an AC using an ICC. * * This function won't return unless the process is reclaimed back * to the time-sharing core, and is the handler for the process * to deal with traps and system calls until the process dies. * * Remember that this function is the "line" between user and kernel * space, it's not expected to raise|handle any error. * * We install a safety error label, just in case we raise errors, * which we shouldn't. (noerrorsleft knows that for exotic processes * there is an error label pushed by us). */ void runacore(void) { Proc *up = externup(); Ureg *ureg; void (*fn)(void); int rc, flush, s; char *n; uint64_t t1; if(waserror()) panic("runacore: error: %s\n", up->errstr); ureg = up->dbgreg; fakeretfromsyscall(ureg); fpusysrfork(ureg); procpriority(up, PriKproc, 1); rc = runac(up->ac, actouser, 1, nil, 0); procpriority(up, PriNormal, 0); for(;;){ t1 = fastticks(nil); flush = 0; fn = nil; switch(rc){ case ICCTRAP: s = splhi(); machp()->MMU.cr2 = up->ac->MMU.cr2; DBG("runacore: trap %llu cr2 %#llx ureg %#p\n", ureg->type, machp()->MMU.cr2, ureg); switch(ureg->type){ case IdtIPI: if(up->procctl || up->nnote) notify(up->dbgreg); if(up->ac == nil) goto ToTC; kexit(up->dbgreg); break; case IdtNM: case IdtMF: case IdtXF: /* these are handled in the AC; * If we get here, they left in m->NIX.icc->data * a note to be posted to the process. * Post it, and make the vector a NOP. */ n = up->ac->NIX.icc->note; if(n != nil) postnote(up, 1, n, NDebug); ureg->type = IdtIPI; /* NOP */ break; default: cr3put(machp()->MMU.pml4->pa); if(0 && ureg->type == IdtPF){ print("before PF:\n"); print("AC:\n"); dumpptepg(4, up->ac->MMU.pml4->pa); print("\n%s:\n", rolename[NIXTC]); dumpptepg(4, machp()->MMU.pml4->pa); } trap(ureg); } splx(s); flush = 1; fn = actrapret; break; case ICCSYSCALL: DBG("runacore: syscall ax %#llx ureg %#p\n", ureg->ax, ureg); cr3put(machp()->MMU.pml4->pa); //syscall(ureg->ax, ureg); flush = 1; fn = acsysret; if(0) if(up->nqtrap > 2 || up->nsyscall > 1) goto ToTC; if(up->ac == nil) goto ToTC; break; default: panic("runacore: unexpected rc = %d", rc); } up->tctime += fastticks2us(fastticks(nil) - t1); procpriority(up, PriExtra, 1); rc = runac(up->ac, fn, flush, nil, 0); procpriority(up, PriNormal, 0); } ToTC: /* * to procctl, then syscall, to * be back in the TC */ DBG("runacore: up %#p: return\n", up); }
uint32_t ms(void) { return fastticks2us(rdtsc()); }