提交 5606f832 创建 作者: Silas Boyd-Wickizer's avatar Silas Boyd-Wickizer

Move sampler code from prof.c to sampler.c.

上级 94264a7d
...@@ -48,6 +48,7 @@ OBJS = \ ...@@ -48,6 +48,7 @@ OBJS = \
proc.o \ proc.o \
prof.o \ prof.o \
rcu.o \ rcu.o \
sampler.o \
sched.o \ sched.o \
spinlock.o \ spinlock.o \
swtch.o \ swtch.o \
......
...@@ -211,8 +211,6 @@ void migrate(struct proc *); ...@@ -211,8 +211,6 @@ void migrate(struct proc *);
extern int profenable; extern int profenable;
void profreset(void); void profreset(void);
void profdump(void); void profdump(void);
void profstart(void);
int profintr(struct trapframe*);
// rcu.c // rcu.c
void rcuinit(void); void rcuinit(void);
...@@ -225,6 +223,11 @@ void rcu_delayed2(int, u64, void (*dofree)(int, u64)); ...@@ -225,6 +223,11 @@ void rcu_delayed2(int, u64, void (*dofree)(int, u64));
void rcu_gc(void); void rcu_gc(void);
void rcu_gc_worker(void); void rcu_gc_worker(void);
// sampler.c
void sampstart(void);
int sampintr(struct trapframe*);
void sampdump(void);
// spinlock.c // spinlock.c
void acquire(struct spinlock*); void acquire(struct spinlock*);
void getcallerpcs(void*, uptr*); void getcallerpcs(void*, uptr*);
......
...@@ -24,7 +24,7 @@ extern void initdisk(void); ...@@ -24,7 +24,7 @@ extern void initdisk(void);
extern void inituser(void); extern void inituser(void);
extern void inithz(void); extern void inithz(void);
extern void initwq(void); extern void initwq(void);
extern void initprof(void); extern void initsamp(void);
static volatile int bstate; static volatile int bstate;
...@@ -34,7 +34,7 @@ mpboot(void) ...@@ -34,7 +34,7 @@ mpboot(void)
initseg(); initseg();
inittls(); inittls();
initlapic(); initlapic();
initprof(); initsamp();
bstate = 1; bstate = 1;
scheduler(); // start running processes scheduler(); // start running processes
} }
...@@ -101,7 +101,7 @@ cmain(void) ...@@ -101,7 +101,7 @@ cmain(void)
#if WQENABLE #if WQENABLE
initwq(); // work queues initwq(); // work queues
#endif #endif
initprof(); initsamp();
cprintf("ncpu %d %lu MHz\n", ncpu, cpuhz / 1000000); cprintf("ncpu %d %lu MHz\n", ncpu, cpuhz / 1000000);
......
...@@ -9,76 +9,10 @@ ...@@ -9,76 +9,10 @@
#include "bits.h" #include "bits.h"
#include "amd64.h" #include "amd64.h"
static const u64 debug_sel =
0UL << 32 |
1 << 24 |
1 << 22 |
1 << 20 |
1 << 17 |
1 << 16 |
0x00 << 8 |
0x76;
static const u64 debug_cnt = 100000;
extern profctr_t sprof[]; extern profctr_t sprof[];
extern profctr_t eprof[]; extern profctr_t eprof[];
int profenable; int profenable;
struct pmu {
void (*config)(u64 ctr, u64 sel, u64 val);
u64 cntval_bits;
};
struct pmu pmu;
struct pmuevent {
u64 rip;
};
struct pmulog {
u64 head;
u64 tail;
u64 size;
u64 try;
struct pmuevent *event;
__padout__;
} __mpalign__;
struct pmulog pmulog[NCPU] __mpalign__;
//
// AMD stuff
//
static void
amdconfig(u64 ctr, u64 sel, u64 val)
{
writemsr(MSR_AMD_PERF_SEL0 | ctr, 0);
writemsr(MSR_AMD_PERF_CNT0 | ctr, val);
writemsr(MSR_AMD_PERF_SEL0 | ctr, sel);
}
struct pmu amdpmu = {
.config = amdconfig,
.cntval_bits = 48,
};
//
// Intel stuff
//
static void
intelconfig(u64 ctr, u64 sel, u64 val)
{
writemsr(MSR_INTEL_PERF_SEL0 | ctr, 0);
writemsr(MSR_INTEL_PERF_CNT0 | ctr, val);
writemsr(MSR_INTEL_PERF_SEL0 | ctr, sel);
}
// XXX
struct pmu intelpmu = {
.config = intelconfig,
.cntval_bits = 48,
};
void void
profreset(void) profreset(void)
{ {
...@@ -108,82 +42,5 @@ profdump(void) ...@@ -108,82 +42,5 @@ profdump(void)
cprintf("%s %lu\n", p->name, tot/cnt); cprintf("%s %lu\n", p->name, tot/cnt);
} }
cprintf("pmu\n"); sampdump();
for (int c = 0; c < NCPU; c++) {
struct pmulog *l = &pmulog[c];
for (u64 i = l->tail; i < l->head; i++)
cprintf(" %lx\n", l->event[i % l->size].rip);
}
}
void
profstart(void)
{
pushcli();
pmu.config(0, debug_sel, -debug_cnt);
popcli();
}
static int
proflog(struct trapframe *tf)
{
struct pmulog *l;
l = &pmulog[cpunum()];
l->try++;
if ((l->head - l->tail) == l->size)
return 0;
l->event[l->head % l->size].rip = tf->rip;
l->head++;
return 1;
}
int
profintr(struct trapframe *tf)
{
// Acquire locks that are we only acquire during NMI.
// NMIs are disabled until the next iret.
// Linux unmasks LAPIC.PC after every interrupt (perf_event.c)
lapicpc(0);
// Only level-triggered interrupts require an lapiceoi.
u64 cnt = rdpmc(0);
if (cnt & (1ULL << (pmu.cntval_bits - 1)))
return 0;
if (proflog(tf))
pmu.config(0, debug_sel, -debug_cnt);
return 1;
}
void
initprof(void)
{
if (cpunum() == mpbcpu()) {
u32 name[4];
char *s = (char *)name;
name[3] = 0;
cpuid(0, 0, &name[0], &name[2], &name[1]);
cprintf("%s\n", s);
if (!strcmp(s, "AuthenticAMD"))
pmu = amdpmu;
else if (!strcmp(s, "GenuineIntel"))
pmu = intelpmu;
else
panic("Unknown Manufacturer");
}
// enable RDPMC at CPL > 0
u64 cr4 = rcr4();
lcr4(cr4 | CR4_PCE);
void *p = kalloc();
if (p == NULL)
panic("initprof: kalloc");
pmulog[cpunum()].event = p;
pmulog[cpunum()].size = PGSIZE / sizeof(struct pmuevent);
} }
#include "param.h"
#include "types.h"
#include "spinlock.h"
#include "condvar.h"
#include "fs.h"
#include "file.h"
#include "prof.h"
#include "kernel.h"
#include "bits.h"
#include "amd64.h"
static const u64 debug_sel =
0UL << 32 |
1 << 24 |
1 << 22 |
1 << 20 |
1 << 17 |
1 << 16 |
0x00 << 8 |
0x76;
static const u64 debug_cnt = 100000;
struct pmu {
void (*config)(u64 ctr, u64 sel, u64 val);
u64 cntval_bits;
};
struct pmu pmu;
struct pmuevent {
u64 rip;
};
struct pmulog {
u64 head;
u64 tail;
u64 size;
u64 try;
struct pmuevent *event;
__padout__;
} __mpalign__;
struct pmulog pmulog[NCPU] __mpalign__;
//
// AMD stuff
//
static void
amdconfig(u64 ctr, u64 sel, u64 val)
{
writemsr(MSR_AMD_PERF_SEL0 | ctr, 0);
writemsr(MSR_AMD_PERF_CNT0 | ctr, val);
writemsr(MSR_AMD_PERF_SEL0 | ctr, sel);
}
struct pmu amdpmu = {
.config = amdconfig,
.cntval_bits = 48,
};
//
// Intel stuff
//
static void
intelconfig(u64 ctr, u64 sel, u64 val)
{
writemsr(MSR_INTEL_PERF_SEL0 | ctr, 0);
writemsr(MSR_INTEL_PERF_CNT0 | ctr, val);
writemsr(MSR_INTEL_PERF_SEL0 | ctr, sel);
}
// XXX
struct pmu intelpmu = {
.config = intelconfig,
.cntval_bits = 48,
};
void
sampdump(void)
{
for (int c = 0; c < NCPU; c++) {
struct pmulog *l = &pmulog[c];
cprintf("%u samples:\n", c);
for (u64 i = l->tail; i < l->head; i++)
cprintf(" %lx\n", l->event[i % l->size].rip);
}
}
void
sampstart(void)
{
pushcli();
pmu.config(0, debug_sel, -debug_cnt);
popcli();
}
static int
samplog(struct trapframe *tf)
{
struct pmulog *l;
l = &pmulog[cpunum()];
l->try++;
if ((l->head - l->tail) == l->size)
return 0;
l->event[l->head % l->size].rip = tf->rip;
l->head++;
return 1;
}
int
sampintr(struct trapframe *tf)
{
// Acquire locks that we only acquire during NMI.
// NMIs are disabled until the next iret.
// Linux unmasks LAPIC.PC after every interrupt (perf_event.c)
lapicpc(0);
// Only level-triggered interrupts require an lapiceoi.
u64 cnt = rdpmc(0);
if (cnt & (1ULL << (pmu.cntval_bits - 1)))
return 0;
if (samplog(tf))
pmu.config(0, debug_sel, -debug_cnt);
return 1;
}
void
initsamp(void)
{
if (cpunum() == mpbcpu()) {
u32 name[4];
char *s = (char *)name;
name[3] = 0;
cpuid(0, 0, &name[0], &name[2], &name[1]);
cprintf("%s\n", s);
if (!strcmp(s, "AuthenticAMD"))
pmu = amdpmu;
else if (!strcmp(s, "GenuineIntel"))
pmu = intelpmu;
else
panic("Unknown Manufacturer");
}
// enable RDPMC at CPL > 0
u64 cr4 = rcr4();
lcr4(cr4 | CR4_PCE);
void *p = kalloc();
if (p == NULL)
panic("initprof: kalloc");
pmulog[cpunum()].event = p;
pmulog[cpunum()].size = PGSIZE / sizeof(struct pmuevent);
}
...@@ -48,7 +48,7 @@ trap(struct trapframe *tf) ...@@ -48,7 +48,7 @@ trap(struct trapframe *tf)
if (tf->trapno == T_NMI) { if (tf->trapno == T_NMI) {
// The only locks that we can acquire during NMI are ones // The only locks that we can acquire during NMI are ones
// we acquire only during NMI. // we acquire only during NMI.
if (profintr(tf)) if (sampintr(tf))
return; return;
panic("NMI"); panic("NMI");
} }
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论