perf: Adding sysfs group format attribute for pmu device

Adding sysfs group 'format' attribute for pmu device that
contains a syntax description on how to construct raw events.

The event configuration is described in following
struct pefr_event_attr attributes:

  config
  config1
  config2

Each sysfs attribute within the format attribute group,
describes mapping of name and bitfield definition within
one of above attributes.

eg:
  "/sys/...<dev>/format/event" contains "config:0-7"
  "/sys/...<dev>/format/umask" contains "config:8-15"
  "/sys/...<dev>/format/usr"   contains "config:16"

the attribute value syntax is:

  line:      config ':' bits
  config:    'config' | 'config1' | 'config2"
  bits:      bits ',' bit_term | bit_term
  bit_term:  VALUE '-' VALUE | VALUE

Adding format attribute definitions for x86 cpu pmus.

Acked-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/n/tip-vhdk5y2hyype9j63prymty36@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Jiri Olsa 2012-03-15 20:09:14 +01:00 committed by Arnaldo Carvalho de Melo
parent 4a3d2d9bfb
commit 641cc93881
7 changed files with 109 additions and 0 deletions

View file

@ -0,0 +1,14 @@
Where: /sys/bus/event_source/devices/<dev>/format
Date: January 2012
Kernel Version: 3.3
Contact: Jiri Olsa <jolsa@redhat.com>
Description:
Attribute group to describe the magic bits that go into
perf_event_attr::config[012] for a particular pmu.
Each attribute of this group defines the 'hardware' bitmask
we want to export, so that userspace can deal with sane
name/value pairs.
Example: 'config1:1,6-10,44'
Defines contents of attribute that occupies bits 1,6-10,44 of
perf_event_attr::config1.

View file

