From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757453AbbEVPbc (ORCPT ); Fri, 22 May 2015 11:31:32 -0400 Received: from mga11.intel.com ([192.55.52.93]:36421 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756981AbbEVPb1 (ORCPT ); Fri, 22 May 2015 11:31:27 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.13,476,1427785200"; d="scan'208";a="698939178" From: Alexander Shishkin To: Peter Zijlstra , Ingo Molnar Cc: linux-kernel@vger.kernel.org, Paul Mackerras , adrian.hunter@intel.com, x86@kernel.org, hpa@zytor.com, acme@infradead.org, Alexander Shishkin Subject: [PATCH v1 3/7] perf/x86/intel/pt: Untangle pt_buffer_reset_markers() Date: Fri, 22 May 2015 18:30:22 +0300 Message-Id: <1432308626-18845-4-git-send-email-alexander.shishkin@linux.intel.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1432308626-18845-1-git-send-email-alexander.shishkin@linux.intel.com> References: <1432308626-18845-1-git-send-email-alexander.shishkin@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Currently, pt_buffer_reset_markers() is a difficult to read knot of arithmetics with a redundant check for multiple-entry topa capability, a commented out wakeup marker placement and a logical error wrt to stop marker placement. The latter happens when write head is not page aligned and results in stop marker being placed one page earlier than it actually should. All these problems only affect PT implementations that support multiple-entry topa tables (read: proper sg). For single-entry topa implementations, there is no functional impact. This patch deals with all of the above. Tested on both single-entry and multiple-entry topa PT implementations. Signed-off-by: Alexander Shishkin --- arch/x86/kernel/cpu/perf_event_intel_pt.c | 34 ++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event_intel_pt.c b/arch/x86/kernel/cpu/perf_event_intel_pt.c index ac08b67c07..8a4595650d 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_pt.c +++ b/arch/x86/kernel/cpu/perf_event_intel_pt.c @@ -615,7 +615,8 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf, struct perf_output_handle *handle) { - unsigned long idx, npages, end; + unsigned long head = local64_read(&buf->head); + unsigned long idx, npages, wakeup; if (buf->snapshot) return 0; @@ -634,17 +635,26 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf, buf->topa_index[buf->stop_pos]->stop = 0; buf->topa_index[buf->intr_pos]->intr = 0; - if (pt_cap_get(PT_CAP_topa_multiple_entries)) { - npages = (handle->size + 1) >> PAGE_SHIFT; - end = (local64_read(&buf->head) >> PAGE_SHIFT) + npages; - /*if (end > handle->wakeup >> PAGE_SHIFT) - end = handle->wakeup >> PAGE_SHIFT;*/ - idx = end & (buf->nr_pages - 1); - buf->stop_pos = idx; - idx = (local64_read(&buf->head) >> PAGE_SHIFT) + npages - 1; - idx &= buf->nr_pages - 1; - buf->intr_pos = idx; - } + /* how many pages till the STOP marker */ + npages = handle->size >> PAGE_SHIFT; + + /* if it's on a page boundary, fill up one more page */ + if (!offset_in_page(head + handle->size + 1)) + npages++; + + idx = (head >> PAGE_SHIFT) + npages; + idx &= buf->nr_pages - 1; + buf->stop_pos = idx; + + wakeup = handle->wakeup >> PAGE_SHIFT; + + /* in the worst case, wake up the consumer one page before hard stop */ + idx = (head >> PAGE_SHIFT) + npages - 1; + if (idx > wakeup) + idx = wakeup; + + idx &= buf->nr_pages - 1; + buf->intr_pos = idx; buf->topa_index[buf->stop_pos]->stop = 1; buf->topa_index[buf->intr_pos]->intr = 1; -- 2.1.4