From: Lin Ming <ming.m.lin@intel.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@elte.hu>,
Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>,
Paul Mundt <lethal@linux-sh.org>,
"eranian@gmail.com" <eranian@gmail.com>,
"Gary.Mohr@Bull.com" <Gary.Mohr@bull.com>,
"arjan@linux.intel.com" <arjan@linux.intel.com>,
"Zhang, Yanmin" <yanmin_zhang@linux.intel.com>,
Paul Mackerras <paulus@samba.org>,
"David S. Miller" <davem@davemloft.net>,
Russell King <rmk+kernel@arm.linux.org.uk>,
Arnaldo Carvalho de Melo <acme@redhat.com>,
Will Deacon <will.deacon@arm.com>,
Maynard Johnson <mpjohn@us.ibm.com>, Carl Love <carll@us.ibm.com>,
"greg@kroah.com" <greg@kroah.com>,
Kay Sievers <kay.sievers@vrfy.org>,
lkml <linux-kernel@vger.kernel.org>
Subject: [RFC][PATCH v2 06/11] perf: core, export pmus via sysfs
Date: Wed, 19 May 2010 01:46:42 +0000 [thread overview]
Message-ID: <1274233602.3036.84.camel@localhost> (raw)
Now only exports cpu hardware events.
For each PMU, there are 2 sysfs dirs: event_source and events.
For example,
/sys/devices/system/cpu/event_source/
/sys/devices/system/cpu/events/
$ tree /sys/devices/system/cpu/event_source/
/sys/devices/system/cpu/event_source/
`-- id
$ tree /sys/devices/system/cpu/events/
/sys/devices/system/cpu/events/
|-- L1-dcache-load-misses
| |-- event_source -> ../../event_source
| `-- id
|-- LLC-load-misses
| |-- event_source -> ../../event_source
| `-- id
|-- branch-misses
| |-- event_source -> ../../event_source
| `-- id
|-- branches
| |-- event_source -> ../../event_source
| `-- id
|-- bus-cycles
| |-- event_source -> ../../event_source
| `-- id
|-- cache-misses
| |-- event_source -> ../../event_source
| `-- id
|-- cache-references
| |-- event_source -> ../../event_source
| `-- id
|-- cycles
| |-- event_source -> ../../event_source
| `-- id
|-- dTLB-load-misses
| |-- event_source -> ../../event_source
| `-- id
|-- dTLB-store-misses
| |-- event_source -> ../../event_source
| `-- id
|-- iTLB-load-misses
| |-- event_source -> ../../event_source
| `-- id
|-- iTLB-load-refs
| |-- event_source -> ../../event_source
| `-- id
`-- instructions
|-- event_source -> ../../event_source
`-- id
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
---
drivers/base/node.c | 3 +-
include/linux/node.h | 2 +
include/linux/perf_event.h | 10 +++
kernel/perf_event.c | 169 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 183 insertions(+), 1 deletions(-)
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 057979a..3b77585 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -19,10 +19,11 @@
static struct sysdev_class_attribute *node_state_attrs[];
-static struct sysdev_class node_class = {
+struct sysdev_class node_class = {
.name = "node",
.attrs = node_state_attrs,
};
+EXPORT_SYMBOL(node_class);
static ssize_t node_read_cpumap(struct sys_device *dev, int type, char *buf)
diff --git a/include/linux/node.h b/include/linux/node.h
index 06292da..43e4422 100644
--- a/include/linux/node.h
+++ b/include/linux/node.h
@@ -50,6 +50,8 @@ extern int unregister_mem_sect_under_nodes(struct memory_block *mem_blk);
extern void register_hugetlbfs_with_node(node_registration_func_t doregister,
node_registration_func_t unregister);
#endif
+
+extern struct sysdev_class node_class;
#else
static inline int register_one_node(int nid)
{
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index ad2aea3..ef519d2 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -552,12 +552,18 @@ struct perf_event;
#define PMU_TYPE_CPU 0
#define PMU_TYPE_NODE 1
+struct perf_event_kobject {
+ struct kobject kobj;
+ u64 id;
+};
+
/**
* struct pmu - generic performance monitoring unit
*/
struct pmu {
int id;
struct list_head entry;
+ struct kobject kobj;
int (*enable) (struct perf_event *event);
void (*disable) (struct perf_event *event);
@@ -577,6 +583,7 @@ struct pmu {
int (*commit_txn) (struct pmu *pmu);
int (*init_event) (struct perf_event *event);
+ int (*register_events) (struct pmu *pmu, struct kobject *events_kobj);
};
/**
@@ -1022,6 +1029,9 @@ extern void perf_event_disable(struct perf_event *event);
extern int perf_event_register_pmu(struct pmu *pmu);
extern void perf_event_unregister_pmu(int id);
+char *perf_hw_event_name(int id);
+char *perf_hw_cache_event_name(u8 type, u8 op, u8 result);
+extern struct kobj_type event_ktype;
#else
static inline void
perf_event_task_sched_in(struct task_struct *task) { }
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 44e35ad..f6df0f8 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -12,6 +12,7 @@
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/cpu.h>
+#include <linux/node.h>
#include <linux/smp.h>
#include <linux/file.h>
#include <linux/poll.h>
@@ -5767,6 +5768,174 @@ static int __init perf_event_sysfs_init(void)
}
device_initcall(perf_event_sysfs_init);
+static char *hw_event_names[] = {
+ "cycles",
+ "instructions",
+ "cache-references",
+ "cache-misses",
+ "branches",
+ "branch-misses",
+ "bus-cycles",
+};
+
+static char *hw_cache[] = {
+ "L1-dcache",
+ "L1-icache",
+ "LLC",
+ "dTLB",
+ "iTLB",
+ "branch",
+};
+
+static char *hw_cache_op[] = {
+ "load",
+ "store",
+ "prefetch",
+};
+
+static char *hw_cache_result[] = {
+ "refs",
+ "misses",
+};
+
+char *perf_hw_event_name(int id)
+{
+ if (id >= ARRAY_SIZE(hw_event_names))
+ return NULL;
+
+ return hw_event_names[id];
+}
+
+char *perf_hw_cache_event_name(u8 cache_type, u8 cache_op, u8 cache_result)
+{
+ static char name[50];
+
+ sprintf(name, "%s-%s-%s", hw_cache[cache_type],
+ hw_cache_op[cache_op],
+ hw_cache_result[cache_result]);
+
+ return name;
+}
+
+static ssize_t event_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ int n;
+ struct perf_event_kobject *event_kobj =
+ container_of(kobj, struct perf_event_kobject, kobj);
+
+ n = sprintf(buf, "0x%llx\n", event_kobj->id);
+
+ return n;
+}
+
+static const struct sysfs_ops event_sysfs_ops = {
+ .show = event_show,
+ .store = NULL,
+};
+
+struct kobj_type event_ktype = {
+ .sysfs_ops = &event_sysfs_ops,
+};
+
+static ssize_t event_source_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ int n;
+ struct pmu *pmu = container_of(kobj, struct pmu, kobj);
+
+ n = sprintf(buf, "%d\n", pmu->id);
+
+ return n;
+}
+
+static const struct sysfs_ops event_source_sysfs_ops = {
+ .show = event_source_show,
+ .store = NULL,
+};
+
+static struct kobj_type event_source_ktype = {
+ .sysfs_ops = &event_source_sysfs_ops,
+};
+
+static struct attribute event_source_id_attr = {
+ .name = "id",
+ .mode = 0444,
+};
+
+static int __init perf_pmu_sysfs_init(void)
+{
+ struct pmu *pmu;
+ struct kobject *parent_kobj, *events_kobj;
+ int err = 0;
+
+ rcu_read_lock();
+
+ list_for_each_entry_rcu(pmu, &pmus, entry) {
+ switch (pmu->id) {
+ case PMU_TYPE_CPU:
+ parent_kobj = &cpu_sysdev_class.kset.kobj;
+ break;
+#ifdef CONFIG_NUMA
+ case PMU_TYPE_NODE:
+ parent_kobj = &node_class.kset.kobj;
+ break;
+#endif
+
+ /* TBD: add other pmu types later */
+ default:
+ parent_kobj = NULL;
+ break;
+ }
+
+ if (!parent_kobj)
+ continue;
+
+ /*
+ * Create event_source sysfs dir, for example
+ * /sys/devices/system/cpu/event_source
+ */
+ err = kobject_init_and_add(&pmu->kobj,
+ &event_source_ktype, parent_kobj, "event_source");
+ if (err)
+ break;
+
+ /*
+ * Create event_source/id attribute, for example
+ * /sys/devices/system/cpu/event_source/id
+ */
+ err = sysfs_create_file(&pmu->kobj, &event_source_id_attr);
+ if (err)
+ break;
+
+ /*
+ * Create events sysfs dir, for example
+ * /sys/devices/system/cpu/events
+ */
+ events_kobj = kobject_create_and_add("events", parent_kobj);
+ if (!events_kobj) {
+ err = -ENOMEM;
+ break;
+ }
+
+ /*
+ * Register all events under events dir, for example
+ * /sys/devices/system/cpu/events/cycles
+ * /sys/devices/system/cpu/events/instructions
+ */
+ if (pmu->register_events) {
+ err = pmu->register_events(pmu, events_kobj);
+ if (err)
+ break;
+ }
+ }
+
+ rcu_read_unlock();
+
+ return err;
+}
+device_initcall(perf_pmu_sysfs_init);
+
int perf_event_register_pmu(struct pmu *pmu)
{
struct pmu *tmp;
next reply other threads:[~2010-05-18 17:46 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-05-19 1:46 Lin Ming [this message]
2010-05-18 20:05 ` [RFC][PATCH v2 06/11] perf: core, export pmus via sysfs Greg KH
2010-05-19 2:34 ` Lin Ming
2010-05-19 2:48 ` Greg KH
2010-05-19 3:40 ` Lin Ming
2010-05-19 5:00 ` Greg KH
2010-05-19 6:32 ` Lin Ming
2010-05-19 7:14 ` Peter Zijlstra
2010-05-20 18:42 ` Greg KH
2010-05-20 19:52 ` Peter Zijlstra
2010-05-20 20:19 ` Greg KH
2010-05-20 20:14 ` Ingo Molnar
2010-05-20 23:12 ` Greg KH
2010-05-21 8:03 ` Peter Zijlstra
2010-05-21 9:40 ` [rfc] Describe events in a structured way " Ingo Molnar
[not found] ` <AANLkTinJeYJtCg2aRWhHTcf5E2-dN2-oAfEJ8tAtFjb9@mail.gmail.com>
2010-06-01 2:34 ` Lin Ming
2010-06-08 18:43 ` Ingo Molnar
[not found] ` <AANLkTimf1Z0N9cv2Pu2qTTUscn4utC37zOPelCbqQoPv@mail.gmail.com>
2010-06-21 8:55 ` Lin Ming
[not found] ` <1277112858.3618.16.camel@jlt3.sipsolutions.net>
[not found] ` <1277187920.4467.3.camel@minggr.sh.intel.com>
[not found] ` <1277189971.3637.5.camel@jlt3.sipsolutions.net>
2010-06-22 7:22 ` Lin Ming
2010-06-22 7:33 ` Johannes Berg
2010-06-22 7:39 ` Johannes Berg
2010-06-22 8:04 ` Lin Ming
2010-06-22 8:16 ` Johannes Berg
2010-06-22 7:47 ` Lin Ming
2010-06-22 7:52 ` Johannes Berg
2010-06-24 9:36 ` Ingo Molnar
2010-06-24 16:14 ` Johannes Berg
2010-06-24 17:33 ` Ingo Molnar
2010-06-29 6:15 ` Lin Ming
2010-06-29 8:55 ` Ingo Molnar
2010-06-29 9:20 ` Lin Ming
2010-06-29 10:26 ` Ingo Molnar
2010-07-02 8:06 ` Lin Ming
2010-07-03 12:54 ` Ingo Molnar
2010-07-17 0:20 ` Corey Ashford
2010-07-20 5:48 ` Lin Ming
2010-07-20 15:19 ` Robert Richter
2010-07-20 17:50 ` Corey Ashford
2010-07-20 18:30 ` Robert Richter
2010-07-20 21:18 ` Corey Ashford
2010-07-20 17:43 ` Corey Ashford
2010-05-19 7:06 ` [RFC][PATCH v2 06/11] perf: core, export pmus " Borislav Petkov
2010-05-19 7:17 ` Peter Zijlstra
2010-05-19 7:23 ` Ingo Molnar
2010-05-18 20:07 ` Greg KH
2010-05-19 2:37 ` Lin Ming
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=1274233602.3036.84.camel@localhost \
--to=ming.m.lin@intel.com \
--cc=Gary.Mohr@bull.com \
--cc=acme@redhat.com \
--cc=arjan@linux.intel.com \
--cc=carll@us.ibm.com \
--cc=cjashfor@linux.vnet.ibm.com \
--cc=davem@davemloft.net \
--cc=eranian@gmail.com \
--cc=fweisbec@gmail.com \
--cc=greg@kroah.com \
--cc=kay.sievers@vrfy.org \
--cc=lethal@linux-sh.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=mpjohn@us.ibm.com \
--cc=paulus@samba.org \
--cc=peterz@infradead.org \
--cc=rmk+kernel@arm.linux.org.uk \
--cc=will.deacon@arm.com \
--cc=yanmin_zhang@linux.intel.com \
/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.