@ -1314,6 +1314,11 @@ static void __init pmu_check_apic(void)
pr_info("no hardware sampling interrupt available.\n"); pr_info("no hardware sampling interrupt available.\n");
} }
static struct attribute_group x86_pmu_format_group = {
.name = "format",
.attrs = NULL,
};
static int __init init_hw_perf_events(void) static int __init init_hw_perf_events(void)
{ {
struct x86_pmu_quirk *quirk; struct x86_pmu_quirk *quirk;
@ -1388,6 +1393,7 @@ static int __init init_hw_perf_events(void)
} }
x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */ x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
x86_pmu_format_group.attrs = x86_pmu.format_attrs;
pr_info("... version: %d\n", x86_pmu.version); pr_info("... version: %d\n", x86_pmu.version);
pr_info("... bit width: %d\n", x86_pmu.cntval_bits); pr_info("... bit width: %d\n", x86_pmu.cntval_bits);
@ -1668,6 +1674,7 @@ static struct attribute_group x86_pmu_attr_group = {
static const struct attribute_group *x86_pmu_attr_groups[] = { static const struct attribute_group *x86_pmu_attr_groups[] = {
&x86_pmu_attr_group, &x86_pmu_attr_group,
&x86_pmu_format_group,
NULL, NULL,
}; };

View file

@ -339,6 +339,7 @@ struct x86_pmu {
* sysfs attrs * sysfs attrs
*/ */
int attr_rdpmc; int attr_rdpmc;
struct attribute **format_attrs;
/* /*
* CPU Hotplug hooks * CPU Hotplug hooks

View file

@ -404,6 +404,21 @@ static void amd_pmu_cpu_dead(int cpu)
} }
} }
PMU_FORMAT_ATTR(event, "config:0-7,32-35");
PMU_FORMAT_ATTR(umask, "config:8-15" );
PMU_FORMAT_ATTR(edge, "config:18" );
PMU_FORMAT_ATTR(inv, "config:23" );
PMU_FORMAT_ATTR(cmask, "config:24-31" );
static struct attribute *amd_format_attr[] = {
&format_attr_event.attr,
&format_attr_umask.attr,
&format_attr_edge.attr,
&format_attr_inv.attr,
&format_attr_cmask.attr,
NULL,
};
static __initconst const struct x86_pmu amd_pmu = { static __initconst const struct x86_pmu amd_pmu = {
.name = "AMD", .name = "AMD",
.handle_irq = x86_pmu_handle_irq, .handle_irq = x86_pmu_handle_irq,
@ -426,6 +441,8 @@ static __initconst const struct x86_pmu amd_pmu = {
.get_event_constraints = amd_get_event_constraints, .get_event_constraints = amd_get_event_constraints,
.put_event_constraints = amd_put_event_constraints, .put_event_constraints = amd_put_event_constraints,
.format_attrs = amd_format_attr,
.cpu_prepare = amd_pmu_cpu_prepare, .cpu_prepare = amd_pmu_cpu_prepare,
.cpu_starting = amd_pmu_cpu_starting, .cpu_starting = amd_pmu_cpu_starting,
.cpu_dead = amd_pmu_cpu_dead, .cpu_dead = amd_pmu_cpu_dead,
@ -596,6 +613,7 @@ static __initconst const struct x86_pmu amd_pmu_f15h = {
.cpu_dead = amd_pmu_cpu_dead, .cpu_dead = amd_pmu_cpu_dead,
#endif #endif
.cpu_starting = amd_pmu_cpu_starting, .cpu_starting = amd_pmu_cpu_starting,
.format_attrs = amd_format_attr,
}; };
__init int amd_pmu_init(void) __init int amd_pmu_init(void)

View file

@ -1431,6 +1431,24 @@ static void core_pmu_enable_all(int added)
} }
} }
PMU_FORMAT_ATTR(event, "config:0-7" );
PMU_FORMAT_ATTR(umask, "config:8-15" );
PMU_FORMAT_ATTR(edge, "config:18" );
PMU_FORMAT_ATTR(pc, "config:19" );
PMU_FORMAT_ATTR(any, "config:21" ); /* v3 + */
PMU_FORMAT_ATTR(inv, "config:23" );
PMU_FORMAT_ATTR(cmask, "config:24-31" );
static struct attribute *intel_arch_formats_attr[] = {
&format_attr_event.attr,
&format_attr_umask.attr,
&format_attr_edge.attr,
&format_attr_pc.attr,
&format_attr_inv.attr,
&format_attr_cmask.attr,
NULL,
};
static __initconst const struct x86_pmu core_pmu = { static __initconst const struct x86_pmu core_pmu = {
.name = "core", .name = "core",
.handle_irq = x86_pmu_handle_irq, .handle_irq = x86_pmu_handle_irq,
@ -1455,6 +1473,7 @@ static __initconst const struct x86_pmu core_pmu = {
.put_event_constraints = intel_put_event_constraints, .put_event_constraints = intel_put_event_constraints,
.event_constraints = intel_core_event_constraints, .event_constraints = intel_core_event_constraints,
.guest_get_msrs = core_guest_get_msrs, .guest_get_msrs = core_guest_get_msrs,
.format_attrs = intel_arch_formats_attr,
}; };
struct intel_shared_regs *allocate_shared_regs(int cpu) struct intel_shared_regs *allocate_shared_regs(int cpu)
@ -1553,6 +1572,21 @@ static void intel_pmu_flush_branch_stack(void)
intel_pmu_lbr_reset(); intel_pmu_lbr_reset();
} }
PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63");
static struct attribute *intel_arch3_formats_attr[] = {
&format_attr_event.attr,
&format_attr_umask.attr,
&format_attr_edge.attr,
&format_attr_pc.attr,
&format_attr_any.attr,
&format_attr_inv.attr,
&format_attr_cmask.attr,
&format_attr_offcore_rsp.attr, /* XXX do NHM/WSM + SNB breakout */
NULL,
};
static __initconst const struct x86_pmu intel_pmu = { static __initconst const struct x86_pmu intel_pmu = {
.name = "Intel", .name = "Intel",
.handle_irq = intel_pmu_handle_irq, .handle_irq = intel_pmu_handle_irq,
@ -1576,6 +1610,8 @@ static __initconst const struct x86_pmu intel_pmu = {
.get_event_constraints = intel_get_event_constraints, .get_event_constraints = intel_get_event_constraints,
.put_event_constraints = intel_put_event_constraints, .put_event_constraints = intel_put_event_constraints,
.format_attrs = intel_arch3_formats_attr,
.cpu_prepare = intel_pmu_cpu_prepare, .cpu_prepare = intel_pmu_cpu_prepare,
.cpu_starting = intel_pmu_cpu_starting, .cpu_starting = intel_pmu_cpu_starting,
.cpu_dying = intel_pmu_cpu_dying, .cpu_dying = intel_pmu_cpu_dying,

View file

@ -87,6 +87,23 @@ static void p6_pmu_enable_event(struct perf_event *event)
(void)checking_wrmsrl(hwc->config_base, val); (void)checking_wrmsrl(hwc->config_base, val);
} }
PMU_FORMAT_ATTR(event, "config:0-7" );
PMU_FORMAT_ATTR(umask, "config:8-15" );
PMU_FORMAT_ATTR(edge, "config:18" );
PMU_FORMAT_ATTR(pc, "config:19" );
PMU_FORMAT_ATTR(inv, "config:23" );
PMU_FORMAT_ATTR(cmask, "config:24-31" );
static struct attribute *intel_p6_formats_attr[] = {
&format_attr_event.attr,
&format_attr_umask.attr,
&format_attr_edge.attr,
&format_attr_pc.attr,
&format_attr_inv.attr,
&format_attr_cmask.attr,
NULL,
};
static __initconst const struct x86_pmu p6_pmu = { static __initconst const struct x86_pmu p6_pmu = {
.name = "p6", .name = "p6",
.handle_irq = x86_pmu_handle_irq, .handle_irq = x86_pmu_handle_irq,
@ -115,6 +132,8 @@ static __initconst const struct x86_pmu p6_pmu = {
.cntval_mask = (1ULL << 32) - 1, .cntval_mask = (1ULL << 32) - 1,
.get_event_constraints = x86_get_event_constraints, .get_event_constraints = x86_get_event_constraints,
.event_constraints = p6_event_constraints, .event_constraints = p6_event_constraints,
.format_attrs = intel_p6_formats_attr,
}; };
__init int p6_pmu_init(void) __init int p6_pmu_init(void)

View file

@ -550,6 +550,7 @@ struct perf_guest_info_callbacks {
#include <linux/irq_work.h> #include <linux/irq_work.h>
#include <linux/static_key.h> #include <linux/static_key.h>
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/sysfs.h>
#include <asm/local.h> #include <asm/local.h>
#define PERF_MAX_STACK_DEPTH 255 #define PERF_MAX_STACK_DEPTH 255
@ -1291,5 +1292,18 @@ do { \
register_cpu_notifier(&fn##_nb); \ register_cpu_notifier(&fn##_nb); \
} while (0) } while (0)
#define PMU_FORMAT_ATTR(_name, _format) \
static ssize_t \
_name##_show(struct device *dev, \
struct device_attribute *attr, \
char *page) \
{ \
BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \
return sprintf(page, _format "\n"); \
} \
\
static struct device_attribute format_attr_##_name = __ATTR_RO(_name)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _LINUX_PERF_EVENT_H */ #endif /* _LINUX_PERF_EVENT_H */