From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752054AbcDWA16 (ORCPT ); Fri, 22 Apr 2016 20:27:58 -0400 Received: from mga14.intel.com ([192.55.52.115]:49492 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751886AbcDWA14 (ORCPT ); Fri, 22 Apr 2016 20:27:56 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.24,519,1455004800"; d="scan'208";a="964660954" From: Vikas Shivappa To: tony.luck@intel.com, ravi.v.shankar@intel.com, fenghua.yu@intel.com, vikas.shivappa@intel.com, vikas.shivappa@linux.intel.com Cc: x86@kernel.org, linux-kernel@vger.kernel.org, hpa@zytor.com, tglx@linutronix.de, mingo@kernel.org, peterz@infradead.org, h.peter.anvin@intel.com Subject: [PATCH 3/4] perf/x86/mbm: Fix mbm counting when RMIDs are reused Date: Fri, 22 Apr 2016 17:27:20 -0700 Message-Id: <1461371241-4258-4-git-send-email-vikas.shivappa@linux.intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1461371241-4258-1-git-send-email-vikas.shivappa@linux.intel.com> References: <1461371241-4258-1-git-send-email-vikas.shivappa@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When multiple instances of perf reuse RMID, then we need to start counting for each instance rather than reporting the current RMID count. This patch adds a st_count(start count) per event to track the same. Signed-off-by: Vikas Shivappa --- arch/x86/events/intel/cqm.c | 71 ++++++++++++++++++++++++++++++++++++++++++--- include/linux/perf_event.h | 1 + 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/arch/x86/events/intel/cqm.c b/arch/x86/events/intel/cqm.c index e679c39..7328b73 100644 --- a/arch/x86/events/intel/cqm.c +++ b/arch/x86/events/intel/cqm.c @@ -484,8 +484,18 @@ static inline void mbm_set_rccount( { u64 tmpval; - tmpval = local64_read(&event->hw.rc_count) + atomic64_read(&rr->value); + tmpval = local64_read(&event->hw.rc_count) + atomic64_read(&rr->value) - + local64_read(&event->hw.st_count); + local64_set(&event->hw.rc_count, tmpval); + + /* + * The st_count(start count) is meant to store the starting bytes + * for an event which is reusing an RMID which already + * had bytes measured.Once we start using the rc_count + * to keep the history bytes, reset the start bytes. + */ + local64_set(&event->hw.st_count, 0UL); local64_set(&event->count, tmpval); } @@ -1025,6 +1035,58 @@ static void init_mbm_sample(u32 rmid, u32 evt_type) on_each_cpu_mask(&cqm_cpumask, __intel_mbm_event_init, &rr, 1); } +static inline bool first_event_ingroup(struct perf_event *group, + struct perf_event *event) +{ + struct list_head *head = &group->hw.cqm_group_entry; + u32 evt_type = event->attr.config; + + if (evt_type == group->attr.config) + return false; + list_for_each_entry(event, head, hw.cqm_group_entry) { + if (evt_type == event->attr.config) + return false; + } + + return true; +} + +/* + * mbm_setup_event - Does mbm specific count initialization + * when multiple events share RMID. + * + * If this is the first mbm event using the RMID, then initialize + * the total_bytes in the RMID and prev_count. + * else only initialize the start count of the event which is the current + * count of the RMID. + * In other words if the RMID has say counted 100MB till now because + * other event was already using it, we start + * from zero for our new event. Because after 1s if user checks the count, + * we need to report for the 1s duration and not the entire duration the + * RMID was being counted. +*/ +static inline void mbm_setup_event(u32 rmid, struct perf_event *group, + struct perf_event *event) +{ + u32 evt_type = event->attr.config; + struct rmid_read rr; + + if (first_event_ingroup(group, event)) { + init_mbm_sample(rmid, evt_type); + } else { + rr = __init_rr(rmid, evt_type, 0); + cqm_mask_call(&rr); + local64_set(&event->hw.st_count, atomic64_read(&rr.value)); + } +} + +static inline void mbm_setup_event_init(struct perf_event *event) +{ + event->hw.is_group_event = false; + local64_set(&event->hw.rc_count, 0UL); + local64_set(&event->hw.st_count, 0UL); +} + /* * Find a group and setup RMID. * @@ -1037,7 +1099,7 @@ static void intel_cqm_setup_event(struct perf_event *event, bool conflict = false; u32 rmid; - event->hw.is_group_event = false; + mbm_setup_event_init(event); list_for_each_entry(iter, &cache_groups, hw.cqm_groups_entry) { rmid = iter->hw.cqm_rmid; @@ -1046,7 +1108,7 @@ static void intel_cqm_setup_event(struct perf_event *event, event->hw.cqm_rmid = rmid; *group = iter; if (is_mbm_event(event->attr.config) && __rmid_valid(rmid)) - init_mbm_sample(rmid, event->attr.config); + mbm_setup_event(rmid, iter, event); return; } @@ -1273,7 +1335,8 @@ static u64 intel_cqm_event_count(struct perf_event *event) if (event->hw.cqm_rmid == rr.rmid) { if (is_mbm_event(event->attr.config)) { tmpval = atomic64_read(&rr.value) + - local64_read(&event->hw.rc_count); + local64_read(&event->hw.rc_count) - + local64_read(&event->hw.st_count); local64_set(&event->count, tmpval); } else { diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index ec7772a..44a7f0c 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -123,6 +123,7 @@ struct hw_perf_event { u32 cqm_rmid; int is_group_event; local64_t rc_count; + local64_t st_count; struct list_head cqm_events_entry; struct list_head cqm_groups_entry; struct list_head cqm_group_entry; -- 1.9.1