void pmcupdate(Mach *m) { PmcCtr *p; int i, maxct, wk; PmcWait *w; return; maxct = pmcnregs(); for (i = 0; i < maxct; i++) { p = &m->pmc[i]; ilock(&m->pmclock); if(p->ctrset & PmcSet) setctr(p->ctr, i); if(p->ctlset & PmcSet) setctl(&p->PmcCtl, i); p->ctr = getctr(i); getctl(&p->PmcCtl, i); p->ctrset = PmcIgn; p->ctlset = PmcIgn; wk = p->stale; p->stale = 0; if(wk){ for(w = p->wq; w != nil; w = w->next){ p->wq = w->next; wakeup(&w->rend); pmcwclose(w); } } iunlock(&m->pmclock); } }
static void ctrdirinit(void) { int nr, i; Dirtab *d; nr = pmcnregs(); npmctab = 1 + 2*nr; pmctab = malloc(npmctab * sizeof(Dirtab)); if (pmctab == nil){ free(toptab); toptab = nil; return; } d = pmctab; strncpy(d->name, ".", KNAMELEN); mkqid(&d->qid, Qctr, 0, QTDIR); d->perm = DMDIR|0555; for (i = 1; i < nr + 1; i++) { d = &pmctab[i]; snprint(d->name, KNAMELEN, "ctr%2.2ud", i - 1); mkqid(&d->qid, PMCQID(i - 1, Qdata), 0, 0); d->perm = 0600; d = &pmctab[nr + i]; snprint(d->name, KNAMELEN, "ctr%2.2udctl", i - 1); mkqid(&d->qid, PMCQID(i - 1, Qctl), 0, 0); d->perm = 0600; } }
static int setctl(PmcCtl *p, int regno) { uint64_t v, e, u; char *toks[2]; char str[KNAMELEN]; if (regno >= pmcnregs()) error("invalid reg"); v = rdmsr(regno + PerfEvtbase); v &= PeEvMskH|PeEvMskL|PeCtEna|PeOS|PeUsr|PeUnMsk; if (p->enab != PmcCtlNullval) if (p->enab) v |= PeCtEna; else v &= ~PeCtEna; if (p->user != PmcCtlNullval) if (p->user) v |= PeUsr; else v &= ~PeUsr; if (p->os != PmcCtlNullval) if (p->os) v |= PeOS; else v &= ~PeOS; if (pmctrans(p) < 0) return -1; if (p->nodesc == 0) { memmove(str, p->descstr, KNAMELEN); if (tokenize(str, toks, 2) != 2) return -1; e = atoi(toks[0]); u = atoi(toks[1]); v &= ~(PeEvMskL|PeEvMskH|PeUnMsk); v |= SetEvMsk(v, e); v |= SetUMsk(v, u); } if (p->reset != PmcCtlNullval && p->reset) { v = 0; wrmsr(regno+ PerfCtrbase, 0); p->reset = PmcCtlNullval; /* only reset once */ } wrmsr(regno+ PerfEvtbase, v); pmcuserenab(pmcanyenab()); if (pmcdebug) { v = rdmsr(regno+ PerfEvtbase); print("conf pmc[%#ux]: %#llux\n", regno, v); } return 0; }
int pmcanyenab(void) { int i; PmcCtl p; for (i = 0; i < pmcnregs(); i++) { if (getctl(&p, i) < 0) return -1; if (p.enab) return 1; } return 0; }
static void pmcinit(void) { int i, j, ncores, nr; Mach *mp; _pmcupdate = pmcupdate; ncores = 0; nr = pmcnregs(); for(i = 0; i < MACHMAX; i++) if((mp = sys->machptr[i]) != nil && mp->online){ ncores++; for(j = 0; j < nr; j++) pmcnull(&mp->pmc[j]); } topdirinit(ncores); ctrdirinit(); }