# HG changeset patch # User Gorka Guardiola # Date 1326835564 28800 # Node ID 03bf4c5fe96acb1bd824ff96f8a24b3e61dc3f4d # Parent afa3c6e9b9949f832665053c15b24a95dd8bb7d5 pmc: fix various issues R=nixiedev, rminnich CC=nix-dev http://codereview.appspot.com/5539072 Committer: John Floren diff -r afa3c6e9b994 -r 03bf4c5fe96a sys/man/3/pmc --- a/sys/man/3/pmc Fri Dec 09 11:02:28 2011 -0800 +++ b/sys/man/3/pmc Tue Jan 17 13:26:04 2012 -0800 @@ -40,10 +40,16 @@ feature it has. .TP .B user -The counter only runs when the processor is in user space. +and +.B nouser +Enable and or disable whether the counter only +runs when the processor is in user space. .TP .B os -The counter only runs when the processor is in the kernel. +and +.B noos +Enable and or disable whether the counter only +runs when the processor is in the kernel. .TP .BI "set configuration Sets the counter configuration. The detail of what the configuration @@ -80,17 +86,19 @@ L2 ITLB miss DRAM access L3 miss - % echo reset > /dev/core0000/ctr00ctl - % echo kernel > /dev/core0000/ctr00ctl - % echo set L2 miss > /dev/core0000/ctr00ctl - % echo enable > /dev/core0000/ctr00ctl - % cat /dev/core0000/ctr00 + echo reset > /dev/core0001/ctr00ctl + echo os > /dev/core0001/ctr00ctl + echo nouser > /dev/core0001/ctr00ctl + echo set L2 miss > /dev/core0001/ctr00ctl + echo 0 > /dev/core0001/ctr00 + echo enable > /dev/core0001/ctr00ctl + cat /dev/core0001/ctr00 0x00000000000003e5 % .EE .SH "SEE ALSO .IR pmc (2) .SH SOURCE -.B /sys/src/9/port/pmc.h -.B /sys/src/9/port/devpmc.c -.B /sys/src/9/k8/pmcio.c +.B /sys/src/nix/port/pmc.h +.B /sys/src/nix/port/devpmc.c +.B /sys/src/nix/k10/pmcio.c diff -r afa3c6e9b994 -r 03bf4c5fe96a sys/src/nix/k10/acore.c --- a/sys/src/nix/k10/acore.c Fri Dec 09 11:02:28 2011 -0800 +++ b/sys/src/nix/k10/acore.c Tue Jan 17 13:26:04 2012 -0800 @@ -150,7 +150,7 @@ } /* - * Entered in AP core context, upon traps and system calls. + * 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, @@ -240,12 +240,14 @@ */ DBG("acsyscall: cpu%d\n", m->machno); + _pmcupdate(m); p = m->proc; p->actime1 = fastticks(nil); m->syscall++; /* would also count it in the TS core */ m->icc->rc = ICCSYSCALL; m->cr2 = cr2get(); fpuprocsave(p); + _pmcupdate(m); mfence(); m->icc->fn = nil; ready(p); diff -r afa3c6e9b994 -r 03bf4c5fe96a sys/src/nix/k10/dat.h --- a/sys/src/nix/k10/dat.h Fri Dec 09 11:02:28 2011 -0800 +++ b/sys/src/nix/k10/dat.h Tue Jan 17 13:26:04 2012 -0800 @@ -18,6 +18,7 @@ typedef struct PFPU PFPU; typedef struct PmcCtr PmcCtr; typedef struct PmcCtl PmcCtl; +typedef struct PmcWait PmcWait; typedef struct PMMU PMMU; typedef struct PNOTIFY PNOTIFY; typedef u64int PTE; @@ -44,7 +45,7 @@ struct Lock { union{ - u64int key; + u64int key; struct{ u32int ticket; u32int users; @@ -217,9 +218,14 @@ int reset; }; +struct PmcWait{ + Rendez r; + PmcWait* next; +}; + struct PmcCtr{ int stale; - Rendez r; + PmcWait *wq; u64int ctr; int ctrset; PmcCtl; diff -r afa3c6e9b994 -r 03bf4c5fe96a sys/src/nix/k10/pmcio.c --- a/sys/src/nix/k10/pmcio.c Fri Dec 09 11:02:28 2011 -0800 +++ b/sys/src/nix/k10/pmcio.c Tue Jan 17 13:26:04 2012 -0800 @@ -12,7 +12,8 @@ #include "../port/pmc.h" -/* non portable, for intel will be CPUID.0AH.EDX */ +/* non portable, for intel will be CPUID.0AH.EDX + */ enum { PeNreg = 4, /* Number of Pe/Pct regs */ @@ -50,7 +51,7 @@ } PmcCtlCtrId pmcids[] = { - {"locked instr", "0x024 0x0"}, + {"locked instr", "0x024 0x1"}, {"SMI intr", "0x02b 0"}, {"data access", "0x040 0x0"}, {"data miss", "0x041 0x0"}, @@ -223,7 +224,7 @@ return 0; } -int +static int notstale(void *x) { PmcCtr *p; @@ -231,26 +232,57 @@ return !p->stale; } +/* + * As it is now, it sends an ipi if the proccessor is an ocuppied AC or a TC + * to update the counter, in case the processor is idle. Probably not needed for TC + * as it will be updated every time we cross the kernel boundary, but we are doing + * it now just in case it is idle or not being updated + * NB: this function releases the ilock + */ +static void +waitnotstale(Mach *mp, PmcCtr *p) +{ + PmcWait *w; + + w = malloc(sizeof (PmcWait)); + w->next = p->wq; + p->wq = w; + iunlock(&mp->pmclock); + apicipi(mp->apicno); + sleep(&w->r, notstale, p); + free(w); +} + u64int pmcgetctr(u32int coreno, u32int regno) { PmcCtr *p; Mach *mp; + u64int v; - if(coreno == m->machno) - return getctr(regno); + if(coreno == m->machno){ + v = getctr(regno); + if (pmcdebug) { + print("int getctr[%#ux, %#ux] = %#llux\n", regno, coreno, v); + } + return v; + } mp = sys->machptr[coreno]; p = &mp->pmc[regno]; - ilock(&m->pmclock); + ilock(&mp->pmclock); p->ctrset |= PmcGet; p->stale = 1; - iunlock(&m->pmclock); if(mp->proc != nil || mp->nixtype != NIXAC){ - apicipi(mp->apicno); - sleep(&p->r, notstale, p); + waitnotstale(mp, p); + ilock(&mp->pmclock); } - return p->ctr; + v = p->ctr; + iunlock(&mp->pmclock); + if (pmcdebug) { + print("ext getctr[%#ux, %#ux] = %#llux\n", regno, coreno, v); + } + return v; } int @@ -259,20 +291,26 @@ PmcCtr *p; Mach *mp; - if(coreno == m->machno) + if(coreno == m->machno){ + if (pmcdebug) { + print("int getctr[%#ux, %#ux] = %#llux\n", regno, coreno, v); + } return setctr(v, regno); + } mp = sys->machptr[coreno]; p = &mp->pmc[regno]; - ilock(&m->pmclock); + if (pmcdebug) { + print("ext setctr[%#ux, %#ux] = %#llux\n", regno, coreno, v); + } + ilock(&mp->pmclock); p->ctr = v; p->ctrset |= PmcSet; p->stale = 1; - iunlock(&m->pmclock); - if(mp->proc != nil || mp->nixtype != NIXAC){ - apicipi(mp->apicno); - sleep(&p->r, notstale, p); - } + if(mp->proc != nil || mp->nixtype != NIXAC) + waitnotstale(mp, p); + else + iunlock(&mp->pmclock); return 0; } @@ -302,15 +340,14 @@ mp = sys->machptr[coreno]; p = &mp->pmc[regno]; - ilock(&m->pmclock); + ilock(&mp->pmclock); ctl2ctl(&p->PmcCtl, pctl); p->ctlset |= PmcSet; p->stale = 1; - iunlock(&m->pmclock); - if(mp->proc != nil || mp->nixtype != NIXAC){ - apicipi(mp->apicno); - sleep(&p->r, notstale, p); - } + if(mp->proc != nil || mp->nixtype != NIXAC) + waitnotstale(mp, p); + else + iunlock(&mp->pmclock); return 0; } @@ -326,17 +363,15 @@ mp = sys->machptr[coreno]; p = &mp->pmc[regno]; - ilock(&m->pmclock); + ilock(&mp->pmclock); p->ctlset |= PmcGet; p->stale = 1; - iunlock(&m->pmclock); if(mp->proc != nil || mp->nixtype != NIXAC){ - apicipi(mp->apicno); - sleep(&p->r, notstale, p); + waitnotstale(mp, p); + ilock(&mp->pmclock); } - ilock(&m->pmclock); memmove(pctl, &p->PmcCtl, sizeof(PmcCtl)); - iunlock(&m->pmclock); + iunlock(&mp->pmclock); return 0; } @@ -345,6 +380,7 @@ { PmcCtr *p; int i, maxct, wk; + PmcWait *w; maxct = pmcnregs(); for (i = 0; i < maxct; i++) { @@ -360,9 +396,13 @@ 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->r); + } + } iunlock(&m->pmclock); - if(wk) - wakeup(&p->r); } } diff -r afa3c6e9b994 -r 03bf4c5fe96a sys/src/nix/port/devpmc.c --- a/sys/src/nix/port/devpmc.c Fri Dec 09 11:02:28 2011 -0800 +++ b/sys/src/nix/port/devpmc.c Tue Jan 17 13:26:04 2012 -0800 @@ -150,6 +150,7 @@ case Qctr: return devgen(c, name, pmctab, npmctab, s, dp); case Qcore: + c->aux = (void *)PMCID(c->qid.path); /* core no */ return devgen(c, name, pmctab, npmctab, s, dp); default: if(s != 0) @@ -180,8 +181,6 @@ static Walkqid* pmcwalk(Chan *c, Chan *nc, char **name, int nname) { - if(PMCTYPE(c->qid.path) == Qcore) - c->aux = (void *)PMCID(c->qid.path); /* core no */ return devwalk(c, nc, name, nname, nil, 0, pmcgen); } @@ -230,7 +229,6 @@ free(s); nexterror(); } - coreno = (u64int)c->aux; p.coreno = coreno; switch(type){ @@ -262,6 +260,8 @@ Disable, User, Os, + NoUser, + NoOs, Reset, Debug, }; @@ -272,6 +272,8 @@ Disable, "disable", 0, User, "user", 0, Os, "os", 0, + NoUser, "nouser", 0, + NoOs, "noos", 0, Reset, "reset", 0, Debug, "debug", 0, }; @@ -387,6 +389,12 @@ case Os: p.os = 1; break; + case NoUser: + p.user = 0; + break; + case NoOs: + p.os = 0; + break; case Reset: p.reset = 1; break;