diff options
author | Anton Blanchard <anton@samba.org> | 2011-03-08 22:38:42 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-03-16 09:04:13 -0400 |
commit | 0837e3242c73566fc1c0196b4ec61779c25ffc93 (patch) | |
tree | db77cdc93b99b1433b73a461f44543983af746bc | |
parent | 7d5d02dadd43db7f829775e404e82019c5d5586f (diff) |
perf, powerpc: Handle events that raise an exception without overflowing
Events on POWER7 can roll back if a speculative event doesn't
eventually complete. Unfortunately in some rare cases they will
raise a performance monitor exception. We need to catch this to
ensure we reset the PMC. In all cases the PMC will be 256 or less
cycles from overflow.
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: <stable@kernel.org> # as far back as it applies cleanly
LKML-Reference: <20110309143842.6c22845e@kryten>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/powerpc/include/asm/reg.h | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/perf_event.c | 24 |
2 files changed, 24 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 125fc1ad665d..7626fa78e1f8 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h | |||
@@ -880,6 +880,7 @@ | |||
880 | #define PV_970 0x0039 | 880 | #define PV_970 0x0039 |
881 | #define PV_POWER5 0x003A | 881 | #define PV_POWER5 0x003A |
882 | #define PV_POWER5p 0x003B | 882 | #define PV_POWER5p 0x003B |
883 | #define PV_POWER7 0x003F | ||
883 | #define PV_970FX 0x003C | 884 | #define PV_970FX 0x003C |
884 | #define PV_630 0x0040 | 885 | #define PV_630 0x0040 |
885 | #define PV_630p 0x0041 | 886 | #define PV_630p 0x0041 |
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c index ab6f6beadb57..97e0ae414940 100644 --- a/arch/powerpc/kernel/perf_event.c +++ b/arch/powerpc/kernel/perf_event.c | |||
@@ -1269,6 +1269,28 @@ unsigned long perf_instruction_pointer(struct pt_regs *regs) | |||
1269 | return ip; | 1269 | return ip; |
1270 | } | 1270 | } |
1271 | 1271 | ||
1272 | static bool pmc_overflow(unsigned long val) | ||
1273 | { | ||
1274 | if ((int)val < 0) | ||
1275 | return true; | ||
1276 | |||
1277 | /* | ||
1278 | * Events on POWER7 can roll back if a speculative event doesn't | ||
1279 | * eventually complete. Unfortunately in some rare cases they will | ||
1280 | * raise a performance monitor exception. We need to catch this to | ||
1281 | * ensure we reset the PMC. In all cases the PMC will be 256 or less | ||
1282 | * cycles from overflow. | ||
1283 | * | ||
1284 | * We only do this if the first pass fails to find any overflowing | ||
1285 | * PMCs because a user might set a period of less than 256 and we | ||
1286 | * don't want to mistakenly reset them. | ||
1287 | */ | ||
1288 | if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256)) | ||
1289 | return true; | ||
1290 | |||
1291 | return false; | ||
1292 | } | ||
1293 | |||
1272 | /* | 1294 | /* |
1273 | * Performance monitor interrupt stuff | 1295 | * Performance monitor interrupt stuff |
1274 | */ | 1296 | */ |
@@ -1316,7 +1338,7 @@ static void perf_event_interrupt(struct pt_regs *regs) | |||
1316 | if (is_limited_pmc(i + 1)) | 1338 | if (is_limited_pmc(i + 1)) |
1317 | continue; | 1339 | continue; |
1318 | val = read_pmc(i + 1); | 1340 | val = read_pmc(i + 1); |
1319 | if ((int)val < 0) | 1341 | if (pmc_overflow(val)) |
1320 | write_pmc(i + 1, 0); | 1342 | write_pmc(i + 1, 0); |
1321 | } | 1343 | } |
1322 | } | 1344 | } |