mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "tip-bot for Yan, Zheng" <zheng.z.yan@intel.com>
To: linux-tip-commits@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, hpa@zytor.com, mingo@kernel.org,
	a.p.zijlstra@chello.nl, zheng.z.yan@intel.com,
	tglx@linutronix.de
Subject: [tip:perf/core] perf: Add generic PCI uncore PMU device support
Date: Wed, 20 Jun 2012 03:56:06 -0700	[thread overview]
Message-ID: <tip-14371cce03c2fc393997e17f979e76674b7f392a@git.kernel.org> (raw)
In-Reply-To: <1339741902-8449-8-git-send-email-zheng.z.yan@intel.com>

Commit-ID:  14371cce03c2fc393997e17f979e76674b7f392a
Gitweb:     http://git.kernel.org/tip/14371cce03c2fc393997e17f979e76674b7f392a
Author:     Yan, Zheng <zheng.z.yan@intel.com>
AuthorDate: Fri, 15 Jun 2012 14:31:36 +0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 18 Jun 2012 12:13:23 +0200

perf: Add generic PCI uncore PMU device support

This patch adds generic support for uncore PMUs presented as
PCI devices. (These come in addition to the CPU/MSR based
uncores.)

Signed-off-by: Zheng Yan <zheng.z.yan@intel.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1339741902-8449-8-git-send-email-zheng.z.yan@intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/kernel/cpu/perf_event_intel_uncore.c |  175 ++++++++++++++++++++++++-
 arch/x86/kernel/cpu/perf_event_intel_uncore.h |   66 +++++++++
 2 files changed, 236 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
index 3ed941a..e20c65a 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
@@ -2,6 +2,11 @@
 
 static struct intel_uncore_type *empty_uncore[] = { NULL, };
 static struct intel_uncore_type **msr_uncores = empty_uncore;
+static struct intel_uncore_type **pci_uncores = empty_uncore;
+/* pci bus to socket mapping */
+static int pcibus_to_physid[256] = { [0 ... 255] = -1, };
+
+static DEFINE_RAW_SPINLOCK(uncore_box_lock);
 
 /* mask of cpus that collect uncore events */
 static cpumask_t uncore_cpu_mask;
@@ -205,13 +210,13 @@ static void uncore_assign_hw_event(struct intel_uncore_box *box,
 	hwc->last_tag = ++box->tags[idx];
 
 	if (hwc->idx == UNCORE_PMC_IDX_FIXED) {
-		hwc->event_base = uncore_msr_fixed_ctr(box);
-		hwc->config_base = uncore_msr_fixed_ctl(box);
+		hwc->event_base = uncore_fixed_ctr(box);
+		hwc->config_base = uncore_fixed_ctl(box);
 		return;
 	}
 
-	hwc->config_base = uncore_msr_event_ctl(box, hwc->idx);
-	hwc->event_base =  uncore_msr_perf_ctr(box, hwc->idx);
+	hwc->config_base = uncore_event_ctl(box, hwc->idx);
+	hwc->event_base  = uncore_perf_ctr(box, hwc->idx);
 }
 
 static void uncore_perf_event_update(struct intel_uncore_box *box,
@@ -305,6 +310,22 @@ struct intel_uncore_box *uncore_alloc_box(int cpu)
 static struct intel_uncore_box *
 uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
 {
+	static struct intel_uncore_box *box;
+
+	box = *per_cpu_ptr(pmu->box, cpu);
+	if (box)
+		return box;
+
+	raw_spin_lock(&uncore_box_lock);
+	list_for_each_entry(box, &pmu->box_list, list) {
+		if (box->phys_id == topology_physical_package_id(cpu)) {
+			atomic_inc(&box->refcnt);
+			*per_cpu_ptr(pmu->box, cpu) = box;
+			break;
+		}
+	}
+	raw_spin_unlock(&uncore_box_lock);
+
 	return *per_cpu_ptr(pmu->box, cpu);
 }
 
@@ -706,6 +727,13 @@ static void __init uncore_type_exit(struct intel_uncore_type *type)
 	type->attr_groups[1] = NULL;
 }
 
