diff options
author | Stephane Eranian <eranian@google.com> | 2015-12-03 17:33:17 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-01-06 05:15:33 -0500 |
commit | 6fc2e83077b05a061afe9b24f2fdff7a0434eb67 (patch) | |
tree | 6445f7732002cfef833745d612f0d05f300a9b35 | |
parent | 61b87cae6361ea6af161c1ffa549898892707b19 (diff) |
perf/x86: Fix LBR related crashes on Intel Atom
This patches fixes the LBR kernel crashes on Intel Atom.
The kernel was assuming that if the CPU supports 64-bit format
LBR, then it has an LBR_SELECT MSR. Atom uses 64-bit LBR format
but does not have LBR_SELECT. That was causing NULL pointer
dereferences in a couple of places.
Signed-off-by: Stephane Eranian <eranian@google.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Cc: kan.liang@intel.com
Fixes: 96f3eda67fcf ("perf/x86/intel: Fix static checker warning in lbr enable")
Link: http://lkml.kernel.org/r/1449182000-31524-2-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_lbr.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c index e2fad0cdca2f..1390148ee2e6 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c +++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c | |||
@@ -161,7 +161,7 @@ static void __intel_pmu_lbr_enable(bool pmi) | |||
161 | */ | 161 | */ |
162 | if (cpuc->lbr_sel) | 162 | if (cpuc->lbr_sel) |
163 | lbr_select = cpuc->lbr_sel->config & x86_pmu.lbr_sel_mask; | 163 | lbr_select = cpuc->lbr_sel->config & x86_pmu.lbr_sel_mask; |
164 | if (!pmi) | 164 | if (!pmi && cpuc->lbr_sel) |
165 | wrmsrl(MSR_LBR_SELECT, lbr_select); | 165 | wrmsrl(MSR_LBR_SELECT, lbr_select); |
166 | 166 | ||
167 | rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); | 167 | rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); |
@@ -430,7 +430,7 @@ static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc) | |||
430 | */ | 430 | */ |
431 | static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) | 431 | static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) |
432 | { | 432 | { |
433 | bool need_info = !(cpuc->lbr_sel->config & LBR_NO_INFO); | 433 | bool need_info = false; |
434 | unsigned long mask = x86_pmu.lbr_nr - 1; | 434 | unsigned long mask = x86_pmu.lbr_nr - 1; |
435 | int lbr_format = x86_pmu.intel_cap.lbr_format; | 435 | int lbr_format = x86_pmu.intel_cap.lbr_format; |
436 | u64 tos = intel_pmu_lbr_tos(); | 436 | u64 tos = intel_pmu_lbr_tos(); |
@@ -438,8 +438,11 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) | |||
438 | int out = 0; | 438 | int out = 0; |
439 | int num = x86_pmu.lbr_nr; | 439 | int num = x86_pmu.lbr_nr; |
440 | 440 | ||
441 | if (cpuc->lbr_sel->config & LBR_CALL_STACK) | 441 | if (cpuc->lbr_sel) { |
442 | num = tos; | 442 | need_info = !(cpuc->lbr_sel->config & LBR_NO_INFO); |
443 | if (cpuc->lbr_sel->config & LBR_CALL_STACK) | ||
444 | num = tos; | ||
445 | } | ||
443 | 446 | ||
444 | for (i = 0; i < num; i++) { | 447 | for (i = 0; i < num; i++) { |
445 | unsigned long lbr_idx = (tos - i) & mask; | 448 | unsigned long lbr_idx = (tos - i) & mask; |