|
@@ -13,7 +13,8 @@ enum {
|
|
|
LBR_FORMAT_EIP = 0x02,
|
|
|
LBR_FORMAT_EIP_FLAGS = 0x03,
|
|
|
LBR_FORMAT_EIP_FLAGS2 = 0x04,
|
|
|
- LBR_FORMAT_MAX_KNOWN = LBR_FORMAT_EIP_FLAGS2,
|
|
|
+ LBR_FORMAT_INFO = 0x05,
|
|
|
+ LBR_FORMAT_MAX_KNOWN = LBR_FORMAT_INFO,
|
|
|
};
|
|
|
|
|
|
static enum {
|
|
@@ -186,6 +187,8 @@ static void intel_pmu_lbr_reset_64(void)
|
|
|
for (i = 0; i < x86_pmu.lbr_nr; i++) {
|
|
|
wrmsrl(x86_pmu.lbr_from + i, 0);
|
|
|
wrmsrl(x86_pmu.lbr_to + i, 0);
|
|
|
+ if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
|
|
|
+ wrmsrl(MSR_LBR_INFO_0 + i, 0);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -234,6 +237,8 @@ static void __intel_pmu_lbr_restore(struct x86_perf_task_context *task_ctx)
|
|
|
lbr_idx = (tos - i) & mask;
|
|
|
wrmsrl(x86_pmu.lbr_from + lbr_idx, task_ctx->lbr_from[i]);
|
|
|
wrmsrl(x86_pmu.lbr_to + lbr_idx, task_ctx->lbr_to[i]);
|
|
|
+ if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
|
|
|
+ wrmsrl(MSR_LBR_INFO_0 + i, task_ctx->lbr_info[i]);
|
|
|
}
|
|
|
task_ctx->lbr_stack_state = LBR_NONE;
|
|
|
}
|
|
@@ -255,6 +260,8 @@ static void __intel_pmu_lbr_save(struct x86_perf_task_context *task_ctx)
|
|
|
lbr_idx = (tos - i) & mask;
|
|
|
rdmsrl(x86_pmu.lbr_from + lbr_idx, task_ctx->lbr_from[i]);
|
|
|
rdmsrl(x86_pmu.lbr_to + lbr_idx, task_ctx->lbr_to[i]);
|
|
|
+ if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
|
|
|
+ rdmsrl(MSR_LBR_INFO_0 + i, task_ctx->lbr_info[i]);
|
|
|
}
|
|
|
task_ctx->lbr_stack_state = LBR_VALID;
|
|
|
}
|
|
@@ -416,11 +423,22 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
|
|
|
unsigned long lbr_idx = (tos - i) & mask;
|
|
|
u64 from, to, mis = 0, pred = 0, in_tx = 0, abort = 0;
|
|
|
int skip = 0;
|
|
|
+ u16 cycles = 0;
|
|
|
int lbr_flags = lbr_desc[lbr_format];
|
|
|
|
|
|
rdmsrl(x86_pmu.lbr_from + lbr_idx, from);
|
|
|
rdmsrl(x86_pmu.lbr_to + lbr_idx, to);
|
|
|
|
|
|
+ if (lbr_format == LBR_FORMAT_INFO) {
|
|
|
+ u64 info;
|
|
|
+
|
|
|
+ rdmsrl(MSR_LBR_INFO_0 + lbr_idx, info);
|
|
|
+ mis = !!(info & LBR_INFO_MISPRED);
|
|
|
+ pred = !mis;
|
|
|
+ in_tx = !!(info & LBR_INFO_IN_TX);
|
|
|
+ abort = !!(info & LBR_INFO_ABORT);
|
|
|
+ cycles = (info & LBR_INFO_CYCLES);
|
|
|
+ }
|
|
|
if (lbr_flags & LBR_EIP_FLAGS) {
|
|
|
mis = !!(from & LBR_FROM_FLAG_MISPRED);
|
|
|
pred = !mis;
|
|
@@ -450,6 +468,7 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
|
|
|
cpuc->lbr_entries[out].predicted = pred;
|
|
|
cpuc->lbr_entries[out].in_tx = in_tx;
|
|
|
cpuc->lbr_entries[out].abort = abort;
|
|
|
+ cpuc->lbr_entries[out].cycles = cycles;
|
|
|
cpuc->lbr_entries[out].reserved = 0;
|
|
|
out++;
|
|
|
}
|