Watchdog code tested only on josmp

上级 4c05b764
...@@ -62,6 +62,7 @@ u64 nsectime(void); ...@@ -62,6 +62,7 @@ u64 nsectime(void);
// console.c // console.c
void cprintf(const char*, ...) __attribute__((format(printf, 1, 2))); void cprintf(const char*, ...) __attribute__((format(printf, 1, 2)));
void __cprintf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
void vcprintf(const char *fmt, va_list ap); void vcprintf(const char *fmt, va_list ap);
void panic(const char*, ...) void panic(const char*, ...)
__noret__ __attribute__((format(printf, 1, 2))); __noret__ __attribute__((format(printf, 1, 2)));
...@@ -187,6 +188,7 @@ int sampintr(struct trapframe*); ...@@ -187,6 +188,7 @@ int sampintr(struct trapframe*);
void sampdump(void); void sampdump(void);
void sampconf(void); void sampconf(void);
void sampidle(bool); void sampidle(bool);
void wdpoke(void);
// sched.cc // sched.cc
void addrun(struct proc *); void addrun(struct proc *);
......
...@@ -96,7 +96,7 @@ snprintf(char *buf, u32 n, const char *fmt, ...) ...@@ -96,7 +96,7 @@ snprintf(char *buf, u32 n, const char *fmt, ...)
va_end(ap); va_end(ap);
} }
static void void
__cprintf(const char *fmt, ...) __cprintf(const char *fmt, ...)
{ {
va_list ap; va_list ap;
...@@ -156,7 +156,7 @@ printtrace(u64 rbp) ...@@ -156,7 +156,7 @@ printtrace(u64 rbp)
getcallerpcs((void*)rbp, pc, NELEM(pc)); getcallerpcs((void*)rbp, pc, NELEM(pc));
for (int i = 0; i < NELEM(pc) && pc[i] != 0; i++) for (int i = 0; i < NELEM(pc) && pc[i] != 0; i++)
__cprintf(" %p\n", pc[i]); __cprintf(" %016lx\n", pc[i]);
} }
void __noret__ void __noret__
...@@ -175,8 +175,8 @@ kerneltrap(struct trapframe *tf) ...@@ -175,8 +175,8 @@ kerneltrap(struct trapframe *tf)
pid = myproc()->pid; pid = myproc()->pid;
kstack = myproc()->kstack; kstack = myproc()->kstack;
} }
__cprintf("kernel trap %u cpu %u\n" __cprintf("kernel trap %lu cpu %u\n"
" tf: rip %p rsp %p rbp %p cr2 %p cs %p\n" " tf: rip %016lx rsp %016lx rbp %016lx cr2 %016lx cs %x\n"
" proc: name %s pid %u kstack %p\n", " proc: name %s pid %u kstack %p\n",
tf->trapno, mycpu()->id, tf->trapno, mycpu()->id,
tf->rip, tf->rsp, tf->rbp, rcr2(), tf->cs, tf->rip, tf->rsp, tf->rbp, rcr2(), tf->cs,
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "sampler.h" #include "sampler.h"
#include "major.h" #include "major.h"
#include "apic.hh" #include "apic.hh"
#include "percpu.hh"
#define LOGHEADER_SZ (sizeof(struct logheader) + \ #define LOGHEADER_SZ (sizeof(struct logheader) + \
sizeof(((struct logheader*)0)->cpu[0])*NCPU) sizeof(((struct logheader*)0)->cpu[0])*NCPU)
...@@ -19,6 +20,25 @@ ...@@ -19,6 +20,25 @@
static volatile u64 selector; static volatile u64 selector;
static volatile u64 period; static volatile u64 period;
static const u64 wd_period = 24000000000ul;
#if defined(HW_josmp)
static const u64 wd_selector =
0UL << 32 |
1 << 24 |
1 << 22 |
1 << 20 |
1 << 17 |
1 << 16 |
0x00 << 8 |
0x76;
#else
static const u64 wd_selector = 0;
#endif
static percpu<bool> wd_flag;
// XXX(sbw) max period should be (1 << (cntval_bits - 1)) - 1
// XXX(sbw) should mask out higher order bits from period (e.g. the top 16 on amd)
struct pmu { struct pmu {
void (*config)(u64 ctr, u64 sel, u64 val); void (*config)(u64 ctr, u64 sel, u64 val);
u64 cntval_bits; u64 cntval_bits;
...@@ -114,9 +134,33 @@ samplog(struct trapframe *tf) ...@@ -114,9 +134,33 @@ samplog(struct trapframe *tf)
return 1; return 1;
} }
static void
wdcheck(struct trapframe* tf)
{
if (! *wd_flag) {
// uartputc guarantees some output
uartputc('W');
uartputc('D');
uartputc('\n');
__cprintf("cpu%u: wdcheck\n", myid());
__cprintf(" %016lx\n", tf->rip);
printtrace(tf->rbp);
}
*wd_flag = false;
}
void
wdpoke(void)
{
*wd_flag = true;
}
int int
sampintr(struct trapframe *tf) sampintr(struct trapframe *tf)
{ {
int r = 0;
u64 cnt;
// Acquire locks that we only acquire during NMI. // Acquire locks that we only acquire during NMI.
// NMIs are disabled until the next iret. // NMIs are disabled until the next iret.
...@@ -124,14 +168,22 @@ sampintr(struct trapframe *tf) ...@@ -124,14 +168,22 @@ sampintr(struct trapframe *tf)
lapicpc(0); lapicpc(0);
// Only level-triggered interrupts require an lapiceoi. // Only level-triggered interrupts require an lapiceoi.
u64 cnt = rdpmc(0); cnt = rdpmc(0);
if (cnt & (1ULL << (pmu.cntval_bits - 1))) if ((cnt & (1ULL << (pmu.cntval_bits - 1))) == 0) {
return 0; // We've overflowed
r = 1;
if (samplog(tf))
pmu.config(0, selector, -period);
}
if (samplog(tf)) cnt = rdpmc(1);
pmu.config(0, selector, -period); if ((cnt & (1ULL << (pmu.cntval_bits - 1))) == 0) {
r = 1;
wdcheck(tf);
pmu.config(1, wd_selector, -wd_period);
}
return 1; return r;
} }
static int static int
...@@ -247,6 +299,17 @@ sampwrite(struct inode *ip, const char *buf, u32 off, u32 n) ...@@ -247,6 +299,17 @@ sampwrite(struct inode *ip, const char *buf, u32 off, u32 n)
} }
void void
initwd(void)
{
wdpoke();
pushcli();
#if defined(HW_josmp)
pmu.config(1, wd_selector, -wd_period);
#endif
popcli();
}
void
initsamp(void) initsamp(void)
{ {
if (myid() == mpbcpu()) { if (myid() == mpbcpu()) {
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论