diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-01 13:45:00 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-01 13:45:00 -0500 |
| commit | 834db333eda46246f6290f0e1a7525af04fc8cb4 (patch) | |
| tree | 4809b5da82a76a9924cde7a2db8986636f8be727 /kernel | |
| parent | 8ea85c2817301adb986b3b86dc20414595b776be (diff) | |
| parent | 5352ae638e2d7d5c9b2e4d528676bbf2af6fd6f3 (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:
perf, hw_breakpoint, kgdb: Do not take mutex for kernel debugger
x86, hw_breakpoints, kgdb: Fix kgdb to use hw_breakpoint API
hw_breakpoints: Release the bp slot if arch_validate_hwbkpt_settings() fails.
perf: Ignore perf.data.old
perf report: Fix segmentation fault when running with '-g none'
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/hw_breakpoint.c | 56 | ||||
| -rw-r--r-- | kernel/kgdb.c | 3 |
2 files changed, 49 insertions, 10 deletions
diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c index 50dbd5999588..8a5c7d55ac9f 100644 --- a/kernel/hw_breakpoint.c +++ b/kernel/hw_breakpoint.c | |||
| @@ -243,38 +243,70 @@ static void toggle_bp_slot(struct perf_event *bp, bool enable) | |||
| 243 | * ((per_cpu(nr_bp_flexible, *) > 1) + max(per_cpu(nr_cpu_bp_pinned, *)) | 243 | * ((per_cpu(nr_bp_flexible, *) > 1) + max(per_cpu(nr_cpu_bp_pinned, *)) |
| 244 | * + max(per_cpu(nr_task_bp_pinned, *))) < HBP_NUM | 244 | * + max(per_cpu(nr_task_bp_pinned, *))) < HBP_NUM |
| 245 | */ | 245 | */ |
| 246 | int reserve_bp_slot(struct perf_event *bp) | 246 | static int __reserve_bp_slot(struct perf_event *bp) |
| 247 | { | 247 | { |
| 248 | struct bp_busy_slots slots = {0}; | 248 | struct bp_busy_slots slots = {0}; |
| 249 | int ret = 0; | ||
| 250 | |||
| 251 | mutex_lock(&nr_bp_mutex); | ||
| 252 | 249 | ||
| 253 | fetch_bp_busy_slots(&slots, bp); | 250 | fetch_bp_busy_slots(&slots, bp); |
| 254 | 251 | ||
| 255 | /* Flexible counters need to keep at least one slot */ | 252 | /* Flexible counters need to keep at least one slot */ |
| 256 | if (slots.pinned + (!!slots.flexible) == HBP_NUM) { | 253 | if (slots.pinned + (!!slots.flexible) == HBP_NUM) |
| 257 | ret = -ENOSPC; | 254 | return -ENOSPC; |
| 258 | goto end; | ||
| 259 | } | ||
| 260 | 255 | ||
| 261 | toggle_bp_slot(bp, true); | 256 | toggle_bp_slot(bp, true); |
| 262 | 257 | ||
| 263 | end: | 258 | return 0; |
| 259 | } | ||
| 260 | |||
| 261 | int reserve_bp_slot(struct perf_event *bp) | ||
| 262 | { | ||
| 263 | int ret; | ||
| 264 | |||
| 265 | mutex_lock(&nr_bp_mutex); | ||
| 266 | |||
| 267 | ret = __reserve_bp_slot(bp); | ||
| 268 | |||
| 264 | mutex_unlock(&nr_bp_mutex); | 269 | mutex_unlock(&nr_bp_mutex); |
| 265 | 270 | ||
| 266 | return ret; | 271 | return ret; |
| 267 | } | 272 | } |
| 268 | 273 | ||
| 274 | static void __release_bp_slot(struct perf_event *bp) | ||
| 275 | { | ||
| 276 | toggle_bp_slot(bp, false); | ||
| 277 | } | ||
| 278 | |||
| 269 | void release_bp_slot(struct perf_event *bp) | 279 | void release_bp_slot(struct perf_event *bp) |
| 270 | { | 280 | { |
| 271 | mutex_lock(&nr_bp_mutex); | 281 | mutex_lock(&nr_bp_mutex); |
| 272 | 282 | ||
| 273 | toggle_bp_slot(bp, false); | 283 | __release_bp_slot(bp); |
| 274 | 284 | ||
| 275 | mutex_unlock(&nr_bp_mutex); | 285 | mutex_unlock(&nr_bp_mutex); |
| 276 | } | 286 | } |
| 277 | 287 | ||
| 288 | /* | ||
| 289 | * Allow the kernel debugger to reserve breakpoint slots without | ||
| 290 | * taking a lock using the dbg_* variant of for the reserve and | ||
| 291 | * release breakpoint slots. | ||
| 292 | */ | ||
| 293 | int dbg_reserve_bp_slot(struct perf_event *bp) | ||
| 294 | { | ||
| 295 | if (mutex_is_locked(&nr_bp_mutex)) | ||
| 296 | return -1; | ||
| 297 | |||
| 298 | return __reserve_bp_slot(bp); | ||
| 299 | } | ||
| 300 | |||
| 301 | int dbg_release_bp_slot(struct perf_event *bp) | ||
| 302 | { | ||
| 303 | if (mutex_is_locked(&nr_bp_mutex)) | ||
| 304 | return -1; | ||
| 305 | |||
| 306 | __release_bp_slot(bp); | ||
| 307 | |||
| 308 | return 0; | ||
| 309 | } | ||
| 278 | 310 | ||
| 279 | int register_perf_hw_breakpoint(struct perf_event *bp) | 311 | int register_perf_hw_breakpoint(struct perf_event *bp) |
| 280 | { | 312 | { |
| @@ -296,6 +328,10 @@ int register_perf_hw_breakpoint(struct perf_event *bp) | |||
| 296 | if (!bp->attr.disabled || !bp->overflow_handler) | 328 | if (!bp->attr.disabled || !bp->overflow_handler) |
| 297 | ret = arch_validate_hwbkpt_settings(bp, bp->ctx->task); | 329 | ret = arch_validate_hwbkpt_settings(bp, bp->ctx->task); |
| 298 | 330 | ||
| 331 | /* if arch_validate_hwbkpt_settings() fails then release bp slot */ | ||
| 332 | if (ret) | ||
| 333 | release_bp_slot(bp); | ||
| 334 | |||
| 299 | return ret; | 335 | return ret; |
| 300 | } | 336 | } |
| 301 | 337 | ||
diff --git a/kernel/kgdb.c b/kernel/kgdb.c index 2eb517e23514..c7ade62e4ef0 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c | |||
| @@ -583,6 +583,9 @@ static void kgdb_wait(struct pt_regs *regs) | |||
| 583 | smp_wmb(); | 583 | smp_wmb(); |
| 584 | atomic_set(&cpu_in_kgdb[cpu], 1); | 584 | atomic_set(&cpu_in_kgdb[cpu], 1); |
| 585 | 585 | ||
| 586 | /* Disable any cpu specific hw breakpoints */ | ||
| 587 | kgdb_disable_hw_debug(regs); | ||
| 588 | |||
| 586 | /* Wait till primary CPU is done with debugging */ | 589 | /* Wait till primary CPU is done with debugging */ |
| 587 | while (atomic_read(&passive_cpu_wait[cpu])) | 590 | while (atomic_read(&passive_cpu_wait[cpu])) |
| 588 | cpu_relax(); | 591 | cpu_relax(); |
