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