diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 13:38:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 13:38:34 -0400 |
commit | 619297855aa16646246ea4b1f6e05f1b2455c808 (patch) | |
tree | a07fe1b24c372f5eabf244555db41fdf574c1205 /arch/powerpc | |
parent | e16b396ce314b2bcdfe6c173fe075bf8e3432368 (diff) | |
parent | 1ef1d1c2353967e2d61ecaddf76edfd058a778b4 (diff) |
Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (30 commits)
trace, filters: Initialize the match variable in process_ops() properly
trace, documentation: Fix branch profiling location in debugfs
oprofile, s390: Cleanups
oprofile, s390: Remove hwsampler_files.c and merge it into init.c
perf: Fix tear-down of inherited group events
perf: Reorder & optimize perf_event_context to remove alignment padding on 64 bit builds
perf: Handle stopped state with tracepoints
perf: Fix the software events state check
perf, powerpc: Handle events that raise an exception without overflowing
perf, x86: Use INTEL_*_CONSTRAINT() for all PEBS event constraints
perf, x86: Clean up SandyBridge PEBS events
perf lock: Fix sorting by wait_min
perf tools: Version incorrect with some versions of grep
perf evlist: New command to list the names of events present in a perf.data file
perf script: Add support for H/W and S/W events
perf script: Add support for dumping symbols
perf script: Support custom field selection for output
perf script: Move printing of 'common' data from print_event and rename
perf tracing: Remove print_graph_cpu and print_graph_proc from trace-event-parse
perf script: Change process_event prototype
...
Diffstat (limited to 'arch/powerpc')
-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 1bc6a12f3725..7e4abebe76c0 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h | |||
@@ -892,6 +892,7 @@ | |||
892 | #define PV_970 0x0039 | 892 | #define PV_970 0x0039 |
893 | #define PV_POWER5 0x003A | 893 | #define PV_POWER5 0x003A |
894 | #define PV_POWER5p 0x003B | 894 | #define PV_POWER5p 0x003B |
895 | #define PV_POWER7 0x003F | ||
895 | #define PV_970FX 0x003C | 896 | #define PV_970FX 0x003C |
896 | #define PV_630 0x0040 | 897 | #define PV_630 0x0040 |
897 | #define PV_630p 0x0041 | 898 | #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 | } |