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:
parent
4a3d2d9bfb
commit
641cc93881
7 changed files with 109 additions and 0 deletions
|
@ -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.
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in a new issue