All of lore.kernel.org
 help / color / mirror / Atom feed
From: Robert Richter <robert.richter@amd.com>
To: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>,
	Stephane Eranian <eranian@google.com>,
	LKML <linux-kernel@vger.kernel.org>,
	Robert Richter <robert.richter@amd.com>
Subject: [PATCH 08/10] perf, amd: Enable northbridge counters on family 15h
Date: Tue, 19 Jun 2012 20:10:46 +0200	[thread overview]
Message-ID: <1340129448-8690-9-git-send-email-robert.richter@amd.com> (raw)
In-Reply-To: <1340129448-8690-1-git-send-email-robert.richter@amd.com>

This patch enables northbridge counter support for family 15h cpus.
Northbridge counters on family 15h have a separate counter bit mask
and constraints. NB counters are enabled if the nb performance counter
extensions cpuid flag is set.

Signed-off-by: Robert Richter <robert.richter@amd.com>
---
 arch/x86/include/asm/cpufeature.h    |    2 +
 arch/x86/include/asm/perf_event.h    |    3 ++
 arch/x86/kernel/cpu/perf_event.c     |   21 +++++++++++++++-
 arch/x86/kernel/cpu/perf_event_amd.c |   42 +++++++++++++++++++++++++++------
 4 files changed, 58 insertions(+), 10 deletions(-)

diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 340ee49..404bb64 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -164,6 +164,7 @@
 #define X86_FEATURE_TBM		(6*32+21) /* trailing bit manipulations */
 #define X86_FEATURE_TOPOEXT	(6*32+22) /* topology extensions CPUID leafs */
 #define X86_FEATURE_PERFCTR_CORE (6*32+23) /* core performance counter extensions */
+#define X86_FEATURE_PERFCTR_NB	(6*32+24) /* nb performance counter extensions */
 
 /*
  * Auxiliary flags: Linux defined - For features scattered in various
@@ -301,6 +302,7 @@ extern const char * const x86_power_flags[32];
 #define cpu_has_hypervisor	boot_cpu_has(X86_FEATURE_HYPERVISOR)
 #define cpu_has_pclmulqdq	boot_cpu_has(X86_FEATURE_PCLMULQDQ)
 #define cpu_has_perfctr_core	boot_cpu_has(X86_FEATURE_PERFCTR_CORE)
+#define cpu_has_perfctr_nb	boot_cpu_has(X86_FEATURE_PERFCTR_NB)
 #define cpu_has_cx8		boot_cpu_has(X86_FEATURE_CX8)
 #define cpu_has_cx16		boot_cpu_has(X86_FEATURE_CX16)
 
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index ffdf5e0..637a72b7 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -9,6 +9,8 @@
 #define INTEL_PMC_MAX_FIXED					3
 #define INTEL_PMC_IDX_FIXED				       32
 
+#define AMD64_PMC_IDX_NB				       32
+
 #define X86_PMC_IDX_MAX					       64
 
 #define MSR_ARCH_PERFMON_PERFCTR0			      0xc1
@@ -48,6 +50,7 @@
 	 AMD64_EVENTSEL_EVENT)
 #define AMD64_NUM_COUNTERS				4
 #define AMD64_NUM_COUNTERS_CORE				6
+#define AMD64_NUM_COUNTERS_NB				4
 
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL		0x3c
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK		(0x00 << 8)
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 9fbf70a..1d59cac 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -805,6 +805,13 @@ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader,
 	return n;
 }
 
+static inline int x86_pmu_rdpmc_index(int index)
+{
+	if (cpu_has_perfctr_nb && (index >= AMD64_PMC_IDX_NB))
+		return index - AMD64_PMC_IDX_NB + AMD64_NUM_COUNTERS_CORE;
+	return index;
+}
+
 static inline void x86_assign_hw_event(struct perf_event *event,
 				struct cpu_hw_events *cpuc, int i)
 {
@@ -824,7 +831,7 @@ static inline void x86_assign_hw_event(struct perf_event *event,
 	} else {
 		hwc->config_base = x86_pmu_config_addr(hwc->idx);
 		hwc->event_base  = x86_pmu_event_addr(hwc->idx);
-		hwc->event_base_rdpmc = hwc->idx;
+		hwc->event_base_rdpmc = x86_pmu_rdpmc_index(hwc->idx);
 	}
 }
 
@@ -1194,7 +1201,17 @@ int x86_pmu_handle_irq(struct pt_regs *regs)
 			 * might still deliver spurious interrupts still
 			 * in flight. Catch them:
 			 */