+static void uncore_types_exit(struct intel_uncore_type **types)
+{
+	int i;
+	for (i = 0; types[i]; i++)
+		uncore_type_exit(types[i]);
+}
+
 static int __init uncore_type_init(struct intel_uncore_type *type)
 {
 	struct intel_uncore_pmu *pmus;
@@ -725,6 +753,7 @@ static int __init uncore_type_init(struct intel_uncore_type *type)
 		pmus[i].func_id = -1;
 		pmus[i].pmu_idx = i;
 		pmus[i].type = type;
+		INIT_LIST_HEAD(&pmus[i].box_list);
 		pmus[i].box = alloc_percpu(struct intel_uncore_box *);
 		if (!pmus[i].box)
 			goto fail;
@@ -773,6 +802,127 @@ fail:
 	return ret;
 }
 
+static struct pci_driver *uncore_pci_driver;
+static bool pcidrv_registered;
+
+/*
+ * add a pci uncore device
+ */
+static int __devinit uncore_pci_add(struct intel_uncore_type *type,
+				    struct pci_dev *pdev)
+{
+	struct intel_uncore_pmu *pmu;
+	struct intel_uncore_box *box;
+	int i, phys_id;
+
+	phys_id = pcibus_to_physid[pdev->bus->number];
+	if (phys_id < 0)
+		return -ENODEV;
+
+	box = uncore_alloc_box(0);
+	if (!box)
+		return -ENOMEM;
+
+	/*
+	 * for performance monitoring unit with multiple boxes,
+	 * each box has a different function id.
+	 */
+	for (i = 0; i < type->num_boxes; i++) {
+		pmu = &type->pmus[i];
+		if (pmu->func_id == pdev->devfn)
+			break;
+		if (pmu->func_id < 0) {
+			pmu->func_id = pdev->devfn;
+			break;
+		}
+		pmu = NULL;
+	}
+
+	if (!pmu) {
+		kfree(box);
+		return -EINVAL;
+	}
+
+	box->phys_id = phys_id;
+	box->pci_dev = pdev;
+	box->pmu = pmu;
+	uncore_box_init(box);
+	pci_set_drvdata(pdev, box);
+
+	raw_spin_lock(&uncore_box_lock);
+	list_add_tail(&box->list, &pmu->box_list);
+	raw_spin_unlock(&uncore_box_lock);
+
+	return 0;
+}
+
+static void __devexit uncore_pci_remove(struct pci_dev *pdev)
+{
+	struct intel_uncore_box *box = pci_get_drvdata(pdev);
+	struct intel_uncore_pmu *pmu = box->pmu;
+	int cpu, phys_id = pcibus_to_physid[pdev->bus->number];
+
+	if (WARN_ON_ONCE(phys_id != box->phys_id))
+		return;
+
+	raw_spin_lock(&uncore_box_lock);
+	list_del(&box->list);
+	raw_spin_unlock(&uncore_box_lock);
+
+	for_each_possible_cpu(cpu) {
+		if (*per_cpu_ptr(pmu->box, cpu) == box) {
+			*per_cpu_ptr(pmu->box, cpu) = NULL;
+			atomic_dec(&box->refcnt);
+		}
+	}
+
+	WARN_ON_ONCE(atomic_read(&box->refcnt) != 1);
+	kfree(box);
+}
+
+static int __devinit uncore_pci_probe(struct pci_dev *pdev,
+				const struct pci_device_id *id)
+{
+	struct intel_uncore_type *type;
+
+	type = (struct intel_uncore_type *)id->driver_data;
+	return uncore_pci_add(type, pdev);
+}
+
+static int __init uncore_pci_init(void)
+{
+	int ret;
+
+	switch (boot_cpu_data.x86_model) {
+	default:
+		return 0;
+	}
+
+	ret = uncore_types_init(pci_uncores);
+	if (ret)
+		return ret;
+
+	uncore_pci_driver->probe = uncore_pci_probe;
+	uncore_pci_driver->remove = uncore_pci_remove;
+
+	ret = pci_register_driver(uncore_pci_driver);
+	if (ret == 0)
+		pcidrv_registered = true;
+	else
+		uncore_types_exit(pci_uncores);
+
+	return ret;
+}
+
+static void __init uncore_pci_exit(void)
+{
+	if (pcidrv_registered) {
+		pcidrv_registered = false;
+		pci_unregister_driver(uncore_pci_driver);
+		uncore_types_exit(pci_uncores);
+	}
+}
+
 static void __cpuinit uncore_cpu_dying(int cpu)
 {
 	struct intel_uncore_type *type;
@@ -921,6 +1071,7 @@ static void __cpuinit uncore_event_exit_cpu(int cpu)
 		cpumask_set_cpu(target, &uncore_cpu_mask);
 
 	uncore_change_context(msr_uncores, cpu, target);
+	uncore_change_context(pci_uncores, cpu, target);
 }
 
 static void __cpuinit uncore_event_init_cpu(int cpu)
