Simple example of a static event enumeration,.. need to come up with something more dynamic for things like trace-events which can come and go during the life-time of a struct pmu. Signed-off-by: Peter Zijlstra --- arch/x86/kernel/cpu/perf_event.c | 51 ++++++++++++++++++++++++++++++++++++ include/linux/perf_event.h | 1 kernel/perf_event.c | 55 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) Index: linux-2.6/include/linux/perf_event.h =================================================================== --- linux-2.6.orig/include/linux/perf_event.h +++ linux-2.6/include/linux/perf_event.h @@ -578,6 +578,7 @@ struct perf_event; struct pmu { struct list_head entry; + const struct attribute_group **groups; struct device *dev; char *name; int type; Index: linux-2.6/kernel/perf_event.c =================================================================== --- linux-2.6.orig/kernel/perf_event.c +++ linux-2.6/kernel/perf_event.c @@ -4700,7 +4700,61 @@ static int perf_swevent_init(struct perf return 0; } +static struct attribute *swevent_attrs[PERF_COUNT_SW_MAX+1]; + +static ssize_t swevent_attr_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int i; + + for (i = 0; swevent_attrs[i]; i++) { + if ((struct attribute *)attr == swevent_attrs[i]) + break; + } + + return snprintf(buf, PAGE_SIZE-1, "%d\n", i); +} + +#define SWEVENT_ATTR(name) \ + static DEVICE_ATTR(name, S_IRUGO, swevent_attr_show, NULL) + +SWEVENT_ATTR(cpu_clock); +SWEVENT_ATTR(task_clock); +SWEVENT_ATTR(page_faults); +SWEVENT_ATTR(context_switches); +SWEVENT_ATTR(cpu_migrations); +SWEVENT_ATTR(page_faults_min); +SWEVENT_ATTR(page_faults_maj); +SWEVENT_ATTR(alignment_faults); +SWEVENT_ATTR(emulation_faults); + +static struct attribute *swevent_attrs[] = { + &dev_attr_cpu_clock.attr, + &dev_attr_task_clock.attr, + &dev_attr_page_faults.attr, + &dev_attr_context_switches.attr, + &dev_attr_cpu_migrations.attr, + &dev_attr_page_faults_min.attr, + &dev_attr_page_faults_maj.attr, + &dev_attr_alignment_faults.attr, + &dev_attr_emulation_faults.attr, + NULL, +}; + +static struct attribute_group swevent_group = { + .name = "events", + .attrs = swevent_attrs, +}; + +static const struct attribute_group *swevent_groups[] = { + &swevent_group, + NULL +}; + static struct pmu perf_swevent = { + .groups = swevent_groups, + .task_ctx_nr = perf_sw_context, .event_init = perf_swevent_init, @@ -5172,6 +5226,7 @@ static int pmu_dev_alloc(struct pmu *pmu dev_set_drvdata(pmu->dev, pmu); pmu->dev->bus = &pmu_bus; pmu->dev->release = pmu_dev_release; + pmu->dev->groups = pmu->groups; ret = device_add(pmu->dev); if (ret) goto free_dev; Index: linux-2.6/arch/x86/kernel/cpu/perf_event.c =================================================================== --- linux-2.6.orig/arch/x86/kernel/cpu/perf_event.c +++ linux-2.6/arch/x86/kernel/cpu/perf_event.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -1607,7 +1608,57 @@ int x86_pmu_event_init(struct perf_event return err; } +static struct attribute *hwevent_attrs[PERF_COUNT_HW_MAX+1]; + +static ssize_t hwevent_attr_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int i; + + for (i = 0; hwevent_attrs[i]; i++) { + if ((struct attribute *)attr == hwevent_attrs[i]) + break; + } + + return snprintf(buf, PAGE_SIZE-1, "0x%Lx\n", x86_pmu.event_map(i)); +} + +#define HWEVENT_ATTR(name) \ + static DEVICE_ATTR(name, S_IRUGO, hwevent_attr_show, NULL) + +HWEVENT_ATTR(cpu_cycles); +HWEVENT_ATTR(instructions); +HWEVENT_ATTR(cache_references); +HWEVENT_ATTR(cache_misses); +HWEVENT_ATTR(branch_instructions); +HWEVENT_ATTR(branch_misses); +HWEVENT_ATTR(bus_cycles); + +static struct attribute *hwevent_attrs[] = { + &dev_attr_cpu_cycles.attr, + &dev_attr_instructions.attr, + &dev_attr_cache_references.attr, + &dev_attr_cache_misses.attr, + &dev_attr_branch_instructions.attr, + &dev_attr_branch_misses.attr, + &dev_attr_bus_cycles.attr, + NULL, +}; + +static struct attribute_group hwevent_group = { + .name = "events", + .attrs = hwevent_attrs, +}; + +static const struct attribute_group *hwevent_groups[] = { + &hwevent_group, + NULL +}; + static struct pmu pmu = { + .groups = hwevent_groups, + .pmu_enable = x86_pmu_enable, .pmu_disable = x86_pmu_disable, -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/