diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2010-03-09 05:41:02 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-03-10 07:23:39 -0500 |
commit | d80c7502ff63aa0d99d8c0c5803d28bbef67a74e (patch) | |
tree | f2873d7f09a667e207f9284b590eb4ea3e9e61bd /arch | |
parent | 7645a24cbd01cbf4865d1273d5ddaa8d8c2ccb3a (diff) |
perf, x86: Fixup the PEBS handler for Core2 cpus
Pull the core handler in line with the nhm one, also make sure we always
drain the buffer.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_ds.c | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 242369488e72..1bfd59beb658 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c | |||
@@ -472,20 +472,39 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) | |||
472 | struct pt_regs regs; | 472 | struct pt_regs regs; |
473 | int n; | 473 | int n; |
474 | 474 | ||
475 | if (!event || !ds || !x86_pmu.pebs) | 475 | if (!ds || !x86_pmu.pebs) |
476 | return; | 476 | return; |
477 | 477 | ||
478 | at = (struct pebs_record_core *)(unsigned long)ds->pebs_buffer_base; | 478 | at = (struct pebs_record_core *)(unsigned long)ds->pebs_buffer_base; |
479 | top = (struct pebs_record_core *)(unsigned long)ds->pebs_index; | 479 | top = (struct pebs_record_core *)(unsigned long)ds->pebs_index; |
480 | 480 | ||
481 | if (top <= at) | 481 | /* |
482 | * Whatever else happens, drain the thing | ||
483 | */ | ||
484 | ds->pebs_index = ds->pebs_buffer_base; | ||
485 | |||
486 | if (!test_bit(0, cpuc->active_mask)) | ||
482 | return; | 487 | return; |
483 | 488 | ||
484 | ds->pebs_index = ds->pebs_buffer_base; | 489 | WARN_ON_ONCE(!event); |
490 | |||
491 | if (!event->attr.precise) | ||
492 | return; | ||
493 | |||
494 | n = top - at; | ||
495 | if (n <= 0) | ||
496 | return; | ||
485 | 497 | ||
486 | if (!intel_pmu_save_and_restart(event)) | 498 | if (!intel_pmu_save_and_restart(event)) |
487 | return; | 499 | return; |
488 | 500 | ||
501 | /* | ||
502 | * Should not happen, we program the threshold at 1 and do not | ||
503 | * set a reset value. | ||
504 | */ | ||
505 | WARN_ON_ONCE(n > 1); | ||
506 | at += n - 1; | ||
507 | |||
489 | perf_sample_data_init(&data, 0); | 508 | perf_sample_data_init(&data, 0); |
490 | data.period = event->hw.last_period; | 509 | data.period = event->hw.last_period; |
491 | 510 | ||
@@ -495,14 +514,6 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) | |||
495 | data.raw = &raw; | 514 | data.raw = &raw; |
496 | } | 515 | } |
497 | 516 | ||
498 | n = top - at; | ||
499 | |||
500 | /* | ||
501 | * Should not happen, we program the threshold at 1 and do not | ||
502 | * set a reset value. | ||
503 | */ | ||
504 | WARN_ON_ONCE(n > 1); | ||
505 | |||
506 | /* | 517 | /* |
507 | * We use the interrupt regs as a base because the PEBS record | 518 | * We use the interrupt regs as a base because the PEBS record |
508 | * does not contain a full regs set, specifically it seems to | 519 | * does not contain a full regs set, specifically it seems to |
@@ -545,12 +556,11 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) | |||
545 | at = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base; | 556 | at = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base; |
546 | top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index; | 557 | top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index; |
547 | 558 | ||
548 | if (top <= at) | ||
549 | return; | ||
550 | |||
551 | ds->pebs_index = ds->pebs_buffer_base; | 559 | ds->pebs_index = ds->pebs_buffer_base; |
552 | 560 | ||
553 | n = top - at; | 561 | n = top - at; |
562 | if (n <= 0) | ||
563 | return; | ||
554 | 564 | ||
555 | /* | 565 | /* |
556 | * Should not happen, we program the threshold at 1 and do not | 566 | * Should not happen, we program the threshold at 1 and do not |