Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753486AbbLCUDV (ORCPT ); Thu, 3 Dec 2015 15:03:21 -0500 Received: from mail-pa0-f48.google.com ([209.85.220.48]:35997 "EHLO mail-pa0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753285AbbLCUDU (ORCPT ); Thu, 3 Dec 2015 15:03:20 -0500 From: Stephane Eranian To: linux-kernel@vger.kernel.org Cc: acme@redhat.com, peterz@infradead.org, mingo@elte.hu, ak@linux.intel.com, kan.liang@intel.com Subject: [PATCH v2 1/2] perf/x86: fix PEBS and LBR issues on Intel Atom Date: Thu, 3 Dec 2015 21:03:09 +0100 Message-Id: <1449172990-30183-2-git-send-email-eranian@google.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1449172990-30183-1-git-send-email-eranian@google.com> References: <1449172990-30183-1-git-send-email-eranian@google.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3233 Lines: 95 This patches fixes a number of problems in the PEBS and LBR support of Intel Atom. Those bugs were introduced by the recent changes to the PEBS code to handle multiple entries. The kernel was assuming that if the CPU support 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. The kernel had a pointer arithmetic error in intel_pmu_drain_pebs_core() when calculating the number of records present in the PEBS buffer. The get_next_pebs_record_by_bit() was called on PEBS fm0 which does not use the pebs_record_nhm layout. This patch fixes all those problems and has PEBS and LBR working again. Signed-off-by: Stephane Eranian --- arch/x86/kernel/cpu/perf_event_intel_ds.c | 9 ++++++++- arch/x86/kernel/cpu/perf_event_intel_lbr.c | 11 +++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 5db1c77..dae5f93 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -1101,6 +1101,13 @@ get_next_pebs_record_by_bit(void *base, void *top, int bit) void *at; u64 pebs_status; + /* + * fmt0 does not have a status bitfield (does not use + * perf_record_nhm format) + */ + if (x86_pmu.intel_cap.pebs_format < 1) + return base; + if (base == NULL) return NULL; @@ -1186,7 +1193,7 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) if (!event->attr.precise_ip) return; - n = (top - at) / x86_pmu.pebs_record_size; + n = top - at; if (n <= 0) return; diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c index e2fad0c..1390148 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) */ if (cpuc->lbr_sel) lbr_select = cpuc->lbr_sel->config & x86_pmu.lbr_sel_mask; - if (!pmi) + if (!pmi && cpuc->lbr_sel) wrmsrl(MSR_LBR_SELECT, lbr_select); rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); @@ -430,7 +430,7 @@ static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc) */ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) { - bool need_info = !(cpuc->lbr_sel->config & LBR_NO_INFO); + bool need_info = false; unsigned long mask = x86_pmu.lbr_nr - 1; int lbr_format = x86_pmu.intel_cap.lbr_format; u64 tos = intel_pmu_lbr_tos(); @@ -438,8 +438,11 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) int out = 0; int num = x86_pmu.lbr_nr; - if (cpuc->lbr_sel->config & LBR_CALL_STACK) - num = tos; + if (cpuc->lbr_sel) { + need_info = !(cpuc->lbr_sel->config & LBR_NO_INFO); + if (cpuc->lbr_sel->config & LBR_CALL_STACK) + num = tos; + } for (i = 0; i < num; i++) { unsigned long lbr_idx = (tos - i) & mask; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/