diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-31 16:34:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-31 16:34:04 -0400 |
commit | f187e9fd68577cdd5f914659b6f7f11124e40485 (patch) | |
tree | ad0e7422359724f7c7ffaaaa80dd3a7281f02a83 /arch | |
parent | adb3b1f3fc1c6edb501808ebf80a81e81c52eb73 (diff) | |
parent | 8ebfdf2babcda5a3b06cc67523bca1f9aed46009 (diff) |
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates and fixes from Ingo Molnar:
"It's mostly fixes, but there's also two late items:
- preliminary GTK GUI support for perf report
- PMU raw event format descriptors in sysfs, to be parsed by tooling
The raw event format in sysfs is a new ABI. For example for the 'CPU'
PMU we have:
aldebaran:~> ll /sys/bus/event_source/devices/cpu/format/*
-r--r--r--. 1 root root 4096 Mar 31 10:29 /sys/bus/event_source/devices/cpu/format/any
-r--r--r--. 1 root root 4096 Mar 31 10:29 /sys/bus/event_source/devices/cpu/format/cmask
-r--r--r--. 1 root root 4096 Mar 31 10:29 /sys/bus/event_source/devices/cpu/format/edge
-r--r--r--. 1 root root 4096 Mar 31 10:29 /sys/bus/event_source/devices/cpu/format/event
-r--r--r--. 1 root root 4096 Mar 31 10:29 /sys/bus/event_source/devices/cpu/format/inv
-r--r--r--. 1 root root 4096 Mar 31 10:29 /sys/bus/event_source/devices/cpu/format/offcore_rsp
-r--r--r--. 1 root root 4096 Mar 31 10:29 /sys/bus/event_source/devices/cpu/format/pc
-r--r--r--. 1 root root 4096 Mar 31 10:29 /sys/bus/event_source/devices/cpu/format/umask
those lists of fields contain a specific format:
aldebaran:~> cat /sys/bus/event_source/devices/cpu/format/offcore_rsp
config1:0-63
So, those who wish to specify raw events can now use the following
event format:
-e cpu/cmask=1,event=2,umask=3
Most people will not want to specify any events (let alone raw
events), they'll just use whatever default event the tools use.
But for more obscure PMU events that have no cross-architecture
generic events the above syntax is more usable and a bit more
structured than specifying hex numbers."
* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (41 commits)
perf tools: Remove auto-generated bison/flex files
perf annotate: Fix off by one symbol hist size allocation and hit accounting
perf tools: Add missing ref-cycles event back to event parser
perf annotate: addr2line wants addresses in same format as objdump
perf probe: Finder fails to resolve function name to address
tracing: Fix ent_size in trace output
perf symbols: Handle NULL dso in dso__name_len
perf symbols: Do not include libgen.h
perf tools: Fix bug in raw sample parsing
perf tools: Fix display of first level of callchains
perf tools: Switch module.h into export.h
perf: Move mmap page data_head offset assertion out of header
perf: Fix mmap_page capabilities and docs
perf diff: Fix to work with new hists design
perf tools: Fix modifier to be applied on correct events
perf tools: Fix various casting issues for 32 bits
perf tools: Simplify event_read_id exit path
tracing: Fix ftrace stack trace entries
tracing: Move the tracing_on/off() declarations into CONFIG_TRACING
perf report: Add a simple GTK2-based 'perf report' browser
...
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 17 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_amd.c | 18 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel.c | 36 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_p6.c | 19 |
5 files changed, 90 insertions, 1 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 40883ffe2da9..bb8e03407e18 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -1313,6 +1313,11 @@ static void __init pmu_check_apic(void) | |||
1313 | pr_info("no hardware sampling interrupt available.\n"); | 1313 | pr_info("no hardware sampling interrupt available.\n"); |
1314 | } | 1314 | } |
1315 | 1315 | ||
1316 | static struct attribute_group x86_pmu_format_group = { | ||
1317 | .name = "format", | ||
1318 | .attrs = NULL, | ||
1319 | }; | ||
1320 | |||
1316 | static int __init init_hw_perf_events(void) | 1321 | static int __init init_hw_perf_events(void) |
1317 | { | 1322 | { |
1318 | struct x86_pmu_quirk *quirk; | 1323 | struct x86_pmu_quirk *quirk; |
@@ -1387,6 +1392,7 @@ static int __init init_hw_perf_events(void) | |||
1387 | } | 1392 | } |
1388 | 1393 | ||
1389 | x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */ | 1394 | x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */ |
1395 | x86_pmu_format_group.attrs = x86_pmu.format_attrs; | ||
1390 | 1396 | ||
1391 | pr_info("... version: %d\n", x86_pmu.version); | 1397 | pr_info("... version: %d\n", x86_pmu.version); |
1392 | pr_info("... bit width: %d\n", x86_pmu.cntval_bits); | 1398 | pr_info("... bit width: %d\n", x86_pmu.cntval_bits); |
@@ -1615,6 +1621,9 @@ static int x86_pmu_event_idx(struct perf_event *event) | |||
1615 | { | 1621 | { |
1616 | int idx = event->hw.idx; | 1622 | int idx = event->hw.idx; |
1617 | 1623 | ||
1624 | if (!x86_pmu.attr_rdpmc) | ||
1625 | return 0; | ||
1626 | |||
1618 | if (x86_pmu.num_counters_fixed && idx >= X86_PMC_IDX_FIXED) { | 1627 | if (x86_pmu.num_counters_fixed && idx >= X86_PMC_IDX_FIXED) { |
1619 | idx -= X86_PMC_IDX_FIXED; | 1628 | idx -= X86_PMC_IDX_FIXED; |
1620 | idx |= 1 << 30; | 1629 | idx |= 1 << 30; |
@@ -1667,6 +1676,7 @@ static struct attribute_group x86_pmu_attr_group = { | |||
1667 | 1676 | ||
1668 | static const struct attribute_group *x86_pmu_attr_groups[] = { | 1677 | static const struct attribute_group *x86_pmu_attr_groups[] = { |
1669 | &x86_pmu_attr_group, | 1678 | &x86_pmu_attr_group, |
1679 | &x86_pmu_format_group, | ||
1670 | NULL, | 1680 | NULL, |
1671 | }; | 1681 | }; |
1672 | 1682 | ||
@@ -1698,14 +1708,19 @@ static struct pmu pmu = { | |||
1698 | .flush_branch_stack = x86_pmu_flush_branch_stack, | 1708 | .flush_branch_stack = x86_pmu_flush_branch_stack, |
1699 | }; | 1709 | }; |
1700 | 1710 | ||
1701 | void perf_update_user_clock(struct perf_event_mmap_page *userpg, u64 now) | 1711 | void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now) |
1702 | { | 1712 | { |
1713 | userpg->cap_usr_time = 0; | ||
1714 | userpg->cap_usr_rdpmc = x86_pmu.attr_rdpmc; | ||
1715 | userpg->pmc_width = x86_pmu.cntval_bits; | ||
1716 | |||
1703 | if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) | 1717 | if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) |
1704 | return; | 1718 | return; |
1705 | 1719 | ||
1706 | if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) | 1720 | if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) |
1707 | return; | 1721 | return; |
1708 | 1722 | ||
1723 | userpg->cap_usr_time = 1; | ||
1709 | userpg->time_mult = this_cpu_read(cyc2ns); | 1724 | userpg->time_mult = this_cpu_read(cyc2ns); |
1710 | userpg->time_shift = CYC2NS_SCALE_FACTOR; | 1725 | userpg->time_shift = CYC2NS_SCALE_FACTOR; |
1711 | userpg->time_offset = this_cpu_read(cyc2ns_offset) - now; | 1726 | userpg->time_offset = this_cpu_read(cyc2ns_offset) - now; |
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 8484e77c211e..6638aaf54493 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h | |||
@@ -339,6 +339,7 @@ struct x86_pmu { | |||
339 | * sysfs attrs | 339 | * sysfs attrs |
340 | */ | 340 | */ |
341 | int attr_rdpmc; | 341 | int attr_rdpmc; |
342 | struct attribute **format_attrs; | ||
342 | 343 | ||
343 | /* | 344 | /* |
344 | * CPU Hotplug hooks | 345 | * CPU Hotplug hooks |
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c index dd002faff7a6..95e7fe1c5f0b 100644 --- a/arch/x86/kernel/cpu/perf_event_amd.c +++ b/arch/x86/kernel/cpu/perf_event_amd.c | |||
@@ -404,6 +404,21 @@ static void amd_pmu_cpu_dead(int cpu) | |||
404 | } | 404 | } |
405 | } | 405 | } |
406 | 406 | ||
407 | PMU_FORMAT_ATTR(event, "config:0-7,32-35"); | ||
408 | PMU_FORMAT_ATTR(umask, "config:8-15" ); | ||
409 | PMU_FORMAT_ATTR(edge, "config:18" ); | ||
410 | PMU_FORMAT_ATTR(inv, "config:23" ); | ||
411 | PMU_FORMAT_ATTR(cmask, "config:24-31" ); | ||
412 | |||
413 | static struct attribute *amd_format_attr[] = { | ||
414 | &format_attr_event.attr, | ||
415 | &format_attr_umask.attr, | ||
416 | &format_attr_edge.attr, | ||
417 | &format_attr_inv.attr, | ||
418 | &format_attr_cmask.attr, | ||
419 | NULL, | ||
420 | }; | ||
421 | |||
407 | static __initconst const struct x86_pmu amd_pmu = { | 422 | static __initconst const struct x86_pmu amd_pmu = { |
408 | .name = "AMD", | 423 | .name = "AMD", |
409 | .handle_irq = x86_pmu_handle_irq, | 424 | .handle_irq = x86_pmu_handle_irq, |
@@ -426,6 +441,8 @@ static __initconst const struct x86_pmu amd_pmu = { | |||
426 | .get_event_constraints = amd_get_event_constraints, | 441 | .get_event_constraints = amd_get_event_constraints, |
427 | .put_event_constraints = amd_put_event_constraints, | 442 | .put_event_constraints = amd_put_event_constraints, |
428 | 443 | ||
444 | .format_attrs = amd_format_attr, | ||
445 | |||
429 | .cpu_prepare = amd_pmu_cpu_prepare, | 446 | .cpu_prepare = amd_pmu_cpu_prepare, |
430 | .cpu_starting = amd_pmu_cpu_starting, | 447 | .cpu_starting = amd_pmu_cpu_starting, |
431 | .cpu_dead = amd_pmu_cpu_dead, | 448 | .cpu_dead = amd_pmu_cpu_dead, |
@@ -596,6 +613,7 @@ static __initconst const struct x86_pmu amd_pmu_f15h = { | |||
596 | .cpu_dead = amd_pmu_cpu_dead, | 613 | .cpu_dead = amd_pmu_cpu_dead, |
597 | #endif | 614 | #endif |
598 | .cpu_starting = amd_pmu_cpu_starting, | 615 | .cpu_starting = amd_pmu_cpu_starting, |
616 | .format_attrs = amd_format_attr, | ||
599 | }; | 617 | }; |
600 | 618 | ||
601 | __init int amd_pmu_init(void) | 619 | __init int amd_pmu_init(void) |
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 6a84e7f28f05..26b3e2fef104 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
@@ -1431,6 +1431,24 @@ static void core_pmu_enable_all(int added) | |||
1431 | } | 1431 | } |
1432 | } | 1432 | } |
1433 | 1433 | ||
1434 | PMU_FORMAT_ATTR(event, "config:0-7" ); | ||
1435 | PMU_FORMAT_ATTR(umask, "config:8-15" ); | ||
1436 | PMU_FORMAT_ATTR(edge, "config:18" ); | ||
1437 | PMU_FORMAT_ATTR(pc, "config:19" ); | ||
1438 | PMU_FORMAT_ATTR(any, "config:21" ); /* v3 + */ | ||
1439 | PMU_FORMAT_ATTR(inv, "config:23" ); | ||
1440 | PMU_FORMAT_ATTR(cmask, "config:24-31" ); | ||
1441 | |||
1442 | static struct attribute *intel_arch_formats_attr[] = { | ||
1443 | &format_attr_event.attr, | ||
1444 | &format_attr_umask.attr, | ||
1445 | &format_attr_edge.attr, | ||
1446 | &format_attr_pc.attr, | ||
1447 | &format_attr_inv.attr, | ||
1448 | &format_attr_cmask.attr, | ||
1449 | NULL, | ||
1450 | }; | ||
1451 | |||
1434 | static __initconst const struct x86_pmu core_pmu = { | 1452 | static __initconst const struct x86_pmu core_pmu = { |
1435 | .name = "core", | 1453 | .name = "core", |
1436 | .handle_irq = x86_pmu_handle_irq, | 1454 | .handle_irq = x86_pmu_handle_irq, |
@@ -1455,6 +1473,7 @@ static __initconst const struct x86_pmu core_pmu = { | |||
1455 | .put_event_constraints = intel_put_event_constraints, | 1473 | .put_event_constraints = intel_put_event_constraints, |
1456 | .event_constraints = intel_core_event_constraints, | 1474 | .event_constraints = intel_core_event_constraints, |
1457 | .guest_get_msrs = core_guest_get_msrs, | 1475 | .guest_get_msrs = core_guest_get_msrs, |
1476 | .format_attrs = intel_arch_formats_attr, | ||
1458 | }; | 1477 | }; |
1459 | 1478 | ||
1460 | struct intel_shared_regs *allocate_shared_regs(int cpu) | 1479 | struct intel_shared_regs *allocate_shared_regs(int cpu) |
@@ -1553,6 +1572,21 @@ static void intel_pmu_flush_branch_stack(void) | |||
1553 | intel_pmu_lbr_reset(); | 1572 | intel_pmu_lbr_reset(); |
1554 | } | 1573 | } |
1555 | 1574 | ||
1575 | PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63"); | ||
1576 | |||
1577 | static struct attribute *intel_arch3_formats_attr[] = { | ||
1578 | &format_attr_event.attr, | ||
1579 | &format_attr_umask.attr, | ||
1580 | &format_attr_edge.attr, | ||
1581 | &format_attr_pc.attr, | ||
1582 | &format_attr_any.attr, | ||
1583 | &format_attr_inv.attr, | ||
1584 | &format_attr_cmask.attr, | ||
1585 | |||
1586 | &format_attr_offcore_rsp.attr, /* XXX do NHM/WSM + SNB breakout */ | ||
1587 | NULL, | ||
1588 | }; | ||
1589 | |||
1556 | static __initconst const struct x86_pmu intel_pmu = { | 1590 | static __initconst const struct x86_pmu intel_pmu = { |
1557 | .name = "Intel", | 1591 | .name = "Intel", |
1558 | .handle_irq = intel_pmu_handle_irq, | 1592 | .handle_irq = intel_pmu_handle_irq, |
@@ -1576,6 +1610,8 @@ static __initconst const struct x86_pmu intel_pmu = { | |||
1576 | .get_event_constraints = intel_get_event_constraints, | 1610 | .get_event_constraints = intel_get_event_constraints, |
1577 | .put_event_constraints = intel_put_event_constraints, | 1611 | .put_event_constraints = intel_put_event_constraints, |
1578 | 1612 | ||
1613 | .format_attrs = intel_arch3_formats_attr, | ||
1614 | |||
1579 | .cpu_prepare = intel_pmu_cpu_prepare, | 1615 | .cpu_prepare = intel_pmu_cpu_prepare, |
1580 | .cpu_starting = intel_pmu_cpu_starting, | 1616 | .cpu_starting = intel_pmu_cpu_starting, |
1581 | .cpu_dying = intel_pmu_cpu_dying, | 1617 | .cpu_dying = intel_pmu_cpu_dying, |
diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index c7181befecde..32bcfc7dd230 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c | |||
@@ -87,6 +87,23 @@ static void p6_pmu_enable_event(struct perf_event *event) | |||
87 | (void)checking_wrmsrl(hwc->config_base, val); | 87 | (void)checking_wrmsrl(hwc->config_base, val); |
88 | } | 88 | } |
89 | 89 | ||
90 | PMU_FORMAT_ATTR(event, "config:0-7" ); | ||
91 | PMU_FORMAT_ATTR(umask, "config:8-15" ); | ||
92 | PMU_FORMAT_ATTR(edge, "config:18" ); | ||
93 | PMU_FORMAT_ATTR(pc, "config:19" ); | ||
94 | PMU_FORMAT_ATTR(inv, "config:23" ); | ||
95 | PMU_FORMAT_ATTR(cmask, "config:24-31" ); | ||
96 | |||
97 | static struct attribute *intel_p6_formats_attr[] = { | ||
98 | &format_attr_event.attr, | ||
99 | &format_attr_umask.attr, | ||
100 | &format_attr_edge.attr, | ||
101 | &format_attr_pc.attr, | ||
102 | &format_attr_inv.attr, | ||
103 | &format_attr_cmask.attr, | ||
104 | NULL, | ||
105 | }; | ||
106 | |||
90 | static __initconst const struct x86_pmu p6_pmu = { | 107 | static __initconst const struct x86_pmu p6_pmu = { |
91 | .name = "p6", | 108 | .name = "p6", |
92 | .handle_irq = x86_pmu_handle_irq, | 109 | .handle_irq = x86_pmu_handle_irq, |
@@ -115,6 +132,8 @@ static __initconst const struct x86_pmu p6_pmu = { | |||
115 | .cntval_mask = (1ULL << 32) - 1, | 132 | .cntval_mask = (1ULL << 32) - 1, |
116 | .get_event_constraints = x86_get_event_constraints, | 133 | .get_event_constraints = x86_get_event_constraints, |
117 | .event_constraints = p6_event_constraints, | 134 | .event_constraints = p6_event_constraints, |
135 | |||
136 | .format_attrs = intel_p6_formats_attr, | ||
118 | }; | 137 | }; |
119 | 138 | ||
120 | __init int p6_pmu_init(void) | 139 | __init int p6_pmu_init(void) |