提交 94264a7d 创建 作者: Silas Boyd-Wickizer's avatar Silas Boyd-Wickizer

Some simple NMI handling and logging.

上级 2ee21cd7
......@@ -20,6 +20,7 @@ static inline void *p2v(uptr a) { return (void *) a + KBASE; }
#define fetchadd(ptr, val) __sync_fetch_and_add(ptr, val)
#define __offsetof offsetof
struct trapframe;
struct spinlock;
struct condvar;
struct wqframe;
......@@ -211,7 +212,7 @@ extern int profenable;
void profreset(void);
void profdump(void);
void profstart(void);
int profintr(void);
int profintr(struct trapframe*);
// rcu.c
void rcuinit(void);
......
......@@ -9,6 +9,18 @@
#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;
extern profctr_t sprof[];
extern profctr_t eprof[];
int profenable;
......@@ -19,6 +31,21 @@ struct pmu {
};
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
//
......@@ -80,34 +107,55 @@ profdump(void)
if (cnt)
cprintf("%s %lu\n", p->name, tot/cnt);
}
cprintf("pmu\n");
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)
{
u64 ctr = 0;
u64 sel = 0;
u64 val = -100000;
sel = 0UL << 32 |
1 << 24 |
1 << 22 |
1 << 20 |
1 << 17 |
1 << 16 |
0x00 << 8 |
0x76;
pushcli();
pmu.config(ctr, sel, val);
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(void)
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;
}
......@@ -132,4 +180,10 @@ initprof(void)
// 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)
if (tf->trapno == T_NMI) {
// The only locks that we can acquire during NMI are ones
// we acquire only during NMI.
if (profintr())
if (profintr(tf))
return;
panic("NMI");
}
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论