From: tip-bot for Maria Dimakopoulou <tipbot@zytor.com>
To: linux-tip-commits@vger.kernel.org
Cc: eranian@google.com, tglx@linutronix.de,
maria.n.dimakopoulou@gmail.com, linux-kernel@vger.kernel.org,
hpa@zytor.com, mingo@kernel.org, peterz@infradead.org
Subject: [tip:perf/core] perf/x86/intel: Add cross-HT counter exclusion infrastructure
Date: Thu, 2 Apr 2015 11:42:47 -0700 [thread overview]
Message-ID: <tip-6f6539cad926f55d5eb6e79d05bbe99f0d54d56d@git.kernel.org> (raw)
In-Reply-To: <1416251225-17721-6-git-send-email-eranian@google.com>
Commit-ID: 6f6539cad926f55d5eb6e79d05bbe99f0d54d56d
Gitweb: http://git.kernel.org/tip/6f6539cad926f55d5eb6e79d05bbe99f0d54d56d
Author: Maria Dimakopoulou <maria.n.dimakopoulou@gmail.com>
AuthorDate: Mon, 17 Nov 2014 20:06:57 +0100
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Thu, 2 Apr 2015 17:33:11 +0200
perf/x86/intel: Add cross-HT counter exclusion infrastructure
This patch adds a new shared_regs style structure to the
per-cpu x86 state (cpuc). It is used to coordinate access
between counters which must be used with exclusion across
HyperThreads on Intel processors. This new struct is not
needed on each PMU, thus is is allocated on demand.
Signed-off-by: Maria Dimakopoulou <maria.n.dimakopoulou@gmail.com>
[peterz: spinlock_t -> raw_spinlock_t]
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Stephane Eranian <eranian@google.com>
Cc: bp@alien8.de
Cc: jolsa@redhat.com
Cc: kan.liang@intel.com
Link: http://lkml.kernel.org/r/1416251225-17721-6-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/kernel/cpu/perf_event.h | 32 +++++++++++++++
arch/x86/kernel/cpu/perf_event_intel.c | 71 +++++++++++++++++++++++++++++++---
2 files changed, 98 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 24a6505..f31f90e 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -71,6 +71,7 @@ struct event_constraint {
#define PERF_X86_EVENT_COMMITTED 0x8 /* event passed commit_txn */
#define PERF_X86_EVENT_PEBS_LD_HSW 0x10 /* haswell style datala, load */
#define PERF_X86_EVENT_PEBS_NA_HSW 0x20 /* haswell style datala, unknown */
+#define PERF_X86_EVENT_EXCL 0x40 /* HT exclusivity on counter */
#define PERF_X86_EVENT_RDPMC_ALLOWED 0x40 /* grant rdpmc permission */
@@ -123,6 +124,26 @@ struct intel_shared_regs {
unsigned core_id; /* per-core: core id */
};
+enum intel_excl_state_type {
+ INTEL_EXCL_UNUSED = 0, /* counter is unused */
+ INTEL_EXCL_SHARED = 1, /* counter can be used by both threads */
+ INTEL_EXCL_EXCLUSIVE = 2, /* counter can be used by one thread only */
+};
+
+struct intel_excl_states {
+ enum intel_excl_state_type init_state[X86_PMC_IDX_MAX];
+ enum intel_excl_state_type state[X86_PMC_IDX_MAX];
+};
+
+struct intel_excl_cntrs {
+ raw_spinlock_t lock;
+
+ struct intel_excl_states states[2];
+
+ int refcnt; /* per-core: #HT threads */
+ unsigned core_id; /* per-core: core id */
+};
+
#define MAX_LBR_ENTRIES 16
enum {
@@ -185,6 +206,12 @@ struct cpu_hw_events {
* used on Intel NHM/WSM/SNB
*/
struct intel_shared_regs *shared_regs;
+ /*
+ * manage exclusive counter access between hyperthread
+ */
+ struct event_constraint *constraint_list; /* in enable order */
+ struct intel_excl_cntrs *excl_cntrs;
+ int excl_thread_id; /* 0 or 1 */
/*
* AMD specific bits
@@ -208,6 +235,10 @@ struct cpu_hw_events {
#define EVENT_CONSTRAINT(c, n, m) \
__EVENT_CONSTRAINT(c, n, m, HWEIGHT(n), 0, 0)
+#define INTEL_EXCLEVT_CONSTRAINT(c, n) \
+ __EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT, HWEIGHT(n),\
+ 0, PERF_X86_EVENT_EXCL)
+
/*
* The overlap flag marks event constraints with overlapping counter
* masks. This is the case if the counter mask of such an event is not
@@ -566,6 +597,7 @@ do { \
*/
#define PMU_FL_NO_HT_SHARING 0x1 /* no hyper-threading resource sharing */
#define PMU_FL_HAS_RSP_1 0x2 /* has 2 equivalent offcore_rsp regs */
+#define PMU_FL_EXCL_CNTRS 0x4 /* has exclusive counter requirements */
#define EVENT_VAR(_id) event_attr_##_id
#define EVENT_PTR(_id) &event_attr_##_id.attr.attr
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 2dd34b5..7f54000 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -2224,16 +2224,52 @@ struct intel_shared_regs *allocate_shared_regs(int cpu)
return regs;
}
+static struct intel_excl_cntrs *allocate_excl_cntrs(int cpu)
+{
+ struct intel_excl_cntrs *c;
+ int i;
+
+ c = kzalloc_node(sizeof(struct intel_excl_cntrs),
+ GFP_KERNEL, cpu_to_node(cpu));
+ if (c) {
+ raw_spin_lock_init(&c->lock);
+ for (i = 0; i < X86_PMC_IDX_MAX; i++) {
+ c->states[0].state[i] = INTEL_EXCL_UNUSED;
+ c->states[0].init_state[i] = INTEL_EXCL_UNUSED;
+
+ c->states[1].state[i] = INTEL_EXCL_UNUSED;
+ c->states[1].init_state[i] = INTEL_EXCL_UNUSED;
+ }
+ c->core_id = -1;
+ }
+ return c;
+}
+
static int intel_pmu_cpu_prepare(int cpu)
{
struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
- if (!(x86_pmu.extra_regs || x86_pmu.lbr_sel_map))
- return NOTIFY_OK;
+ if (x86_pmu.extra_regs || x86_pmu.lbr_sel_map) {
+ cpuc->shared_regs = allocate_shared_regs(cpu);
+ if (!cpuc->shared_regs)
+ return NOTIFY_BAD;
+ }
- cpuc->shared_regs = allocate_shared_regs(cpu);
- if (!cpuc->shared_regs)
- return NOTIFY_BAD;
+ if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
+ size_t sz = X86_PMC_IDX_MAX * sizeof(struct event_constraint);
+
+ cpuc->constraint_list = kzalloc(sz, GFP_KERNEL);
+ if (!cpuc->constraint_list)
+ return NOTIFY_BAD;
+
+ cpuc->excl_cntrs = allocate_excl_cntrs(cpu);
+ if (!cpuc->excl_cntrs) {
+ kfree(cpuc->constraint_list);
+ kfree(cpuc->shared_regs);
+ return NOTIFY_BAD;
+ }
+ cpuc->excl_thread_id = 0;
+ }
return NOTIFY_OK;
}
@@ -2274,12 +2310,29 @@ static void intel_pmu_cpu_starting(int cpu)
if (x86_pmu.lbr_sel_map)
cpuc->lbr_sel = &cpuc->shared_regs->regs[EXTRA_REG_LBR];
+
+ if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
+ for_each_cpu(i, topology_thread_cpumask(cpu)) {
+ struct intel_excl_cntrs *c;
+
+ c = per_cpu(cpu_hw_events, i).excl_cntrs;
+ if (c && c->core_id == core_id) {
+ cpuc->kfree_on_online[1] = cpuc->excl_cntrs;
+ cpuc->excl_cntrs = c;
+ cpuc->excl_thread_id = 1;
+ break;
+ }
+ }
+ cpuc->excl_cntrs->core_id = core_id;
+ cpuc->excl_cntrs->refcnt++;
+ }
}
static void intel_pmu_cpu_dying(int cpu)
{
struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
struct intel_shared_regs *pc;
+ struct intel_excl_cntrs *c;
pc = cpuc->shared_regs;
if (pc) {
@@ -2287,6 +2340,14 @@ static void intel_pmu_cpu_dying(int cpu)
kfree(pc);
cpuc->shared_regs = NULL;
}
+ c = cpuc->excl_cntrs;
+ if (c) {
+ if (c->core_id == -1 || --c->refcnt == 0)
+ kfree(c);
+ cpuc->excl_cntrs = NULL;
+ kfree(cpuc->constraint_list);
+ cpuc->constraint_list = NULL;
+ }
fini_debug_store_on_cpu(cpu);
}
next prev parent reply other threads:[~2015-04-02 18:43 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-17 19:06 [PATCH v3 00/13] perf/x86: implement HT counter corruption workaround Stephane Eranian
2014-11-17 19:06 ` [PATCH v3 01/13] perf,x86: rename er_flags to flags Stephane Eranian
2015-04-02 18:41 ` [tip:perf/core] perf/x86: Rename x86_pmu::er_flags to 'flags' tip-bot for Stephane Eranian
2014-11-17 19:06 ` [PATCH v3 02/13] perf/x86: vectorize cpuc->kfree_on_online Stephane Eranian
2015-04-02 18:41 ` [tip:perf/core] perf/x86: Vectorize cpuc->kfree_on_online tip-bot for Stephane Eranian
2014-11-17 19:06 ` [PATCH v3 03/13] perf/x86: add 3 new scheduling callbacks Stephane Eranian
2015-04-02 18:42 ` [tip:perf/core] perf/x86: Add " tip-bot for Maria Dimakopoulou
2014-11-17 19:06 ` [PATCH v3 04/13] perf/x86: add index param to get_event_constraint() callback Stephane Eranian
2015-04-02 18:42 ` [tip:perf/core] perf/x86: Add 'index' " tip-bot for Stephane Eranian
2014-11-17 19:06 ` [PATCH v3 05/13] perf/x86: add cross-HT counter exclusion infrastructure Stephane Eranian
2015-04-02 18:42 ` tip-bot for Maria Dimakopoulou [this message]
2014-11-17 19:06 ` [PATCH v3 06/13] perf/x86: implement cross-HT corruption bug workaround Stephane Eranian
2015-04-02 18:43 ` [tip:perf/core] perf/x86/intel: Implement " tip-bot for Maria Dimakopoulou
2014-11-17 19:06 ` [PATCH v3 07/13] perf/x86: enforce HT bug workaround for SNB/IVB/HSW Stephane Eranian
2015-04-02 18:43 ` [tip:perf/core] perf/x86/intel: Enforce HT bug workaround for SNB /IVB/HSW tip-bot for Maria Dimakopoulou
2014-11-17 19:07 ` [PATCH v3 08/13] perf/x86: enforce HT bug workaround with PEBS for SNB/IVB/HSW Stephane Eranian
2015-04-02 18:43 ` [tip:perf/core] perf/x86/intel: Enforce " tip-bot for Maria Dimakopoulou
2014-11-17 19:07 ` [PATCH v3 09/13] perf/x86: fix intel_get_event_constraints() for dynamic constraints Stephane Eranian
2015-04-02 18:43 ` [tip:perf/core] perf/x86/intel: Fix " tip-bot for Stephane Eranian
2014-11-17 19:07 ` [PATCH v3 10/13] perf/x86: limit to half counters to avoid exclusive mode starvation Stephane Eranian
2015-04-02 18:44 ` [tip:perf/core] perf/x86/intel: Limit to half counters when the HT workaround is enabled, " tip-bot for Stephane Eranian
2014-11-17 19:07 ` [PATCH v3 11/13] watchdog: add watchdog enable/disable all functions Stephane Eranian
2015-04-02 18:44 ` [tip:perf/core] watchdog: Add watchdog enable/ disable " tip-bot for Stephane Eranian
2014-11-17 19:07 ` [PATCH v3 12/13] perf/x86: make HT bug workaround conditioned on HT enabled Stephane Eranian
2015-04-02 18:44 ` [tip:perf/core] perf/x86/intel: Make the HT bug workaround conditional " tip-bot for Stephane Eranian
2014-11-17 19:07 ` [PATCH v3 13/13] perf/x86: add syfs entry to disable HT bug workaround Stephane Eranian
2014-11-17 23:02 ` Borislav Petkov
2014-11-17 23:38 ` Thomas Gleixner
2014-11-17 23:58 ` Borislav Petkov
2014-11-18 0:31 ` Thomas Gleixner
2014-11-18 15:29 ` Stephane Eranian
2014-11-18 15:43 ` Borislav Petkov
2014-11-18 16:37 ` Stephane Eranian
2014-11-18 16:42 ` Borislav Petkov
2014-11-18 15:01 ` Maria Dimakopoulou
2014-11-18 15:12 ` Borislav Petkov
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=tip-6f6539cad926f55d5eb6e79d05bbe99f0d54d56d@git.kernel.org \
--to=tipbot@zytor.com \
--cc=eranian@google.com \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-tip-commits@vger.kernel.org \
--cc=maria.n.dimakopoulou@gmail.com \
--cc=mingo@kernel.org \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome