diff options
author | Robert Richter <robert.richter@amd.com> | 2012-09-12 06:59:44 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-10-05 07:57:47 -0400 |
commit | 2e132b12f78d88672711ae1d87624951de1089ca (patch) | |
tree | bfbfa9b51e5e01ef9ad599816de2bb8915a2b10f | |
parent | c942ee2e62dff1a7bc6f809965e93e46808d554c (diff) |
perf/AMD/IBS: Add sysfs support
Add sysfs format entries for AMD IBS PMUs:
# find /sys/bus/event_source/devices/ibs_*/format
/sys/bus/event_source/devices/ibs_fetch/format
/sys/bus/event_source/devices/ibs_fetch/format/rand_en
/sys/bus/event_source/devices/ibs_op/format
/sys/bus/event_source/devices/ibs_op/format/cnt_ctl
This allows to specify following IBS options:
$ perf record -e ibs_fetch/rand_en=1/GH ...
$ perf record -e ibs_op/cnt_ctl=1/GH ...
Option cnt_ctl is only enabled if the IBS_CAPS_OPCNT bit is set in IBS
cpuid feature flags (AMD family 10h RevC and above).
Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1347447584-28405-1-git-send-email-robert.richter@amd.com
[ Added small readability improvements. ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_amd_ibs.c | 61 |
1 files changed, 49 insertions, 12 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c index eebd5ffe1bba..6336bcbd0618 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c | |||
@@ -41,17 +41,22 @@ struct cpu_perf_ibs { | |||
41 | }; | 41 | }; |
42 | 42 | ||
43 | struct perf_ibs { | 43 | struct perf_ibs { |
44 | struct pmu pmu; | 44 | struct pmu pmu; |
45 | unsigned int msr; | 45 | unsigned int msr; |
46 | u64 config_mask; | 46 | u64 config_mask; |
47 | u64 cnt_mask; | 47 | u64 cnt_mask; |
48 | u64 enable_mask; | 48 | u64 enable_mask; |
49 | u64 valid_mask; | 49 | u64 valid_mask; |
50 | u64 max_period; | 50 | u64 max_period; |
51 | unsigned long offset_mask[1]; | 51 | unsigned long offset_mask[1]; |
52 | int offset_max; | 52 | int offset_max; |
53 | struct cpu_perf_ibs __percpu *pcpu; | 53 | struct cpu_perf_ibs __percpu *pcpu; |
54 | u64 (*get_count)(u64 config); | 54 | |
55 | struct attribute **format_attrs; | ||
56 | struct attribute_group format_group; | ||
57 | const struct attribute_group *attr_groups[2]; | ||
58 | |||
59 | u64 (*get_count)(u64 config); | ||
55 | }; | 60 | }; |
56 | 61 | ||
57 | struct perf_ibs_data { | 62 | struct perf_ibs_data { |
@@ -446,6 +451,19 @@ static void perf_ibs_del(struct perf_event *event, int flags) | |||
446 | 451 | ||
447 | static void perf_ibs_read(struct perf_event *event) { } | 452 | static void perf_ibs_read(struct perf_event *event) { } |
448 | 453 | ||
454 | PMU_FORMAT_ATTR(rand_en, "config:57"); | ||
455 | PMU_FORMAT_ATTR(cnt_ctl, "config:19"); | ||
456 | |||
457 | static struct attribute *ibs_fetch_format_attrs[] = { | ||
458 | &format_attr_rand_en.attr, | ||
459 | NULL, | ||
460 | }; | ||
461 | |||
462 | static struct attribute *ibs_op_format_attrs[] = { | ||
463 | NULL, /* &format_attr_cnt_ctl.attr if IBS_CAPS_OPCNT */ | ||
464 | NULL, | ||
465 | }; | ||
466 | |||
449 | static struct perf_ibs perf_ibs_fetch = { | 467 | static struct perf_ibs perf_ibs_fetch = { |
450 | .pmu = { | 468 | .pmu = { |
451 | .task_ctx_nr = perf_invalid_context, | 469 | .task_ctx_nr = perf_invalid_context, |
@@ -465,6 +483,7 @@ static struct perf_ibs perf_ibs_fetch = { | |||
465 | .max_period = IBS_FETCH_MAX_CNT << 4, | 483 | .max_period = IBS_FETCH_MAX_CNT << 4, |
466 | .offset_mask = { MSR_AMD64_IBSFETCH_REG_MASK }, | 484 | .offset_mask = { MSR_AMD64_IBSFETCH_REG_MASK }, |
467 | .offset_max = MSR_AMD64_IBSFETCH_REG_COUNT, | 485 | .offset_max = MSR_AMD64_IBSFETCH_REG_COUNT, |
486 | .format_attrs = ibs_fetch_format_attrs, | ||
468 | 487 | ||
469 | .get_count = get_ibs_fetch_count, | 488 | .get_count = get_ibs_fetch_count, |
470 | }; | 489 | }; |
@@ -488,6 +507,7 @@ static struct perf_ibs perf_ibs_op = { | |||
488 | .max_period = IBS_OP_MAX_CNT << 4, | 507 | .max_period = IBS_OP_MAX_CNT << 4, |
489 | .offset_mask = { MSR_AMD64_IBSOP_REG_MASK }, | 508 | .offset_mask = { MSR_AMD64_IBSOP_REG_MASK }, |
490 | .offset_max = MSR_AMD64_IBSOP_REG_COUNT, | 509 | .offset_max = MSR_AMD64_IBSOP_REG_COUNT, |
510 | .format_attrs = ibs_op_format_attrs, | ||
491 | 511 | ||
492 | .get_count = get_ibs_op_count, | 512 | .get_count = get_ibs_op_count, |
493 | }; | 513 | }; |
@@ -597,6 +617,17 @@ static __init int perf_ibs_pmu_init(struct perf_ibs *perf_ibs, char *name) | |||
597 | 617 | ||
598 | perf_ibs->pcpu = pcpu; | 618 | perf_ibs->pcpu = pcpu; |
599 | 619 | ||
620 | /* register attributes */ | ||
621 | if (perf_ibs->format_attrs[0]) { | ||
622 | memset(&perf_ibs->format_group, 0, sizeof(perf_ibs->format_group)); | ||
623 | perf_ibs->format_group.name = "format"; | ||
624 | perf_ibs->format_group.attrs = perf_ibs->format_attrs; | ||
625 | |||
626 | memset(&perf_ibs->attr_groups, 0, sizeof(perf_ibs->attr_groups)); | ||
627 | perf_ibs->attr_groups[0] = &perf_ibs->format_group; | ||
628 | perf_ibs->pmu.attr_groups = perf_ibs->attr_groups; | ||
629 | } | ||
630 | |||
600 | ret = perf_pmu_register(&perf_ibs->pmu, name, -1); | 631 | ret = perf_pmu_register(&perf_ibs->pmu, name, -1); |
601 | if (ret) { | 632 | if (ret) { |
602 | perf_ibs->pcpu = NULL; | 633 | perf_ibs->pcpu = NULL; |
@@ -608,13 +639,19 @@ static __init int perf_ibs_pmu_init(struct perf_ibs *perf_ibs, char *name) | |||
608 | 639 | ||
609 | static __init int perf_event_ibs_init(void) | 640 | static __init int perf_event_ibs_init(void) |
610 | { | 641 | { |
642 | struct attribute **attr = ibs_op_format_attrs; | ||
643 | |||
611 | if (!ibs_caps) | 644 | if (!ibs_caps) |
612 | return -ENODEV; /* ibs not supported by the cpu */ | 645 | return -ENODEV; /* ibs not supported by the cpu */ |
613 | 646 | ||
614 | perf_ibs_pmu_init(&perf_ibs_fetch, "ibs_fetch"); | 647 | perf_ibs_pmu_init(&perf_ibs_fetch, "ibs_fetch"); |
615 | if (ibs_caps & IBS_CAPS_OPCNT) | 648 | |
649 | if (ibs_caps & IBS_CAPS_OPCNT) { | ||
616 | perf_ibs_op.config_mask |= IBS_OP_CNT_CTL; | 650 | perf_ibs_op.config_mask |= IBS_OP_CNT_CTL; |
651 | *attr++ = &format_attr_cnt_ctl.attr; | ||
652 | } | ||
617 | perf_ibs_pmu_init(&perf_ibs_op, "ibs_op"); | 653 | perf_ibs_pmu_init(&perf_ibs_op, "ibs_op"); |
654 | |||
618 | register_nmi_handler(NMI_LOCAL, perf_ibs_nmi_handler, 0, "perf_ibs"); | 655 | register_nmi_handler(NMI_LOCAL, perf_ibs_nmi_handler, 0, "perf_ibs"); |
619 | printk(KERN_INFO "perf: AMD IBS detected (0x%08x)\n", ibs_caps); | 656 | printk(KERN_INFO "perf: AMD IBS detected (0x%08x)\n", ibs_caps); |
620 | 657 | ||