@@ -936,6 +1087,7 @@ static void __cpuinit uncore_event_init_cpu(int cpu)
 	cpumask_set_cpu(cpu, &uncore_cpu_mask);
 
 	uncore_change_context(msr_uncores, -1, cpu);
+	uncore_change_context(pci_uncores, -1, cpu);
 }
 
 static int __cpuinit uncore_cpu_notifier(struct notifier_block *self,
@@ -1051,6 +1203,14 @@ static int __init uncore_pmus_register(void)
 		}
 	}
 
+	for (i = 0; pci_uncores[i]; i++) {
+		type = pci_uncores[i];
+		for (j = 0; j < type->num_boxes; j++) {
+			pmu = &type->pmus[j];
+			uncore_pmu_register(pmu);
+		}
+	}
+
 	return 0;
 }
 
@@ -1061,9 +1221,14 @@ static int __init intel_uncore_init(void)
 	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
 		return -ENODEV;
 
-	ret = uncore_cpu_init();
+	ret = uncore_pci_init();
 	if (ret)
 		goto fail;
+	ret = uncore_cpu_init();
+	if (ret) {
+		uncore_pci_exit();
+		goto fail;
+	}
 
 	uncore_pmus_register();
 	return 0;
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
index eeb5ca5..aa01df8 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
@@ -1,5 +1,6 @@
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/pci.h>
 #include <linux/perf_event.h>
 #include "perf_event.h"
 
@@ -110,6 +111,7 @@ struct intel_uncore_pmu {
 	int func_id;
 	struct intel_uncore_type *type;
 	struct intel_uncore_box ** __percpu box;
+	struct list_head box_list;
 };
 
 struct intel_uncore_box {
@@ -123,6 +125,7 @@ struct intel_uncore_box {
 	struct perf_event *event_list[UNCORE_PMC_IDX_MAX];
 	unsigned long active_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)];
 	u64 tags[UNCORE_PMC_IDX_MAX];
+	struct pci_dev *pci_dev;
 	struct intel_uncore_pmu *pmu;
 	struct hrtimer hrtimer;
 	struct list_head list;
@@ -161,6 +164,33 @@ static ssize_t uncore_event_show(struct kobject *kobj,
 	return sprintf(buf, "%s", event->config);
 }
 
+static inline unsigned uncore_pci_box_ctl(struct intel_uncore_box *box)
+{
+	return box->pmu->type->box_ctl;
+}
+
+static inline unsigned uncore_pci_fixed_ctl(struct intel_uncore_box *box)
+{
+	return box->pmu->type->fixed_ctl;
+}
+
+static inline unsigned uncore_pci_fixed_ctr(struct intel_uncore_box *box)
+{
+	return box->pmu->type->fixed_ctr;
+}
+
+static inline
+unsigned uncore_pci_event_ctl(struct intel_uncore_box *box, int idx)
+{
+	return idx * 4 + box->pmu->type->event_ctl;
+}
+
+static inline
+unsigned uncore_pci_perf_ctr(struct intel_uncore_box *box, int idx)
+{
+	return idx * 8 + box->pmu->type->perf_ctr;
+}
+
 static inline
 unsigned uncore_msr_box_ctl(struct intel_uncore_box *box)
 {
@@ -200,6 +230,42 @@ unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx)
 		box->pmu->type->msr_offset * box->pmu->pmu_idx;
 }
 
+static inline
+unsigned uncore_fixed_ctl(struct intel_uncore_box *box)
+{
+	if (box->pci_dev)
+		return uncore_pci_fixed_ctl(box);
+	else
+		return uncore_msr_fixed_ctl(box);
+}
+
+static inline
+unsigned uncore_fixed_ctr(struct intel_uncore_box *box)
+{
+	if (box->pci_dev)
+		return uncore_pci_fixed_ctr(box);
+	else
+		return uncore_msr_fixed_ctr(box);
+}
+
+static inline
+unsigned uncore_event_ctl(struct intel_uncore_box *box, int idx)
+{
+	if (box->pci_dev)
+		return uncore_pci_event_ctl(box, idx);
+	else
+		return uncore_msr_event_ctl(box, idx);
+}
+
+static inline
+unsigned uncore_perf_ctr(struct intel_uncore_box *box, int idx)
+{
+	if (box->pci_dev)
+		return uncore_pci_perf_ctr(box, idx);
+	else
+		return uncore_msr_perf_ctr(box, idx);
+}
+
 static inline int uncore_perf_ctr_bits(struct intel_uncore_box *box)
 {
 	return box->pmu->type->perf_ctr_bits;

  parent reply	other threads:[~2012-06-20 10:56 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-06-15  6:31 [PATCH V6 0/13] perf: Intel uncore pmu counting support Yan, Zheng
2012-06-15  6:31 ` [PATCH V6 01/13] perf: Export perf_assign_events Yan, Zheng
2012-06-20 10:49   ` [tip:perf/core] perf: Export perf_assign_events() tip-bot for Yan, Zheng
2012-06-15  6:31 ` [PATCH V6 02/13] perf: Avoid race between cpu hotplug and installing event Yan, Zheng
2012-06-20 10:50   ` [tip:perf/core] " tip-bot for Yan, Zheng
2012-06-15  6:31 ` [PATCH V6 03/13] perf: Allow pmu to choose cpu on which to install event Yan, Zheng
2012-06-20 10:51   ` [tip:perf/core] perf: Allow the PMU driver to choose the CPU on which to install events tip-bot for Yan, Zheng
2012-06-15  6:31 ` [PATCH V6 04/13] perf: Introduce perf_pmu_migrate_context Yan, Zheng
2012-06-20 10:52   ` [tip:perf/core] perf: Introduce perf_pmu_migrate_context() tip-bot for Yan, Zheng
2012-06-15  6:31 ` [PATCH V6 05/13] perf: Generic intel uncore support Yan, Zheng
2012-06-20 10:54   ` [tip:perf/core] perf/x86: Add generic Intel uncore PMU support tip-bot for Yan, Zheng
2012-06-21 22:43     ` Andrew Morton
2012-06-21 22:46       ` Andrew Morton
2012-06-21 22:47       ` H. Peter Anvin
2012-06-21 22:51         ` Andrew Morton
2012-06-21 23:10           ` H. Peter Anvin
2012-06-21 23:15             ` Andrew Morton
2012-06-21 23:18               ` Andrew Morton
2012-06-21 23:22                 ` H. Peter Anvin
2012-06-21 23:29                   ` Andrew Morton
2012-06-22  8:05       ` Peter Zijlstra
2012-07-24  3:27   ` [PATCH V6 05/13] perf: Generic intel uncore support Stephane Eranian
2012-07-24  6:00     ` Yan, Zheng
2012-07-24  6:21       ` Stephane Eranian
2012-06-15  6:31 ` [PATCH V6 06/13] perf: Add Nehalem and Sandy Bridge " Yan, Zheng
2012-06-15 15:28   ` Peter Zijlstra
2012-06-15 16:31     ` Peter Zijlstra
2012-06-15 18:43     ` Andi Kleen
2012-06-15 17:18   ` Peter Zijlstra
2012-06-15 18:46     ` Stephane Eranian
2012-06-16 12:46       ` Peter Zijlstra
2012-06-16 12:52         ` Peter Zijlstra
2012-06-18  9:23         ` Stephane Eranian
2012-06-19  1:39           ` Yan, Zheng
2012-06-15 17:29   ` Peter Zijlstra
2012-06-15 18:47     ` Stephane Eranian
2012-06-16 12:46       ` Peter Zijlstra
2012-06-20 10:55   ` [tip:perf/core] perf/x86: Add Intel Nehalem and Sandy Bridge uncore PMU support tip-bot for Yan, Zheng
2012-06-15  6:31 ` [PATCH V6 07/13] perf: Generic pci uncore device support Yan, Zheng
2012-06-15 16:02   ` Peter Zijlstra
2012-06-18  3:06     ` Yan, Zheng
2012-06-18  7:43       ` Peter Zijlstra
2012-06-20 10:56   ` tip-bot for Yan, Zheng [this message]
2012-06-20 16:39     ` [PATCH] perf, x86: Fix section mismatch in uncore_pci_init() Robert Richter
2012-06-25 11:40       ` [tip:perf/core] perf/x86: Fix section mismatch in uncore_pci_init( ) tip-bot for Robert Richter
2012-08-13 17:10   ` [tip:perf/urgent] perf, x86: Fix uncore_types_exit section mismatch tip-bot for Borislav Petkov
2012-06-15  6:31 ` [PATCH V6 08/13] perf: Add Sandy Bridge-EP uncore support Yan, Zheng
2012-06-15 17:10   ` Peter Zijlstra
2012-06-18  1:47     ` Yan, Zheng
2012-06-18  7:42       ` Peter Zijlstra
2012-06-18 15:28   ` Stephane Eranian
2012-06-19  0:59     ` Yan, Zheng
2012-06-19  7:18       ` Stephane Eranian
2012-06-19  8:17         ` Yan, Zheng
2012-06-20 10:56   ` [tip:perf/core] perf/x86: Add Intel Nehalem and " tip-bot for Yan, Zheng
2012-07-22 19:37   ` [PATCH V6 08/13] perf: Add " Stephane Eranian
2012-06-15  6:31 ` [PATCH V6 09/13] perf, tool: Use data struct for arg passing in event parse function Yan, Zheng
2012-06-20 10:57   ` [tip:perf/core] perf/tool: " tip-bot for Jiri Olsa
2012-06-15  6:31 ` [PATCH V6 10/13] perf, tool: Make the event parser reentrantable Yan, Zheng
2012-06-20 10:58   ` [tip:perf/core] perf/tool: Make the event parser re-entrant tip-bot for Zheng Yan
2012-06-15  6:31 ` [PATCH V6 11/13] perf, tool: Add support to reuse event grammar to parse out terms Yan, Zheng
2012-06-20 10:59   ` [tip:perf/core] perf/tool: " tip-bot for Jiri Olsa
2012-06-15  6:31 ` [PATCH V6 12/13] perf, tool: Add pmu event alias support Yan, Zheng
2012-06-20 11:00   ` [tip:perf/core] perf/tool: Add PMU " tip-bot for Zheng Yan
2012-06-15  6:31 ` [PATCH V6 13/13] perf, tool: Add automated test for pure terms parsing Yan, Zheng
2012-06-20 11:01   ` [tip:perf/core] perf/tool: " tip-bot for Jiri Olsa
2012-06-20 16:01 ` [PATCH V6 0/13] perf: Intel uncore pmu counting support Peter Zijlstra
2012-06-21  2:34   ` Yan, Zheng
2012-06-21  8:10     ` Stephane Eranian
2012-06-21  8:43       ` Yan, Zheng
2012-06-21  9:13         ` Stephane Eranian
2012-06-21 11:40           ` Peter Zijlstra
2012-06-21 11:48             ` Stephane Eranian
2012-06-21 13:08               ` Yan, Zheng

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-14371cce03c2fc393997e17f979e76674b7f392a@git.kernel.org \
    --to=zheng.z.yan@intel.com \
    --cc=a.p.zijlstra@chello.nl \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-tip-commits@vger.kernel.org \
    --cc=mingo@kernel.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