-			if (__test_and_clear_bit(idx, cpuc->running))
+			if (idx >= AMD64_PMC_IDX_NB && cpuc->amd_nb && cpuc->amd_nb->owners[idx]) {
+				/*
+				 * AMD NB counters send nmis to all
+				 * cpus on the node. Fix this later:
+				 * This swallows all nmis on the node
+				 * if a nb counter is active and even
+				 * if there was no overflow.
+				 */
+				handled++;
+				__set_bit(idx, cpuc->running);
+			} else if (__test_and_clear_bit(idx, cpuc->running))
 				handled++;
 			continue;
 		}
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
index e538512..7a870d2 100644
--- a/arch/x86/kernel/cpu/perf_event_amd.c
+++ b/arch/x86/kernel/cpu/perf_event_amd.c
@@ -7,6 +7,9 @@
 
 #include "perf_event.h"
 
+#define AMD64_COUNTERS_MASK_NB	\
+	(((1ULL << AMD64_NUM_COUNTERS_NB) - 1) << AMD64_PMC_IDX_NB)
+
 static __initconst const u64 amd_hw_cache_event_ids
 				[PERF_COUNT_HW_CACHE_MAX]
 				[PERF_COUNT_HW_CACHE_OP_MAX]
@@ -461,12 +464,13 @@ static struct attribute *amd_format_attr[] = {
  * (**) only one unitmask enabled at a time
  */
 
-static struct event_constraint amd_f15_PMC0  = EVENT_CONSTRAINT(0, 0x01, 0);
-static struct event_constraint amd_f15_PMC20 = EVENT_CONSTRAINT(0, 0x07, 0);
-static struct event_constraint amd_f15_PMC3  = EVENT_CONSTRAINT(0, 0x08, 0);
-static struct event_constraint amd_f15_PMC30 = EVENT_CONSTRAINT_OVERLAP(0, 0x09, 0);
-static struct event_constraint amd_f15_PMC50 = EVENT_CONSTRAINT(0, 0x3F, 0);
-static struct event_constraint amd_f15_PMC53 = EVENT_CONSTRAINT(0, 0x38, 0);
+static struct event_constraint amd_f15_PMC0  	= EVENT_CONSTRAINT(0, 0x01, 0);
+static struct event_constraint amd_f15_PMC20	= EVENT_CONSTRAINT(0, 0x07, 0);
+static struct event_constraint amd_f15_PMC3	= EVENT_CONSTRAINT(0, 0x08, 0);
+static struct event_constraint amd_f15_PMC30	= EVENT_CONSTRAINT_OVERLAP(0, 0x09, 0);
+static struct event_constraint amd_f15_PMC50	= EVENT_CONSTRAINT(0, 0x3F, 0);
+static struct event_constraint amd_f15_PMC53	= EVENT_CONSTRAINT(0, 0x38, 0);
+static struct event_constraint amd_f15_NBPMC30	= EVENT_CONSTRAINT(0, AMD64_COUNTERS_MASK_NB, 0);
 
 static struct event_constraint *
 __amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *event)
@@ -533,8 +537,7 @@ __amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *
 			return &amd_f15_PMC20;
 		}
 	case AMD_EVENT_NB:
-		/* not yet implemented */
-		return &emptyconstraint;
+		return &amd_f15_NBPMC30;
 	default:
 		return &emptyconstraint;
 	}
