Commit d4cf1949 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar

perf/x86/intel: Add {rd,wr}lbr_{to,from} wrappers

The whole rdmsr()/wrmsr() for lbr_from got a little unweildy with the
sign extension quirk, provide a few simple wrappers to clean things up.
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: David Carrillo-Cisneros <davidcc@google.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 71adae99
...@@ -289,12 +289,42 @@ inline u64 lbr_from_signext_quirk_wr(u64 val) ...@@ -289,12 +289,42 @@ inline u64 lbr_from_signext_quirk_wr(u64 val)
*/ */
u64 lbr_from_signext_quirk_rd(u64 val) u64 lbr_from_signext_quirk_rd(u64 val)
{ {
if (static_branch_unlikely(&lbr_from_quirk_key)) if (static_branch_unlikely(&lbr_from_quirk_key)) {
/* /*
* Quirk is on when TSX is not enabled. Therefore TSX * Quirk is on when TSX is not enabled. Therefore TSX
* flags must be read as OFF. * flags must be read as OFF.
*/ */
val &= ~(LBR_FROM_FLAG_IN_TX | LBR_FROM_FLAG_ABORT); val &= ~(LBR_FROM_FLAG_IN_TX | LBR_FROM_FLAG_ABORT);
}
return val;
}
static inline void wrlbr_from(unsigned int idx, u64 val)
{
val = lbr_from_signext_quirk_wr(val);
wrmsrl(x86_pmu.lbr_from + idx, val);
}
static inline void wrlbr_to(unsigned int idx, u64 val)
{
wrmsrl(x86_pmu.lbr_to + idx, val);
}
static inline u64 rdlbr_from(unsigned int idx)
{
u64 val;
rdmsrl(x86_pmu.lbr_from + idx, val);
return lbr_from_signext_quirk_rd(val);
}
static inline u64 rdlbr_to(unsigned int idx)
{
u64 val;
rdmsrl(x86_pmu.lbr_from + idx, val);
return val; return val;
} }
...@@ -314,9 +344,9 @@ static void __intel_pmu_lbr_restore(struct x86_perf_task_context *task_ctx) ...@@ -314,9 +344,9 @@ static void __intel_pmu_lbr_restore(struct x86_perf_task_context *task_ctx)
tos = task_ctx->tos; tos = task_ctx->tos;
for (i = 0; i < tos; i++) { for (i = 0; i < tos; i++) {
lbr_idx = (tos - i) & mask; lbr_idx = (tos - i) & mask;
wrmsrl(x86_pmu.lbr_from + lbr_idx, wrlbr_from(lbr_idx, task_ctx->lbr_from[i]);
lbr_from_signext_quirk_wr(task_ctx->lbr_from[i])); wrlbr_to (lbr_idx, task_ctx->lbr_to[i]);
wrmsrl(x86_pmu.lbr_to + lbr_idx, task_ctx->lbr_to[i]);
if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO) if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
wrmsrl(MSR_LBR_INFO_0 + lbr_idx, task_ctx->lbr_info[i]); wrmsrl(MSR_LBR_INFO_0 + lbr_idx, task_ctx->lbr_info[i]);
} }
...@@ -326,9 +356,9 @@ static void __intel_pmu_lbr_restore(struct x86_perf_task_context *task_ctx) ...@@ -326,9 +356,9 @@ static void __intel_pmu_lbr_restore(struct x86_perf_task_context *task_ctx)
static void __intel_pmu_lbr_save(struct x86_perf_task_context *task_ctx) static void __intel_pmu_lbr_save(struct x86_perf_task_context *task_ctx)
{ {
int i;
unsigned lbr_idx, mask; unsigned lbr_idx, mask;
u64 tos, val; u64 tos;
int i;
if (task_ctx->lbr_callstack_users == 0) { if (task_ctx->lbr_callstack_users == 0) {
task_ctx->lbr_stack_state = LBR_NONE; task_ctx->lbr_stack_state = LBR_NONE;
...@@ -339,9 +369,8 @@ static void __intel_pmu_lbr_save(struct x86_perf_task_context *task_ctx) ...@@ -339,9 +369,8 @@ static void __intel_pmu_lbr_save(struct x86_perf_task_context *task_ctx)
tos = intel_pmu_lbr_tos(); tos = intel_pmu_lbr_tos();
for (i = 0; i < tos; i++) { for (i = 0; i < tos; i++) {
lbr_idx = (tos - i) & mask; lbr_idx = (tos - i) & mask;
rdmsrl(x86_pmu.lbr_from + lbr_idx, val); task_ctx->lbr_from[i] = rdlbr_from(lbr_idx);
task_ctx->lbr_from[i] = lbr_from_signext_quirk_rd(val); task_ctx->lbr_to[i] = rdlbr_to(lbr_idx);
rdmsrl(x86_pmu.lbr_to + lbr_idx, task_ctx->lbr_to[i]);
if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO) if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
rdmsrl(MSR_LBR_INFO_0 + lbr_idx, task_ctx->lbr_info[i]); rdmsrl(MSR_LBR_INFO_0 + lbr_idx, task_ctx->lbr_info[i]);
} }
...@@ -517,10 +546,8 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) ...@@ -517,10 +546,8 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
u16 cycles = 0; u16 cycles = 0;
int lbr_flags = lbr_desc[lbr_format]; int lbr_flags = lbr_desc[lbr_format];
rdmsrl(x86_pmu.lbr_from + lbr_idx, from); from = rdlbr_from(lbr_idx);
from = lbr_from_signext_quirk_rd(from); to = rdlbr_to(lbr_idx);
rdmsrl(x86_pmu.lbr_to + lbr_idx, to);
if (lbr_format == LBR_FORMAT_INFO && need_info) { if (lbr_format == LBR_FORMAT_INFO && need_info) {
u64 info; u64 info;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment