提交 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; } ...@@ -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 fetchadd(ptr, val) __sync_fetch_and_add(ptr, val)
#define __offsetof offsetof #define __offsetof offsetof
struct trapframe;
struct spinlock; struct spinlock;
struct condvar; struct condvar;
struct wqframe; struct wqframe;
...@@ -211,7 +212,7 @@ extern int profenable; ...@@ -211,7 +212,7 @@ extern int profenable;
void profreset(void); void profreset(void);
void profdump(void); void profdump(void);
void profstart(void); void profstart(void);
int profintr(void); int profintr(struct trapframe*);
// rcu.c // rcu.c
void rcuinit(void); void rcuinit(void);
......
...@@ -9,6 +9,18 @@ ...@@ -9,6 +9,18 @@
#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;
...@@ -19,6 +31,21 @@ struct pmu { ...@@ -19,6 +31,21 @@ struct pmu {
}; };
struct pmu 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 // AMD stuff
// //
...@@ -80,34 +107,55 @@ profdump(void) ...@@ -80,34 +107,55 @@ profdump(void)
if (cnt) if (cnt)
cprintf("%s %lu\n", p->name, tot/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 void
profstart(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(); pushcli();
pmu.config(ctr, sel, val); pmu.config(0, debug_sel, -debug_cnt);
popcli(); 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 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); lapicpc(0);
// Only level-triggered interrupts require an lapiceoi. // 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; return 1;
} }
...@@ -132,4 +180,10 @@ initprof(void) ...@@ -132,4 +180,10 @@ initprof(void)
// enable RDPMC at CPL > 0 // enable RDPMC at CPL > 0
u64 cr4 = rcr4(); u64 cr4 = rcr4();
lcr4(cr4 | CR4_PCE); 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()) if (profintr(tf))
return; return;
panic("NMI"); panic("NMI");
} }
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论