/* * 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); }
static int32_t pmcwrite(Chan *c, void *a, int32_t n, int64_t mm) { Proc *up = externup(); Cmdbuf *cb; Cmdtab *ct; uint32_t type; char str[64]; /* 0x0000000000000000\0 */ AcPmcArg p; AcCtrArg ctr; uint64_t coreno; Mach *mp; if (c->qid.type == QTDIR) error(Eperm); if (c->qid.path == Qgctl) error(Eperm); if (n >= sizeof(str)) error(Ebadctl); pmcnull(&p); coreno = (uint64_t)c->aux; p.coreno = coreno; type = PMCTYPE(c->qid.path); p.regno = PMCID(c->qid.path); memmove(str, a, n); str[n] = '\0'; mp = up->ac; ctr.coreno = coreno; ctr.regno = p.regno; if (type == Qdata) { /* I am a handler for a proc in the core, run an RPC*/ if (mp != nil && mp->machno == coreno) { if (runac(mp, acpmcsetctr, 0, &ctr, sizeof(AcCtrArg)) < 0) n = -1; } else { if (pmcsetctr(coreno, strtoull(str, 0, 0), p.regno) < 0) n = -1; } return n; } /* TODO: should iterate through multiple lines */ if (strncmp(str, "set ", 4) == 0){ memmove(p.descstr, (char *)str + 4, n - 4); p.descstr[n - 4] = '\0'; p.nodesc = 0; } else { cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } ct = lookupcmd(cb, pmcctlmsg, nelem(pmcctlmsg)); switch(ct->index){ case Enable: p.enab = 1; break; case Disable: p.enab = 0; break; case User: p.user = 1; break; case Os: p.os = 1; break; case NoUser: p.user = 0; break; case NoOs: p.os = 0; break; case Reset: p.reset = 1; break; case Debug: pmcdebug = ~pmcdebug; break; default: cmderror(cb, "invalid ctl"); break; } free(cb); poperror(); } /* I am a handler for a proc in the core, run an RPC*/ if (mp != nil && mp->machno == coreno) { if (runac(mp, acpmcsetctl, 0, &p, sizeof(AcPmcArg)) < 0) n = -1; } else { if (pmcsetctl(coreno, &p, p.regno) < 0) n = -1; } return n; }