提交 778e40e8 创建 作者: Silas Boyd-Wickizer's avatar Silas Boyd-Wickizer

Odds and ends for event counters on AMD.

上级 3b80afc5
......@@ -129,6 +129,7 @@ int cpunum(void);
void lapicstartap(u8, u32 addr);
void lapiceoi(void);
void lapic_tlbflush(u32);
void lapicpc(char mask);
// mp.c
extern int ncpu;
......@@ -210,6 +211,7 @@ extern int profenable;
void profreset(void);
void profdump(void);
void profstart(void);
int profintr(void);
// rcu.c
void rcuinit(void);
......
......@@ -35,6 +35,8 @@
#define LINT1 (0x0360/4) // Local Vector Table 2 (LINT1)
#define ERROR (0x0370/4) // Local Vector Table 3 (ERROR)
#define MASKED 0x00010000 // Interrupt masked
#define MT_NMI 0x00000400 // NMI message type
#define MT_FIX 0x00000000 // Fixed message type
#define TICR (0x0380/4) // Timer Initial Count
#define TCCR (0x0390/4) // Timer Current Count
#define TDCR (0x03E0/4) // Timer Divide Configuration
......@@ -107,7 +109,7 @@ initlapic(void)
// Disable performance counter overflow interrupts
// on machines that provide that interrupt entry.
if(((lapic[VER]>>16) & 0xFF) >= 4)
lapicw(PCINT, MASKED);
lapicpc(0);
// Map error interrupt to IRQ_ERROR.
lapicw(ERROR, T_IRQ0 + IRQ_ERROR);
......@@ -129,6 +131,12 @@ initlapic(void)
lapicw(TPR, 0);
}
void
lapicpc(char mask)
{
lapicw(PCINT, mask ? MASKED : MT_NMI);
}
int
cpunum(void)
{
......
......@@ -24,6 +24,7 @@ extern void initdisk(void);
extern void inituser(void);
extern void inithz(void);
extern void initwq(void);
extern void initprof(void);
static volatile int bstate;
......@@ -33,6 +34,7 @@ mpboot(void)
initseg();
inittls();
initlapic();
initprof();
bstate = 1;
scheduler(); // start running processes
}
......@@ -99,6 +101,7 @@ cmain(void)
#if WQENABLE
initwq(); // work queues
#endif
initprof();
cprintf("ncpu %d %lu MHz\n", ncpu, cpuhz / 1000000);
......
......@@ -11,10 +11,46 @@
extern profctr_t sprof[];
extern profctr_t eprof[];
int profenable;
static void (*profconfig)(u64 ctr, u64 sel, u64 val);
struct pmu {
void (*config)(u64 ctr, u64 sel, u64 val);
u64 cntval_bits;
};
struct pmu pmu;
//
// 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
profreset(void)
......@@ -46,30 +82,12 @@ profdump(void)
}
}
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);
}
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);
}
void
profstart(void)
{
u64 ctr = 0;
u64 sel = 0;
u64 val = -1000;
cprintf("profstart ...\n");
u64 val = -100000;
sel = 0UL << 32 |
1 << 24 |
......@@ -81,10 +99,16 @@ profstart(void)
0x76;
pushcli();
profconfig(ctr, sel, val);
pmu.config(ctr, sel, val);
popcli();
}
cprintf("rdpmc %lx\n", rdpmc(0));
int
profintr(void)
{
lapicpc(0);
// Only level-triggered interrupts require an lapiceoi.
return 1;
}
void
......@@ -97,10 +121,10 @@ initprof(void)
cpuid(0, 0, &name[0], &name[2], &name[1]);
cprintf("%s\n", s);
if (strcmp(s, "AuthenticAMD"))
profconfig = amdconfig;
else if (strcmp(s, "GenuineIntel"))
profconfig = intelconfig;
if (!strcmp(s, "AuthenticAMD"))
pmu = amdpmu;
else if (!strcmp(s, "GenuineIntel"))
pmu = intelpmu;
else
panic("Unknown Manufacturer");
}
......
......@@ -48,6 +48,14 @@ trap(struct trapframe *tf)
writemsr(MSR_GS_BASE, (u64)&cpus[cpunum()].cpu);
sti();
if (tf->trapno == T_NMI) {
// The only locks that we can acquire during NMI are ones
// we acquire only during NMI.
if (profintr())
return;
panic("NMI");
}
// XXX(sbw) sysenter/sysexit
if(tf->trapno == T_SYSCALL){
if(myproc()->killed) {
......@@ -92,6 +100,7 @@ trap(struct trapframe *tf)
lapiceoi();
piceoi();
break;
case T_IRQ0 + IRQ_COM2:
case T_IRQ0 + IRQ_COM1:
uartintr();
lapiceoi();
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论