kernel: deep refactoring and cleanup
This large commit address several issues - removed 386 directory: Jehanne is 64bit only - simplified kernel options management - rewritten boot process - ported memory related stuff from 9front's 9/pc64 - removed devacpi - removed old code - deep refactor of awake syscall - removed MCACHE support for mount - fix libc's setjmp/longjmp
This commit is contained in:
380
sys/src/kern/amd64/devpmc.c
Normal file
380
sys/src/kern/amd64/devpmc.c
Normal file
@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Performance counters
|
||||
*/
|
||||
|
||||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "../port/error.h"
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
|
||||
enum{
|
||||
Qdir = 0,
|
||||
Qdesc,
|
||||
Qcore,
|
||||
PmcCtlRdStr = 4*1024,
|
||||
};
|
||||
|
||||
#define PMCTYPE(x) (((unsigned)x)&0xffful)
|
||||
#define PMCID(x) (((unsigned)x)>>12)
|
||||
#define PMCQID(i, t) ((((unsigned)i)<<12)|(t))
|
||||
|
||||
static Dirtab *toptab;
|
||||
static Lock toptablck;
|
||||
static int ntoptab;
|
||||
int pmcdebug;
|
||||
|
||||
static void
|
||||
topdirinit(void)
|
||||
{
|
||||
Dirtab *d;
|
||||
int nent;
|
||||
|
||||
nent = 1 + MACHMAX;
|
||||
toptab = jehanne_mallocz(nent * sizeof(Dirtab), 1);
|
||||
if (toptab == nil)
|
||||
return;
|
||||
d = toptab;
|
||||
jehanne_strncpy(d->name, "ctrdesc", KNAMELEN);
|
||||
mkqid(&d->qid, Qdesc, 0, 0);
|
||||
d->perm = 0440;
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
corefilesinit(void)
|
||||
{
|
||||
int i, nc, newn;
|
||||
Dirtab *d;
|
||||
Mach *mp;
|
||||
|
||||
nc = 0;
|
||||
lock(&toptablck);
|
||||
for(i = 0; i < MACHMAX; i++) {
|
||||
if((mp = sys->machptr[i]) != nil && mp->online != 0){
|
||||
d = &toptab[nc + 1];
|
||||
/* if you take them out, be careful in pmcgen too */
|
||||
if(d->name[0] != '\0'){
|
||||
if(PMCQID(i, Qcore) == d->qid.path){
|
||||
nc++;
|
||||
continue;
|
||||
}else{
|
||||
/* a new one appeared, make space, should almost never happen */
|
||||
jehanne_memmove(d + 1, d, (MACHMAX - i)*sizeof(*d));
|
||||
jehanne_memset(d, 0, sizeof(*d));
|
||||
}
|
||||
}
|
||||
jehanne_snprint(d->name, KNAMELEN, "core%4.4ud", i);
|
||||
mkqid(&d->qid, PMCQID(i, Qcore), 0, 0);
|
||||
d->perm = 0660;
|
||||
nc++;
|
||||
}
|
||||
}
|
||||
newn = 1 + nc;
|
||||
ntoptab = newn;
|
||||
unlock(&toptablck);
|
||||
return newn;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pmcinit(void)
|
||||
{
|
||||
pmcconfigure();
|
||||
topdirinit();
|
||||
corefilesinit();
|
||||
}
|
||||
|
||||
static Chan *
|
||||
pmcattach(Chan *c, Chan *ac, char *spec, int flags)
|
||||
{
|
||||
corefilesinit();
|
||||
return devattach(L'ε', spec);
|
||||
}
|
||||
|
||||
int
|
||||
pmcgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
|
||||
{
|
||||
int ntab;
|
||||
Dirtab *d;
|
||||
|
||||
ntab = corefilesinit();
|
||||
if(s == DEVDOTDOT){
|
||||
devdir(c, (Qid){Qdir, 0, QTDIR}, "#ε", 0, eve, 0555, dp);
|
||||
c->aux = nil;
|
||||
return 1;
|
||||
}
|
||||
/* first, for directories, generate children */
|
||||
switch((int)PMCTYPE(c->qid.path)){
|
||||
case Qdir:
|
||||
case Qcore:
|
||||
if(s >= ntab)
|
||||
return -1;
|
||||
d = &toptab[s];
|
||||
devdir(c, d->qid, d->name, d->length, eve, d->perm, dp);
|
||||
return 1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static long
|
||||
pmcstat(Chan *c, uint8_t *dp, long n)
|
||||
{
|
||||
return devstat(c, dp, n, nil, 0, pmcgen);
|
||||
}
|
||||
|
||||
static Chan*
|
||||
pmcopen(Chan *c, int omode)
|
||||
{
|
||||
if (!iseve())
|
||||
error(Eperm);
|
||||
return devopen(c, omode, nil, 0, pmcgen);
|
||||
}
|
||||
|
||||
static void
|
||||
pmcclose(Chan *)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
pmcctlstr(char *str, int nstr, PmcCtl *p, int64_t v)
|
||||
{
|
||||
int ns;
|
||||
|
||||
ns = 0;
|
||||
ns += jehanne_snprint(str + ns, nstr - ns, "%#ullx ", v);
|
||||
if (p->enab && p->enab != PmcCtlNullval)
|
||||
ns += jehanne_snprint(str + ns, nstr - ns, "on ");
|
||||
else
|
||||
ns += jehanne_snprint(str + ns, nstr - ns, "off ");
|
||||
|
||||
if (p->user && p->user != PmcCtlNullval)
|
||||
ns += jehanne_snprint(str + ns, nstr - ns, "user ");
|
||||
else
|
||||
ns += jehanne_snprint(str + ns, nstr - ns, "nouser ");
|
||||
|
||||
if (p->os && p->user != PmcCtlNullval)
|
||||
ns += jehanne_snprint(str + ns, nstr - ns, "os ");
|
||||
else
|
||||
ns += jehanne_snprint(str + ns, nstr - ns, "noos ");
|
||||
|
||||
/* TODO, inverse pmctrans? */
|
||||
if(!p->nodesc)
|
||||
ns += jehanne_snprint(str + ns, nstr - ns, "%s", p->descstr);
|
||||
else
|
||||
ns += jehanne_snprint(str + ns, nstr - ns, "no desc");
|
||||
ns += jehanne_snprint(str + ns, nstr - ns, "\n");
|
||||
return ns;
|
||||
}
|
||||
|
||||
|
||||
/* this should be safe to use even if there is no core anymore */
|
||||
static long
|
||||
pmcread(Chan *c, void *a, long n, int64_t offset)
|
||||
{
|
||||
uint32_t type;
|
||||
PmcCtl p;
|
||||
char *s;
|
||||
uint64_t v;
|
||||
uint64_t coreno;
|
||||
int nr, i, ns, nn;
|
||||
|
||||
type = PMCTYPE(c->qid.path);
|
||||
coreno = PMCID(c->qid.path);
|
||||
|
||||
if(type == Qdir)
|
||||
return devdirread(c, a, n, nil, 0, pmcgen);
|
||||
s = jehanne_malloc(PmcCtlRdStr);
|
||||
if(waserror()){
|
||||
jehanne_free(s);
|
||||
nexterror();
|
||||
}
|
||||
|
||||
p.coreno = coreno;
|
||||
nr = pmcnregs();
|
||||
switch(type){
|
||||
case Qcore:
|
||||
ns = 0;
|
||||
for(i = 0; i < nr; i ++){
|
||||
if (pmcgetctl(coreno, &p, i) < 0)
|
||||
error("bad ctr");
|
||||
if(! p.enab)
|
||||
continue;
|
||||
v = pmcgetctr(coreno, i);
|
||||
ns += jehanne_snprint(s + ns, PmcCtlRdStr - ns, "%2.2ud ", i);
|
||||
nn = pmcctlstr(s + ns, PmcCtlRdStr - ns, &p, v);
|
||||
if (n < 0)
|
||||
error("bad pmc");
|
||||
ns += nn;
|
||||
}
|
||||
break;
|
||||
case Qdesc:
|
||||
if (pmcdescstr(s, PmcCtlRdStr) < 0)
|
||||
error("bad pmc");
|
||||
break;
|
||||
default:
|
||||
error(Eperm);
|
||||
}
|
||||
n = readstr(offset, a, n, s);
|
||||
jehanne_free(s);
|
||||
poperror();
|
||||
return n;
|
||||
}
|
||||
|
||||
static int
|
||||
isset(char *str)
|
||||
{
|
||||
return jehanne_strncmp(str, "-", 2) != 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pickregno(int coreno)
|
||||
{
|
||||
PmcCtl p;
|
||||
int nr, i;
|
||||
|
||||
nr = pmcnregs();
|
||||
for(i = 0; i < nr; i++){
|
||||
if (pmcgetctl(coreno, &p, i) || p.enab)
|
||||
continue;
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
fillctl(PmcCtl *p, Cmdbuf *cb, int start, int end)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(end > cb->nf -1)
|
||||
end = cb->nf -1;
|
||||
for(i = start; i <= end; i++){
|
||||
if(pmcdebug != 0)
|
||||
jehanne_print("setting field %d to %s\n", i, cb->f[i]);
|
||||
if(!isset(cb->f[i]))
|
||||
continue;
|
||||
else if(jehanne_strcmp("on", cb->f[i]) == 0)
|
||||
p->enab = 1;
|
||||
else if(jehanne_strcmp("off", cb->f[i]) == 0)
|
||||
p->enab = 0;
|
||||
else if(jehanne_strcmp("user", cb->f[i]) == 0)
|
||||
p->user = 1;
|
||||
else if(jehanne_strcmp("os", cb->f[i]) == 0)
|
||||
p->os = 1;
|
||||
else if(jehanne_strcmp("nouser", cb->f[i]) == 0)
|
||||
p->user = 0;
|
||||
else if(jehanne_strcmp("noos", cb->f[i]) == 0)
|
||||
p->os = 0;
|
||||
else
|
||||
error("bad ctl");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this should be safe to use even if there is no core anymore */
|
||||
static long
|
||||
pmcwrite(Chan *c, void *a, long n, int64_t)
|
||||
{
|
||||
Cmdbuf *cb;
|
||||
uint64_t coreno;
|
||||
int regno, i, ns;
|
||||
PmcCtl p;
|
||||
char *s;
|
||||
|
||||
if (c->qid.type == QTDIR)
|
||||
error(Eperm);
|
||||
if (c->qid.path == Qdesc)
|
||||
error(Eperm);
|
||||
|
||||
coreno = PMCID(c->qid.path);;
|
||||
p.coreno = coreno;
|
||||
|
||||
/* TODO, multiple lines? */
|
||||
cb = parsecmd(a, n);
|
||||
if(waserror()){
|
||||
jehanne_free(cb);
|
||||
nexterror();
|
||||
}
|
||||
if(cb->nf < 1)
|
||||
error("short ctl");
|
||||
if(jehanne_strcmp("debug", cb->f[0]) == 0)
|
||||
pmcdebug = ~pmcdebug;
|
||||
else{
|
||||
if(cb->nf < 2)
|
||||
error("short ctl");
|
||||
if(!isset(cb->f[0])){
|
||||
/* racy, it does not reserve the core */
|
||||
regno = pickregno(coreno);
|
||||
if(regno < 0)
|
||||
error("no free regno");
|
||||
if(pmcdebug != 0)
|
||||
jehanne_print("picked regno %d\n", regno);
|
||||
}else{
|
||||
regno = jehanne_strtoull(cb->f[0], 0, 0);
|
||||
if(regno > pmcnregs())
|
||||
error("ctr number too big");
|
||||
if(pmcdebug != 0)
|
||||
jehanne_print("setting regno %d\n", regno);
|
||||
}
|
||||
if(isset(cb->f[1]))
|
||||
pmcsetctr(coreno, jehanne_strtoull(cb->f[1], 0, 0), regno);
|
||||
|
||||
pmcinitctl(&p);
|
||||
fillctl(&p, cb, 2, 4);
|
||||
ns = 0;
|
||||
s = p.descstr;
|
||||
s[0] = '\0';
|
||||
for(i = 5; i < cb->nf; i++){
|
||||
if(!isset(cb->f[i]))
|
||||
continue;
|
||||
ns += jehanne_snprint(s + ns, KNAMELEN - ns, "%s ", cb->f[i]);
|
||||
p.nodesc = 0;
|
||||
}
|
||||
if(pmcdebug != 0)
|
||||
jehanne_print("setting desc to %s\n", p.descstr);
|
||||
pmcsetctl(coreno, &p, regno);
|
||||
}
|
||||
jehanne_free(cb);
|
||||
poperror();
|
||||
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
Dev pmcdevtab = {
|
||||
L'ε',
|
||||
"pmc",
|
||||
|
||||
pmcinit,
|
||||
devinit,
|
||||
devshutdown,
|
||||
pmcattach,
|
||||
pmcwalk,
|
||||
pmcstat,
|
||||
pmcopen,
|
||||
devcreate,
|
||||
pmcclose,
|
||||
pmcread,
|
||||
devbread,
|
||||
pmcwrite,
|
||||
devbwrite,
|
||||
devremove,
|
||||
devwstat,
|
||||
};
|
Reference in New Issue
Block a user