@@ -635,6 +638,28 @@ static int setup_perfctr_core(void)
 	return 0;
 }
 
+static int setup_perfctr_nb(void)
+{
+	if (!cpu_has_perfctr_nb)
+		return -ENODEV;
+
+	/* requires core perfctrs initialized first */
+	if (x86_pmu.eventsel != MSR_F15H_PERF_CTL)
+		return -ENODEV;
+
+	if (x86_pmu.get_event_constraints == amd_get_event_constraints) {
+		WARN(1, KERN_ERR "hw perf events nb counter needs constraints handler!");
+		return -ENODEV;
+	}
+
+	x86_pmu.num_counters	+= AMD64_NUM_COUNTERS_NB;
+	x86_pmu.counters_mask64	|= AMD64_COUNTERS_MASK_NB;
+
+	printk(KERN_INFO "perf: AMD northbridge performance counters detected\n");
+
+	return 0;
+}
+
 __init int amd_pmu_init(void)
 {
 	/* Performance-monitoring supported from K7 and later: */
@@ -645,6 +670,7 @@ __init int amd_pmu_init(void)
 
 	setup_event_constraints();
 	setup_perfctr_core();
+	setup_perfctr_nb();
 
 	/* Events are common for all AMDs */
 	memcpy(hw_cache_event_ids, amd_hw_cache_event_ids,
-- 
1.7.8.4



  parent reply	other threads:[~2012-06-19 18:12 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-06-19 18:10 [PATCH 00/10] perf, x86: Add northbridge counter support for AMD family 15h Robert Richter
2012-06-19 18:10 ` [PATCH 01/10] perf, amd: Rework northbridge event constraints handler Robert Richter
2012-06-19 18:10 ` [PATCH 02/10] perf, x86: Rework counter reservation code Robert Richter
2012-06-19 18:10 ` [PATCH 03/10] perf, x86: Use bitmasks for generic counters Robert Richter
2012-06-19 18:10 ` [PATCH 04/10] perf, x86: Rename Intel specific macros Robert Richter
2012-06-19 18:10 ` [PATCH 05/10] perf, x86: Move Intel specific code to intel_pmu_init() Robert Richter
2012-06-20  9:36   ` Peter Zijlstra
2012-06-20 14:22     ` Robert Richter
2012-06-19 18:10 ` [PATCH 06/10] perf, amd: Unify AMD's generic and family 15h pmus Robert Richter
2012-06-19 18:10 ` [PATCH 07/10] perf, amd: Generalize northbridge constraints code for family 15h Robert Richter
2012-06-19 18:10 ` Robert Richter [this message]
2012-06-19 18:10 ` [PATCH 09/10] perf, x86: Improve debug output in check_hw_exists() Robert Richter
2012-06-19 18:10 ` [PATCH 10/10] perf, amd: Check northbridge event config value Robert Richter
2012-06-20  8:36 ` [PATCH 00/10] perf, x86: Add northbridge counter support for AMD family 15h Stephane Eranian
2012-06-20  8:54   ` Peter Zijlstra
     [not found] ` <CABPqkBS9hRxKLsecVK+AgRue6oqTtAg4=0Dpd5Z2VwAUja50fw@mail.gmail.com>
2012-06-20  9:29   ` Robert Richter
2012-06-20  9:38     ` Peter Zijlstra
2012-06-20 10:00       ` Robert Richter
2012-06-20 10:16         ` Peter Zijlstra
2012-06-20 12:29           ` Robert Richter
2012-06-20 15:54             ` Peter Zijlstra
2012-06-20 16:08               ` Peter Zijlstra
2012-06-20 16:21               ` Stephane Eranian
2012-06-20 10:46         ` Stephane Eranian
2012-06-20 12:41           ` Robert Richter
2012-06-20  9:41     ` Peter Zijlstra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1340129448-8690-9-git-send-email-robert.richter@amd.com \
    --to=robert.richter@amd.com \
    --cc=eranian@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.