|
@@ -284,6 +284,7 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
|
|
|
int lbr_format = x86_pmu.intel_cap.lbr_format;
|
|
|
u64 tos = intel_pmu_lbr_tos();
|
|
|
int i;
|
|
|
+ int out = 0;
|
|
|
|
|
|
for (i = 0; i < x86_pmu.lbr_nr; i++) {
|
|
|
unsigned long lbr_idx = (tos - i) & mask;
|
|
@@ -306,15 +307,27 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
|
|
|
}
|
|
|
from = (u64)((((s64)from) << skip) >> skip);
|
|
|
|
|
|
- cpuc->lbr_entries[i].from = from;
|
|
|
- cpuc->lbr_entries[i].to = to;
|
|
|
- cpuc->lbr_entries[i].mispred = mis;
|
|
|
- cpuc->lbr_entries[i].predicted = pred;
|
|
|
- cpuc->lbr_entries[i].in_tx = in_tx;
|
|
|
- cpuc->lbr_entries[i].abort = abort;
|
|
|
- cpuc->lbr_entries[i].reserved = 0;
|
|
|
+ /*
|
|
|
+ * Some CPUs report duplicated abort records,
|
|
|
+ * with the second entry not having an abort bit set.
|
|
|
+ * Skip them here. This loop runs backwards,
|
|
|
+ * so we need to undo the previous record.
|
|
|
+ * If the abort just happened outside the window
|
|
|
+ * the extra entry cannot be removed.
|
|
|
+ */
|
|
|
+ if (abort && x86_pmu.lbr_double_abort && out > 0)
|
|
|
+ out--;
|
|
|
+
|
|
|
+ cpuc->lbr_entries[out].from = from;
|
|
|
+ cpuc->lbr_entries[out].to = to;
|
|
|
+ cpuc->lbr_entries[out].mispred = mis;
|
|
|
+ cpuc->lbr_entries[out].predicted = pred;
|
|
|
+ cpuc->lbr_entries[out].in_tx = in_tx;
|
|
|
+ cpuc->lbr_entries[out].abort = abort;
|
|
|
+ cpuc->lbr_entries[out].reserved = 0;
|
|
|
+ out++;
|
|
|
}
|
|
|
- cpuc->lbr_stack.nr = i;
|
|
|
+ cpuc->lbr_stack.nr = out;
|
|
|
}
|
|
|
|
|
|
void intel_pmu_lbr_read(void)
|