[RFC][PATCH] perf, pebs: Add PEBS v3 record decoding

From: Peter Zijlstra
Date: Tue May 12 2015 - 09:26:32 EST




So seeing how I have both this series and Andi's SKL patches, I did the
below on top of them both.

Could someone try that?

---
Subject: perf, pebs: Add PEBS v3 record decoding
From: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Date: Tue May 12 15:18:18 CEST 2015

PEBS v3 as present on Skylake fixed the long standing issue of the
status bits. They now really reflect the events that generated the
record.

Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
---
arch/x86/kernel/cpu/perf_event_intel_ds.c | 30 +++++++++++++++++++-----------
1 file changed, 19 insertions(+), 11 deletions(-)

--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -1034,6 +1034,9 @@ get_next_pebs_record_by_bit(void *base,
struct pebs_record_nhm *p = at;

if (test_bit(bit, (unsigned long *)&p->status)) {
+ /* PEBS v3 has accurate status bits */
+ if (x86_pmu.intel_cap.pebs_format >= 3)
+ return at;

if (p->status == (1 << bit))
return at;
@@ -1055,20 +1058,18 @@ static void __intel_pmu_pebs_event(struc
{
struct perf_sample_data data;
struct pt_regs regs;
- int i;
void *at = get_next_pebs_record_by_bit(base, top, bit);

if (!intel_pmu_save_and_restart(event) &&
!(event->hw.flags & PERF_X86_EVENT_AUTO_RELOAD))
return;

- if (count > 1) {
- for (i = 0; i < count - 1; i++) {
- setup_pebs_sample_data(event, iregs, at, &data, &regs);
- perf_event_output(event, &data, &regs);
- at += x86_pmu.pebs_record_size;
- at = get_next_pebs_record_by_bit(at, top, bit);
- }
+ while (count > 1) {
+ setup_pebs_sample_data(event, iregs, at, &data, &regs);
+ perf_event_output(event, &data, &regs);
+ at += x86_pmu.pebs_record_size;
+ at = get_next_pebs_record_by_bit(at, top, bit);
+ count--;
}

setup_pebs_sample_data(event, iregs, at, &data, &regs);
@@ -1124,9 +1125,9 @@ static void intel_pmu_drain_pebs_nhm(str
struct debug_store *ds = cpuc->ds;
struct perf_event *event;
void *base, *at, *top;
- int bit;
short counts[MAX_PEBS_EVENTS] = {};
short error[MAX_PEBS_EVENTS] = {};
+ int bit, i;

if (!x86_pmu.pebs_active)
return;
@@ -1142,6 +1143,15 @@ static void intel_pmu_drain_pebs_nhm(str
for (at = base; at < top; at += x86_pmu.pebs_record_size) {
struct pebs_record_nhm *p = at;

+ /* PEBS v3 has accurate status bits */
+ if (x86_pmu.intel_cap.pebs_format >= 3) {
+ for_each_set_bit(bit, (unsigned long *)&p->status,
+ MAX_PEBS_EVENTS)
+ counts[bit]++;
+
+ continue;
+ }
+
bit = find_first_bit((unsigned long *)&p->status,
x86_pmu.max_pebs_events);
if (bit >= x86_pmu.max_pebs_events)
@@ -1171,8 +1181,6 @@ static void intel_pmu_drain_pebs_nhm(str
pebs_status = p->status & cpuc->pebs_enabled;
pebs_status &= (1ULL << MAX_PEBS_EVENTS) - 1;
if (pebs_status != (1 << bit)) {
- u8 i;
-
for_each_set_bit(i, (unsigned long *)&pebs_status,
MAX_PEBS_EVENTS)
error[i]++;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/