Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jiri Olsa and committed by
Arnaldo Carvalho de Melo
641cc938 4a3d2d9b

+109
+14
Documentation/ABI/testing/sysfs-bus-event_source-devices-format
··· 1 + Where: /sys/bus/event_source/devices/<dev>/format 2 + Date: January 2012 3 + Kernel Version: 3.3 4 + Contact: Jiri Olsa <jolsa@redhat.com> 5 + Description: 6 + Attribute group to describe the magic bits that go into 7 + perf_event_attr::config[012] for a particular pmu. 8 + Each attribute of this group defines the 'hardware' bitmask 9 + we want to export, so that userspace can deal with sane 10 + name/value pairs. 11 + 12 + Example: 'config1:1,6-10,44' 13 + Defines contents of attribute that occupies bits 1,6-10,44 of 14 + perf_event_attr::config1.
+7
arch/x86/kernel/cpu/perf_event.c
··· 1314 1314 pr_info("no hardware sampling interrupt available.\n"); 1315 1315 } 1316 1316 1317 + static struct attribute_group x86_pmu_format_group = { 1318 + .name = "format", 1319 + .attrs = NULL, 1320 + }; 1321 + 1317 1322 static int __init init_hw_perf_events(void) 1318 1323 { 1319 1324 struct x86_pmu_quirk *quirk; ··· 1393 1388 } 1394 1389 1395 1390 x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */ 1391 + x86_pmu_format_group.attrs = x86_pmu.format_attrs; 1396 1392 1397 1393 pr_info("... version: %d\n", x86_pmu.version); 1398 1394 pr_info("... bit width: %d\n", x86_pmu.cntval_bits); ··· 1674 1668 1675 1669 static const struct attribute_group *x86_pmu_attr_groups[] = { 1676 1670 &x86_pmu_attr_group, 1671 + &x86_pmu_format_group, 1677 1672 NULL, 1678 1673 }; 1679 1674
+1
arch/x86/kernel/cpu/perf_event.h
··· 339 339 * sysfs attrs 340 340 */ 341 341 int attr_rdpmc; 342 + struct attribute **format_attrs; 342 343 343 344 /* 344 345 * CPU Hotplug hooks
+18
arch/x86/kernel/cpu/perf_event_amd.c
··· 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 422 static __initconst const struct x86_pmu amd_pmu = { 408 423 .name = "AMD", 409 424 .handle_irq = x86_pmu_handle_irq, ··· 440 425 .max_period = (1ULL << 47) - 1, 441 426 .get_event_constraints = amd_get_event_constraints, 442 427 .put_event_constraints = amd_put_event_constraints, 428 + 429 + .format_attrs = amd_format_attr, 443 430 444 431 .cpu_prepare = amd_pmu_cpu_prepare, 445 432 .cpu_starting = amd_pmu_cpu_starting, ··· 613 596 .cpu_dead = amd_pmu_cpu_dead, 614 597 #endif 615 598 .cpu_starting = amd_pmu_cpu_starting, 599 + .format_attrs = amd_format_attr, 616 600 }; 617 601 618 602 __init int amd_pmu_init(void)
+36
arch/x86/kernel/cpu/perf_event_intel.c
··· 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 1452 static __initconst const struct x86_pmu core_pmu = { 1435 1453 .name = "core", 1436 1454 .handle_irq = x86_pmu_handle_irq, ··· 1473 1455 .put_event_constraints = intel_put_event_constraints, 1474 1456 .event_constraints = intel_core_event_constraints, 1475 1457 .guest_get_msrs = core_guest_get_msrs, 1458 + .format_attrs = intel_arch_formats_attr, 1476 1459 }; 1477 1460 1478 1461 struct intel_shared_regs *allocate_shared_regs(int cpu) ··· 1572 1553 intel_pmu_lbr_reset(); 1573 1554 } 1574 1555 1556 + PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63"); 1557 + 1558 + static struct attribute *intel_arch3_formats_attr[] = { 1559 + &format_attr_event.attr, 1560 + &format_attr_umask.attr, 1561 + &format_attr_edge.attr, 1562 + &format_attr_pc.attr, 1563 + &format_attr_any.attr, 1564 + &format_attr_inv.attr, 1565 + &format_attr_cmask.attr, 1566 + 1567 + &format_attr_offcore_rsp.attr, /* XXX do NHM/WSM + SNB breakout */ 1568 + NULL, 1569 + }; 1570 + 1575 1571 static __initconst const struct x86_pmu intel_pmu = { 1576 1572 .name = "Intel", 1577 1573 .handle_irq = intel_pmu_handle_irq, ··· 1609 1575 .max_period = (1ULL << 31) - 1, 1610 1576 .get_event_constraints = intel_get_event_constraints, 1611 1577 .put_event_constraints = intel_put_event_constraints, 1578 + 1579 + .format_attrs = intel_arch3_formats_attr, 1612 1580 1613 1581 .cpu_prepare = intel_pmu_cpu_prepare, 1614 1582 .cpu_starting = intel_pmu_cpu_starting,
+19
arch/x86/kernel/cpu/perf_event_p6.c
··· 87 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 107 static __initconst const struct x86_pmu p6_pmu = { 91 108 .name = "p6", 92 109 .handle_irq = x86_pmu_handle_irq, ··· 132 115 .cntval_mask = (1ULL << 32) - 1, 133 116 .get_event_constraints = x86_get_event_constraints, 134 117 .event_constraints = p6_event_constraints, 118 + 119 + .format_attrs = intel_p6_formats_attr, 135 120 }; 136 121 137 122 __init int p6_pmu_init(void)
+14
include/linux/perf_event.h
··· 550 550 #include <linux/irq_work.h> 551 551 #include <linux/static_key.h> 552 552 #include <linux/atomic.h> 553 + #include <linux/sysfs.h> 553 554 #include <asm/local.h> 554 555 555 556 #define PERF_MAX_STACK_DEPTH 255 ··· 1291 1290 (void *)(unsigned long)smp_processor_id()); \ 1292 1291 register_cpu_notifier(&fn##_nb); \ 1293 1292 } while (0) 1293 + 1294 + 1295 + #define PMU_FORMAT_ATTR(_name, _format) \ 1296 + static ssize_t \ 1297 + _name##_show(struct device *dev, \ 1298 + struct device_attribute *attr, \ 1299 + char *page) \ 1300 + { \ 1301 + BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \ 1302 + return sprintf(page, _format "\n"); \ 1303 + } \ 1304 + \ 1305 + static struct device_attribute format_attr_##_name = __ATTR_RO(_name) 1294 1306 1295 1307 #endif /* __KERNEL__ */ 1296 1308 #endif /* _LINUX_PERF_EVENT_H */