perf PMU support for Haswell: Extended functionality v1
Subsystems (3)
This is based on v7 of the earlier combined Haswell PMU patchkit. The basic functionality has moved into a separate patchkit. These patches implement more advanced functionality. Most of the functionality is related to TSX.
This applies on top of the basic hsw/pmu4-basics patchkit posted separately.
Some of this touches similar areas as Stephane's patchkit, with some shared patches too.
Available atgit://git.kernel.org/pub/scm/linux/kernel/ak/linux-misc.git hsw/pmu4
High level overview:
- Easy high level TSX measurement in perf stat -T
- Transaction events and attributes implemented with sysfs enumeration
- Export arch perfmon events in sysfs
- Generic weightend profiling for memory latency and transaction abort costs.
- Support for address profiling
- KVM support to do basic TSX profiling from guests
- Support for filtering/displaying transaction abort types based on PEBS information
For more details on the Haswell PMU please see the SDM. For more details on TSX please see http://halobates.de/adding-lock-elision-to-linux.pdf
Some of the added features could be added to older CPUs too. I plan to do this, but in separate patches.
Open:
- Weight sorting does not work (see thread), not a show stopper.
-Andi
PATCH 1/18 perf, tools: Support sorting by intx, abort branch flags v2
From: Andi Kleen <[email protected]>
Extend the perf branch sorting code to support sorting by intx or abort qualifiers. Also print out those qualifiers.
This also fixes up some of the existing sort key documentation.
We do not support notx here, because it's simply not showing the intx flag.
v2: Readd flags to man pages
--- tools/perf/util/sort.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
tools/perf/util/sort.c +2 -0
@@ -537,6 +537,8 @@ static struct sort_dimension common_sort_dimensions[] = {DIM (SORT_PARENT ,"parent" , sort_parent),DIM (SORT_CPU ,"cpu" , sort_cpu),DIM (SORT_SRCLINE ,"srcline" , sort_srcline), +DIM (SORT_ABORT ,"abort" , sort_abort), + DIM(SORT_INTX, "intx", sort_intx) };#undef DIM
Signature · 1 line
1.7.7.6
PATCH 2/18 perf, kvm: Support the intx/intx_cp modifiers in KVM arch perfmon emulation v5
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
This is not arch perfmon, but older CPUs will just ignore it. This makes it possible to do at least some TSX measurements from a KVM guest
Cc: [email protected]
v2: Various fixes to address review feedback
v3: Ignore the bits when no CPUID. No #GP. Force raw events with TSX bits.
v4: Use reserved bits for #GP
v5: Remove obsolete argument
--- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/pmu.c | 25 ++++++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-)
arch/x86/include/asm/kvm_host.h +1 -0
@@ -320,6 +320,7 @@ struct kvm_pmu {u64 global_ovf_ctrl;u64 counter_bitmask[2 ];u64 global_ctrl_mask; +u64 reserved_bits;u8 version;struct kvm_pmc gp_counters[INTEL_PMC_MAX_GENERIC ];struct kvm_pmc fixed_counters[INTEL_PMC_MAX_FIXED ];
arch/x86/kvm/pmu.c +20 -5
@@ -160,7 +160,7 @@ static void stop_counter(struct kvm_pmc *pmc)static void reprogram_counter (struct kvm_pmc *pmc,u32 type,unsigned config,bool exclude_user,bool exclude_kernel, -bool intr) +bool intr,bool intx,bool intx_cp) {struct perf_event *event;struct perf_event_attr attr = {
@@ -173,6 +173,10 @@ static void reprogram_counter(struct kvm_pmc *pmc, u32 type, .exclude_kernel = exclude_kernel, .config = config, }; +if (intx) + attr.config |=HSW_INTX ; +if (intx_cp) + attr.config |=HSW_INTX_CHECKPOINTED ; attr.sample_period = (-pmc->counter) &pmc_bitmask (pmc);
@@ -226,7 +230,9 @@ static void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)if (!(eventsel & (ARCH_PERFMON_EVENTSEL_EDGE |ARCH_PERFMON_EVENTSEL_INV | -ARCH_PERFMON_EVENTSEL_CMASK ))) { +ARCH_PERFMON_EVENTSEL_CMASK | +HSW_INTX | +HSW_INTX_CHECKPOINTED ))) { config =find_arch_event (&pmc->vcpu->arch.pmu, event_select, unit_mask);if (config !=PERF_COUNT_HW_MAX )
@@ -239,7 +245,9 @@ static void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)reprogram_counter (pmc, type, config, !(eventsel &ARCH_PERFMON_EVENTSEL_USR ), !(eventsel &ARCH_PERFMON_EVENTSEL_OS ), - eventsel &ARCH_PERFMON_EVENTSEL_INT ); + eventsel &ARCH_PERFMON_EVENTSEL_INT , + (eventsel &HSW_INTX ), + (eventsel &HSW_INTX_CHECKPOINTED )); }static void reprogram_fixed_counter (struct kvm_pmc *pmc,u8 en_pmi,int idx)
@@ -256,7 +264,7 @@ static void reprogram_fixed_counter(struct kvm_pmc *pmc, u8 en_pmi, int idx) arch_events[fixed_pmc_events[idx]].event_type, !(en &0x2 ),/* exclude user */ !(en &0x1 ),/* exclude kernel */ - pmi); + pmi, false, false); }static inline u8 fixed_en_pmi (u64 ctrl,int idx)
@@ -400,7 +408,7 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data) }else if ((pmc =get_gp_pmc (pmu, index,MSR_P6_EVNTSEL0 ))) {if (data == pmc->eventsel)return 0 ; -if (!(data &0xffffffff00200000ull )) { +if (!(data & pmu->reserved_bits)) {reprogram_gp_counter (pmc, data);return 0 ; }
@@ -442,6 +450,7 @@ void kvm_pmu_cpuid_update(struct kvm_vcpu *vcpu) pmu->counter_bitmask[KVM_PMC_GP ] =0 ; pmu->counter_bitmask[KVM_PMC_FIXED ] =0 ; pmu->version =0 ; + pmu->reserved_bits =0xffffffff00200000ull ; entry =kvm_find_cpuid_entry (vcpu,0xa ,0 );if (!entry)
@@ -470,6 +479,12 @@ void kvm_pmu_cpuid_update(struct kvm_vcpu *vcpu) pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) -1 ) | (((1ull << pmu->nr_arch_fixed_counters) -1 ) <<INTEL_PMC_IDX_FIXED ); pmu->global_ctrl_mask = ~pmu->global_ctrl; + + entry =kvm_find_cpuid_entry (vcpu,7 ,0 ); +if (entry && + (boot_cpu_has (X86_FEATURE_HLE ) ||boot_cpu_has (X86_FEATURE_RTM )) && + (entry->ebx & (X86_FEATURE_HLE |X86_FEATURE_RTM ))) + pmu->reserved_bits ^=HSW_INTX |HSW_INTX_CHECKPOINTED ; }void kvm_pmu_init (struct kvm_vcpu *vcpu)
Signature · 1 line
1.7.7.6
Re: [PATCH 02/18] perf, kvm: Support the intx/intx_cp modifiers in KVM arch perfmon emulation v5
Quoted 11 lines · Andi Kleen
From: Andi Kleen <[email protected]>
This is not arch perfmon, but older CPUs will just ignore it. This makes it possible to do at least some TSX measurements from a KVM guest
Cc: [email protected]
v2: Various fixes to address review feedback
v3: Ignore the bits when no CPUID. No #GP. Force raw events with TSX bits.
v4: Use reserved bits for #GP
v5: Remove obsolete argumentSigned-off-by Andi Kleen <[email protected]>
I suppose it will go through tip tree with all the other patches this one depends on.
Quoted 104 lines
--- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/pmu.c | 25 ++++++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-)arch/x86/include/asm/kvm_host.h +1
-0@@ -320,6 +320,7 @@ struct kvm_pmu {u64 global_ovf_ctrl;u64 counter_bitmask[2 ];u64 global_ctrl_mask; +u64 reserved_bits;u8 version;struct kvm_pmc gp_counters[INTEL_PMC_MAX_GENERIC ];struct kvm_pmc fixed_counters[INTEL_PMC_MAX_FIXED ];arch/x86/kvm/pmu.c +20
-5@@ -160,7 +160,7 @@ static void stop_counter(struct kvm_pmc *pmc)static void reprogram_counter (struct kvm_pmc *pmc,u32 type,unsigned config,bool exclude_user,bool exclude_kernel, -bool intr) +bool intr,bool intx,bool intx_cp) {struct perf_event *event;struct perf_event_attr attr = {@@ -173,6 +173,10 @@ static void reprogram_counter(struct kvm_pmc *pmc, u32 type, .exclude_kernel = exclude_kernel, .config = config, }; +if (intx) + attr.config |=HSW_INTX ; +if (intx_cp) + attr.config |=HSW_INTX_CHECKPOINTED ; attr.sample_period = (-pmc->counter) &pmc_bitmask (pmc);@@ -226,7 +230,9 @@ static void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)if (!(eventsel & (ARCH_PERFMON_EVENTSEL_EDGE |ARCH_PERFMON_EVENTSEL_INV | -ARCH_PERFMON_EVENTSEL_CMASK ))) { +ARCH_PERFMON_EVENTSEL_CMASK | +HSW_INTX | +HSW_INTX_CHECKPOINTED ))) { config =find_arch_event (&pmc->vcpu->arch.pmu, event_select, unit_mask);if (config !=PERF_COUNT_HW_MAX )@@ -239,7 +245,9 @@ static void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)reprogram_counter (pmc, type, config, !(eventsel &ARCH_PERFMON_EVENTSEL_USR ), !(eventsel &ARCH_PERFMON_EVENTSEL_OS ), - eventsel &ARCH_PERFMON_EVENTSEL_INT ); + eventsel &ARCH_PERFMON_EVENTSEL_INT , + (eventsel &HSW_INTX ), + (eventsel &HSW_INTX_CHECKPOINTED )); }static void reprogram_fixed_counter (struct kvm_pmc *pmc,u8 en_pmi,int idx)@@ -256,7 +264,7 @@ static void reprogram_fixed_counter(struct kvm_pmc *pmc, u8 en_pmi, int idx) arch_events[fixed_pmc_events[idx]].event_type, !(en &0x2 ),/* exclude user */ !(en &0x1 ),/* exclude kernel */ - pmi); + pmi, false, false); }static inline u8 fixed_en_pmi (u64 ctrl,int idx)@@ -400,7 +408,7 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data) }else if ((pmc =get_gp_pmc (pmu, index,MSR_P6_EVNTSEL0 ))) {if (data == pmc->eventsel)return 0 ; -if (!(data &0xffffffff00200000ull )) { +if (!(data & pmu->reserved_bits)) {reprogram_gp_counter (pmc, data);return 0 ; }@@ -442,6 +450,7 @@ void kvm_pmu_cpuid_update(struct kvm_vcpu *vcpu) pmu->counter_bitmask[KVM_PMC_GP ] =0 ; pmu->counter_bitmask[KVM_PMC_FIXED ] =0 ; pmu->version =0 ; + pmu->reserved_bits =0xffffffff00200000ull ; entry =kvm_find_cpuid_entry (vcpu,0xa ,0 );if (!entry)@@ -470,6 +479,12 @@ void kvm_pmu_cpuid_update(struct kvm_vcpu *vcpu) pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) -1 ) | (((1ull << pmu->nr_arch_fixed_counters) -1 ) <<INTEL_PMC_IDX_FIXED ); pmu->global_ctrl_mask = ~pmu->global_ctrl; + + entry =kvm_find_cpuid_entry (vcpu,7 ,0 ); +if (entry && + (boot_cpu_has (X86_FEATURE_HLE ) ||boot_cpu_has (X86_FEATURE_RTM )) && + (entry->ebx & (X86_FEATURE_HLE |X86_FEATURE_RTM ))) + pmu->reserved_bits ^=HSW_INTX |HSW_INTX_CHECKPOINTED ; }void kvm_pmu_init (struct kvm_vcpu *vcpu)Signature · 1 line
1.7.7.6
--
Gleb.
PATCH 3/18 perf, x86: Support PERF_SAMPLE_ADDR on Haswell
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Haswell supplies the address for every PEBS memory event, so always fill it in when the user requested it. It will be 0 when not useful (no memory access)
--- arch/x86/kernel/cpu/perf_event_intel_ds.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
arch/x86/kernel/cpu/perf_event_intel_ds.c +4 -0
@@ -630,6 +630,10 @@ static void __intel_pmu_pebs_event(struct perf_event *event,else regs.flags &= ~PERF_EFLAGS_EXACT ; +if ((event->attr.sample_type &PERF_SAMPLE_ADDR ) && + x86_pmu.intel_cap.pebs_format >=2 ) + data.addr = ((struct pebs_record_v2 *)pebs)->nhm.dla; +if (has_branch_stack (event)) data.br_stack = &cpuc->lbr_stack;
Signature · 1 line
1.7.7.6
PATCH 4/18 perf, core: Add a concept of a weightened sample v2
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
For some events it's useful to weight sample with a hardware provided number. This expresses how expensive the action the sample represent was. This allows the profiler to scale the samples to be more informative to the programmer.
There is already the period which is used similarly, but it means something different, so I chose to not overload it. Instead a new sample type for WEIGHT is added.
Can be used for multiple things. Initially it is used for TSX abort costs and profiling by memory latencies (so to make expensive load appear higher up in the histograms) The concept is quite generic and can be extended to many other kinds of events or architectures, as long as the hardware provides suitable auxillary values. In principle it could be also used for software tracpoints.
This adds the generic glue. A new optional sample format for a 64bit weight value.
v2: Move weight format to the end. Remove *_FORMAT_WEIGHT
--- include/linux/perf_event.h | 2 ++ include/uapi/linux/perf_event.h | 6 +++++- kernel/events/core.c | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletions(-)
include/linux/perf_event.h +2 -0
@@ -588,6 +588,7 @@ struct perf_sample_data {struct perf_branch_stack *br_stack;struct perf_regs_user regs_user;u64 stack_user_size; +u64 weight; }; static inline void perf_sample_data_init(struct perf_sample_data *data,
@@ -601,6 +602,7 @@ static inline void perf_sample_data_init(struct perf_sample_data *data, data->regs_user.abi =PERF_SAMPLE_REGS_ABI_NONE ; data->regs_user.regs =NULL ; data->stack_user_size =0 ; + data->weight =0 ; } extern void perf_output_sample(struct perf_output_handle *handle,
include/uapi/linux/perf_event.h +5 -1
@@ -132,8 +132,10 @@ enum perf_event_sample_format {PERF_SAMPLE_BRANCH_STACK =1U <<11 ,PERF_SAMPLE_REGS_USER =1U <<12 ,PERF_SAMPLE_STACK_USER =1U <<13 , +PERF_SAMPLE_WEIGHT =1U <<14 , + + PERF_SAMPLE_MAX = 1U << 15, /* non-ABI */ - PERF_SAMPLE_MAX = 1U << 14, /* non-ABI */ };/*
@@ -591,6 +593,8 @@ enum perf_event_type {* { u64 size; * char data[size]; * u64 dyn_size; } && PERF_SAMPLE_STACK_USER +* +* { u64 weight; } && PERF_SAMPLE_WEIGHT * }; */ PERF_RECORD_SAMPLE = 9,
kernel/events/core.c +6 -0
@@ -952,6 +952,9 @@ static void perf_event__header_size(struct perf_event *event)if (sample_type &PERF_SAMPLE_PERIOD ) size +=sizeof (data->period); +if (sample_type &PERF_SAMPLE_WEIGHT ) + size +=sizeof (data->weight); +if (sample_type &PERF_SAMPLE_READ ) size += event->read_size;
@@ -4169,6 +4172,9 @@ void perf_output_sample(struct perf_output_handle *handle,perf_output_sample_ustack (handle, data->stack_user_size, data->regs_user.regs); + +if (sample_type &PERF_SAMPLE_WEIGHT ) +perf_output_put (handle, data->weight); } void perf_prepare_sample(struct perf_event_header *header,
Signature · 1 line
1.7.7.6
PATCH 5/18 perf, x86: Support weight samples for PEBS
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
When a weighted sample is requested, first try to report the TSX abort cost on Haswell. If that is not available report the memory latency. This allows profiling both by abort cost and by memory latencies.
Memory latencies requires enabling a different PEBS mode (LL). When both address and weight is requested address wins.
The LL mode only works for memory related PEBS events, so add a separate event constraint table for those.
I only did this for Haswell for now, but it could be added for several other Intel CPUs too by just adding the right table for them.
--- arch/x86/kernel/cpu/perf_event.h | 4 ++ arch/x86/kernel/cpu/perf_event_intel.c | 4 ++ arch/x86/kernel/cpu/perf_event_intel_ds.c | 47 +++++++++++++++++++++++++++- 3 files changed, 53 insertions(+), 2 deletions(-)
arch/x86/kernel/cpu/perf_event.h +4 -0
@@ -168,6 +168,7 @@ struct cpu_hw_events {u64 perf_ctr_virt_mask;void *kfree_on_online; +u8 *memory_latency_events; };#define __EVENT_CONSTRAINT (c, n, m, w, o) {\
@@ -390,6 +391,7 @@ struct x86_pmu {struct event_constraint *pebs_constraints;void (*pebs_aliases)(struct perf_event *event);int max_pebs_events; +struct event_constraint *memory_lat_events;/* * Intel LBR
@@ -599,6 +601,8 @@ extern struct event_constraint intel_ivb_pebs_event_constraints[];extern struct event_constraint intel_hsw_pebs_event_constraints[]; +extern struct event_constraint intel_hsw_memory_latency_events[]; +struct event_constraint *intel_pebs_constraints (struct perf_event *event);void intel_pmu_pebs_enable (struct perf_event *event);
arch/x86/kernel/cpu/perf_event_intel.c +4 -0
@@ -1619,6 +1619,9 @@ static int hsw_hw_config(struct perf_event *event)if (ret)return ret; +/* PEBS cannot capture both */ +if (event->attr.sample_type &PERF_SAMPLE_ADDR ) + event->attr.sample_type &= ~PERF_SAMPLE_WEIGHT ;if (!boot_cpu_has (X86_FEATURE_RTM ) && !boot_cpu_has (X86_FEATURE_HLE ))return 0 ; event->hw.config |= event->attr.config & (HSW_INTX |HSW_INTX_CHECKPOINTED );
@@ -2225,6 +2228,7 @@ __init int intel_pmu_init(void) x86_pmu.hw_config = hsw_hw_config; x86_pmu.get_event_constraints = hsw_get_event_constraints; x86_pmu.format_attrs = intel_hsw_formats_attr; + x86_pmu.memory_lat_events = intel_hsw_memory_latency_events;pr_cont ("Haswell events, " );break ;
arch/x86/kernel/cpu/perf_event_intel_ds.c +45 -2
77 lines not on this page · raw message
Signature · 1 line
1.7.7.6
PATCH 6/18 perf, tools: Add support for weight v8
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
perf record has a new option -W that enables weightened sampling.
Add sorting support in top/report for the average weight per sample and the total weight sum. This allows to both compare relative cost per event and the total cost over the measurement period.
Add the necessary glue to perf report, record and the library.
v2: Merge with new hist refactoring.
v3: Fix manpage. Remove value check.
Rename global_weight to weight and weight to local_weight.
v4: Readd sort keys to manpage
v5: Move weight to end
v6: Move weight to template
v7: Rename weight key
v8: Port to latest tree
--- tools/perf/Documentation/perf-record.txt | 6 ++++ tools/perf/Documentation/perf-report.txt | 3 ++ tools/perf/Documentation/perf-top.txt | 2 +- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-diff.c | 7 ++-- tools/perf/builtin-record.c | 2 + tools/perf/builtin-report.c | 8 +++-- tools/perf/builtin-top.c | 5 ++- tools/perf/perf.h | 1 + tools/perf/tests/hists_link.c | 4 +- tools/perf/util/event.h | 1 + tools/perf/util/evsel.c | 10 ++++++ tools/perf/util/hist.c | 23 ++++++++++---- tools/perf/util/hist.h | 8 ++++- tools/perf/util/session.c | 3 ++ tools/perf/util/sort.c | 47 ++++++++++++++++++++++++++++- tools/perf/util/sort.h | 3 ++ 17 files changed, 112 insertions(+), 23 deletions(-)
tools/perf/Documentation/perf-record.txt +6 -0
@@ -185,6 +185,12 @@ is enabled for all the sampling events. The sampled branch type is the same for The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k Note that this feature may not be available on all processors. +-W:: +--weight:: +Enable weightened sampling. An additional weight is recorded per sample and can be +displayed with the weight and local_weight sort keys. This currently works for TSX +abort events and some memory events in precise mode on modern Intel CPUs. + SEE ALSO -------- linkperf:perf-stat[1], linkperf:perf-list[1]
tools/perf/Documentation/perf-report.txt +3 -0
@@ -72,6 +72,9 @@ OPTIONS - cpu: cpu number the task ran at the time of sample - srcline: filename and line number executed at the time of sample. The DWARF debugging info must be provided. + - weight: Event specific weight, e.g. memory latency or transaction + abort cost. This is the global weight. + - local_weight: Local weight version of the weight above. By default, comm, dso and symbol keys are used. (i.e. --sort comm,dso,symbol)
tools/perf/Documentation/perf-top.txt +1 -1
@@ -114,7 +114,7 @@ Default is to monitor all CPUS. --sort:: Sort by key(s): pid, comm, dso, symbol, parent, srcline, dso_from, dso_to, symbol_to, symbol_from, mispredict, - abort, intx + abort, intx, local_weight, weight -n:: --show-nr-samples::
tools/perf/builtin-annotate.c +1 -1
@@ -62,7 +62,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,return 0 ; } - he =__hists__add_entry (&evsel->hists, al,NULL ,1 ); + he =__hists__add_entry (&evsel->hists, al,NULL ,1 ,1 );if (he ==NULL )return -ENOMEM ;
tools/perf/builtin-diff.c +4 -3
@@ -231,9 +231,10 @@ int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair, }static int hists__add_entry (struct hists *self, -struct addr_location *al,u64 period) +struct addr_location *al,u64 period, +u64 weight) { -if (__hists__add_entry (self, al,NULL , period) !=NULL ) +if (__hists__add_entry (self, al,NULL , period, weight) !=NULL )return 0 ;return -ENOMEM ; }
@@ -255,7 +256,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,if (al.filtered)return 0 ; -if (hists__add_entry (&evsel->hists, &al, sample->period)) { +if (hists__add_entry (&evsel->hists, &al, sample->period, sample->weight)) {pr_warning ("problem incrementing symbol period, skipping event\n" );return -1 ; }
tools/perf/builtin-record.c +2 -0
@@ -951,6 +951,8 @@ const struct option record_options[] = {OPT_CALLBACK ('j' ,"branch-filter" , &record.opts.branch_stack,"branch filter mask" ,"branch stack filter modes" , parse_branch_stack), +OPT_BOOLEAN ('W' ,"weight" , &record.opts.sample_weight, +"sample by weight (on special events only)" ), OPT_END() };
tools/perf/builtin-report.c +5 -3
@@ -88,7 +88,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,* and not events sampled. Thus we use a pseudo period of 1. */ he =__hists__add_branch_entry (&evsel->hists, al, parent, - &bi[i],1 ); + &bi[i],1 ,1 );if (he) {struct annotation *notes; err = -ENOMEM ;
@@ -146,7 +146,8 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel,return err; } - he =__hists__add_entry (&evsel->hists, al, parent, sample->period); + he =__hists__add_entry (&evsel->hists, al, parent, sample->period, + sample->weight);if (he ==NULL )return -ENOMEM ;
@@ -596,7 +597,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) "Use the stdio interface"),OPT_STRING ('s' ,"sort" , &sort_order,"key[,key2...]" ,"sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline," -" dso_to, dso_from, symbol_to, symbol_from, mispredict, abort, intx" ), +" dso_to, dso_from, symbol_to, symbol_from, mispredict, " +" abort, intx, weight, local_weight" ),OPT_BOOLEAN (0 ,"showcpuutilization" , &symbol_conf.show_cpu_utilization,"Show sample percentage for different cpu modes" ), OPT_STRING('p', "parent", &parent_pattern, "regex",
tools/perf/builtin-top.c +3 -2
@@ -249,7 +249,8 @@ static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel, {struct hist_entry *he; - he =__hists__add_entry (&evsel->hists, al,NULL , sample->period); + he =__hists__add_entry (&evsel->hists, al,NULL , sample->period, + sample->weight);if (he ==NULL )return NULL ;
@@ -1080,7 +1081,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)OPT_STRING ('s' ,"sort" , &sort_order,"key[,key2...]" ,"sort by key(s): pid, comm, dso, symbol, parent, dso_to," " dso_from, symbol_to, symbol_from, mispredict, srcline," -" abort, intx" ), +" abort, intx, weight, local_weight" ),OPT_BOOLEAN ('n' ,"show-nr-samples" , &symbol_conf.show_nr_samples,"Show a column with the number of samples" ), OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts,
tools/perf/perf.h +1 -0
@@ -234,6 +234,7 @@ struct perf_record_opts {bool pipe_output;bool raw_samples;bool sample_address; +bool sample_weight;bool sample_time;bool period;unsigned int freq;
tools/perf/tests/hists_link.c +2 -2
@@ -223,7 +223,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) &sample, 0) < 0) goto out; - he =__hists__add_entry (&evsel->hists, &al,NULL ,1 ); + he =__hists__add_entry (&evsel->hists, &al,NULL ,1 ,0 );if (he ==NULL ) goto out;
@@ -247,7 +247,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) &sample, 0) < 0) goto out; - he =__hists__add_entry (&evsel->hists, &al,NULL ,1 ); + he =__hists__add_entry (&evsel->hists, &al,NULL ,1 ,0 );if (he ==NULL ) goto out;
tools/perf/util/event.h +1 -0
@@ -88,6 +88,7 @@ struct perf_sample {u64 id;u64 stream_id;u64 period; +u64 weight;u32 cpu;u32 raw_size;void *raw_data;
tools/perf/util/evsel.c +10 -0
@@ -538,6 +538,9 @@ void perf_evsel__config(struct perf_evsel *evsel, attr->branch_sample_type = opts->branch_stack; } +if (opts->sample_weight) + attr->sample_type |=PERF_SAMPLE_WEIGHT ; + attr->mmap = track; attr->comm = track;
@@ -956,6 +959,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, data->cpu = data->pid = data->tid =-1 ; data->stream_id = data->id = data->time =-1ULL ; data->period =1 ; + data->weight =0 ;if (event->header.type !=PERF_RECORD_SAMPLE ) {if (!evsel->attr.sample_id_all)
@@ -1106,6 +1110,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, } } + data->weight =0 ; +if (type &PERF_SAMPLE_WEIGHT ) { + data->weight = *array; + array++; + } +return 0 ; }
tools/perf/util/hist.c +16 -7
@@ -154,9 +154,11 @@ static void hist_entry__add_cpumode_period(struct hist_entry *he, } } -static void he_stat__add_period (struct he_stat *he_stat,u64 period) +static void he_stat__add_period (struct he_stat *he_stat,u64 period, +u64 weight) { he_stat->period += period; + he_stat->weight += weight; he_stat->nr_events +=1 ; }
@@ -168,12 +170,14 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) dest->period_guest_sys += src->period_guest_sys; dest->period_guest_us += src->period_guest_us; dest->nr_events += src->nr_events; + dest->weight += src->weight; }static void hist_entry__decay (struct hist_entry *he) { he->stat.period = (he->stat.period *7 ) /8 ; he->stat.nr_events = (he->stat.nr_events *7 ) /8 ; +/* XXX need decay for weight too? */ }static bool hists__decay_entry (struct hists *hists,struct hist_entry *he)
@@ -281,7 +285,8 @@ static u8 symbol__parent_filter(const struct symbol *parent)static struct hist_entry *add_hist_entry (struct hists *hists,struct hist_entry *entry,struct addr_location *al, -u64 period) +u64 period, +u64 weight) {struct rb_node **p;struct rb_node *parent =NULL ;
@@ -305,7 +310,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists, cmp =hist_entry__cmp (he, entry);if (!cmp) { -he_stat__add_period (&he->stat, period); +he_stat__add_period (&he->stat, period, weight);/* If the map of an existing hist_entry has * become out-of-date due to an exec() or
@@ -344,7 +349,8 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self, struct addr_location *al, struct symbol *sym_parent, struct branch_info *bi, - u64 period) + u64 period, + u64 weight) { struct hist_entry entry = { .thread = al->thread,
@@ -358,6 +364,7 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self, .stat = { .period = period, .nr_events = 1, + .weight = weight, }, .parent = sym_parent, .filtered = symbol__parent_filter(sym_parent),
@@ -365,12 +372,13 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self, .hists = self, }; -return add_hist_entry (self, &entry, al, period); +return add_hist_entry (self, &entry, al, period, weight); }struct hist_entry *__hists__add_entry (struct hists *self,struct addr_location *al, -struct symbol *sym_parent,u64 period) +struct symbol *sym_parent,u64 period, +u64 weight) {struct hist_entry entry = { .thread = al->thread,
@@ -384,13 +392,14 @@ struct hist_entry *__hists__add_entry(struct hists *self, .stat = { .period = period, .nr_events = 1, + .weight = weight, }, .parent = sym_parent, .filtered = symbol__parent_filter(sym_parent), .hists = self, }; -return add_hist_entry (self, &entry, al, period); +return add_hist_entry (self, &entry, al, period, weight); }int64_t
tools/perf/util/hist.h +6 -2
@@ -51,6 +51,8 @@ enum hist_column {HISTC_DSO_FROM ,HISTC_DSO_TO ,HISTC_SRCLINE , +HISTC_LOCAL_WEIGHT , +HISTC_GLOBAL_WEIGHT , HISTC_NR_COLS, /* Last entry */ };
@@ -75,7 +77,8 @@ struct hists {struct hist_entry *__hists__add_entry (struct hists *self,struct addr_location *al, -struct symbol *parent,u64 period); +struct symbol *parent,u64 period, +u64 weight);int64_t hist_entry__cmp (struct hist_entry *left,struct hist_entry *right);int64_t hist_entry__collapse (struct hist_entry *left,struct hist_entry *right); int hist_entry__sort_snprintf(struct hist_entry *self, char *bf, size_t size,
@@ -86,7 +89,8 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self,struct addr_location *al, struct symbol *sym_parent, struct branch_info *bi, - u64 period); + u64 period, + u64 weight);void hists__output_resort (struct hists *self);void hists__output_resort_threaded (struct hists *hists);
tools/perf/util/session.c +3 -0
@@ -800,6 +800,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,if (sample_type &PERF_SAMPLE_STACK_USER )stack_user__printf (&sample->user_stack); + +if (sample_type &PERF_SAMPLE_WEIGHT ) +printf ("... weight: %" PRIu64"\n" , sample->weight); } static struct machine *
tools/perf/util/sort.c +45 -2
59 lines not on this page · raw message
tools/perf/util/sort.h +3 -0
@@ -49,6 +49,7 @@ struct he_stat {u64 period_us;u64 period_guest_sys;u64 period_guest_us; +u64 weight;u32 nr_events; };
@@ -130,6 +131,8 @@ enum sort_type {SORT_PARENT ,SORT_CPU ,SORT_SRCLINE , +SORT_LOCAL_WEIGHT , +SORT_GLOBAL_WEIGHT ,/* branch stack specific sort keys */ __SORT_BRANCH_STACK,
Signature · 1 line
1.7.7.6
PATCH 7/18 perf, core: Add generic transaction flags v3
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Add a generic qualifier for transaction events, as a new sample type that returns a flag word. This is particularly useful for qualifying aborts: to distinguish aborts which happen due to asynchronous events (like conflicts caused by another CPU) versus instructions that lead to an abort.
The tuning strategies are very different for those cases, so it's important to distinguish them easily and early.
Since it's inconvenient and inflexible to filter for this in the kernel we report all the events out and allow some post processing in user space.
The flags are based on the Intel TSX events, but should be fairly generic and mostly applicable to other architectures too. In addition to various flag words there's also reserved space to report an program supplied abort code. For TSX this is used to distinguish specific classes of aborts, like a lock busy abort when doing lock elision.
This adds the perf core glue needed for reporting the new flag word out.
v2: Add MEM/MISC
v3: Move transaction to the end
--- include/linux/perf_event.h | 2 ++ include/uapi/linux/perf_event.h | 26 ++++++++++++++++++++++++-- kernel/events/core.c | 6 ++++++ 3 files changed, 32 insertions(+), 2 deletions(-)
include/linux/perf_event.h +2 -0
@@ -589,6 +589,7 @@ struct perf_sample_data {struct perf_regs_user regs_user;u64 stack_user_size;u64 weight; +u64 transaction; }; static inline void perf_sample_data_init(struct perf_sample_data *data,
@@ -603,6 +604,7 @@ static inline void perf_sample_data_init(struct perf_sample_data *data, data->regs_user.regs =NULL ; data->stack_user_size =0 ; data->weight =0 ; + data->transaction =0 ; } extern void perf_output_sample(struct perf_output_handle *handle,
include/uapi/linux/perf_event.h +24 -2
@@ -133,9 +133,9 @@ enum perf_event_sample_format {PERF_SAMPLE_REGS_USER =1U <<12 ,PERF_SAMPLE_STACK_USER =1U <<13 ,PERF_SAMPLE_WEIGHT =1U <<14 , +PERF_SAMPLE_TRANSACTION =1U <<15 , - PERF_SAMPLE_MAX = 1U << 15, /* non-ABI */ - + PERF_SAMPLE_MAX = 1U << 16, /* non-ABI */ };/*
@@ -179,6 +179,28 @@ enum perf_sample_regs_abi { };/* +* Values for the transaction event qualifier, mostly for abort events. +*/ +enum { +PERF_SAMPLE_TXN_ELISION = (1 <<0 ),/* From elision */ +PERF_SAMPLE_TXN_TRANSACTION = (1 <<1 ),/* From transaction */ +PERF_SAMPLE_TXN_SYNC = (1 <<2 ),/* Instruction is related */ +PERF_SAMPLE_TXN_ASYNC = (1 <<3 ),/* Instruction not related */ +PERF_SAMPLE_TXN_RETRY = (1 <<4 ),/* Retry possible */ +PERF_SAMPLE_TXN_CONFLICT = (1 <<5 ),/* Conflict abort */ +PERF_SAMPLE_TXN_CAPACITY = (1 <<6 ),/* Capacity abort */ +PERF_SAMPLE_TXN_MEMORY = (1 <<7 ),/* Memory related abort */ +PERF_SAMPLE_TXN_MISC = (1 <<8 ),/* Misc aborts */ + +PERF_SAMPLE_TXN_MAX = (1 <<9 ),/* non-ABI */ + +/* bits 24..31 are reserved for the abort code */ + +PERF_SAMPLE_TXN_ABORT_MASK =0xff000000 , +PERF_SAMPLE_TXN_ABORT_SHIFT =24 , +}; + +/* * The format of the data returned by read() on a perf event fd, * as specified by attr.read_format: *
kernel/events/core.c +6 -0
@@ -955,6 +955,9 @@ static void perf_event__header_size(struct perf_event *event)if (sample_type &PERF_SAMPLE_WEIGHT ) size +=sizeof (data->weight); +if (sample_type &PERF_SAMPLE_TRANSACTION ) + size +=sizeof (data->transaction); +if (sample_type &PERF_SAMPLE_READ ) size += event->read_size;
@@ -4175,6 +4178,9 @@ void perf_output_sample(struct perf_output_handle *handle,if (sample_type &PERF_SAMPLE_WEIGHT )perf_output_put (handle, data->weight); + +if (sample_type &PERF_SAMPLE_TRANSACTION ) +perf_output_put (handle, data->transaction); } void perf_prepare_sample(struct perf_event_header *header,
Signature · 1 line
1.7.7.6
PATCH 8/18 perf, x86: Add Haswell specific transaction flag reporting
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
In the PEBS handler report the transaction flags using the new generic transaction flags facility. Most of them come from the "tsx_tuning" field in PEBSv2, but the abort code is derived from the RAX register reported in the PEBS record.
--- arch/x86/kernel/cpu/perf_event_intel_ds.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-)
arch/x86/kernel/cpu/perf_event_intel_ds.c +9 -0
@@ -677,6 +677,15 @@ static void __intel_pmu_pebs_event(struct perf_event *event, data.weight = ((struct pebs_record_v2 *)pebs)->nhm.lat; } +if ((event->attr.sample_type &PERF_SAMPLE_TRANSACTION ) && + x86_pmu.intel_cap.pebs_format >=2 ) { + data.transaction = + ((struct pebs_record_v2 *)pebs)->tsx_tuning >>32 ; +if ((data.transaction &PERF_SAMPLE_TXN_TRANSACTION ) && + (pebs->ax &1 )) + data.transaction |= pebs->ax &0xff000000 ; + } +if (has_branch_stack (event)) data.br_stack = &cpuc->lbr_stack;
Signature · 1 line
1.7.7.6
PATCH 9/18 perf, tools: Add support for record transaction flags v3
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Add the glue in the user tools to record transaction flags with --transaction (-T was already taken) and dump them.
Followon patches will use them.
v2: Fix manpage
v3: Move transaction to the end
--- tools/perf/Documentation/perf-record.txt | 4 +++- tools/perf/builtin-record.c | 2 ++ tools/perf/perf.h | 1 + tools/perf/util/event.h | 1 + tools/perf/util/evsel.c | 9 +++++++++ tools/perf/util/session.c | 3 +++ 6 files changed, 19 insertions(+), 1 deletions(-)
tools/perf/Documentation/perf-record.txt +3 -1
@@ -185,12 +185,14 @@ is enabled for all the sampling events. The sampled branch type is the same for The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k Note that this feature may not be available on all processors. --W:: --weight:: Enable weightened sampling. An additional weight is recorded per sample and can be displayed with the weight and local_weight sort keys. This currently works for TSX abort events and some memory events in precise mode on modern Intel CPUs. +--transaction:: +Record transaction flags for transaction related events. + SEE ALSO -------- linkperf:perf-stat[1], linkperf:perf-list[1]
tools/perf/builtin-record.c +2 -0
@@ -953,6 +953,8 @@ const struct option record_options[] = { parse_branch_stack),OPT_BOOLEAN ('W' ,"weight" , &record.opts.sample_weight,"sample by weight (on special events only)" ), +OPT_BOOLEAN (0 ,"transaction" , &record.opts.sample_transaction, +"sample transaction flags (special events only)" ), OPT_END() };
tools/perf/perf.h +1 -0
@@ -244,6 +244,7 @@ struct perf_record_opts {u64 default_interval;u64 user_interval;u16 stack_dump_size; + bool sample_transaction; };#endif
tools/perf/util/event.h +1 -0
@@ -89,6 +89,7 @@ struct perf_sample {u64 stream_id;u64 period;u64 weight; +u64 transaction;u32 cpu;u32 raw_size;void *raw_data;
tools/perf/util/evsel.c +9 -0
@@ -541,6 +541,9 @@ void perf_evsel__config(struct perf_evsel *evsel,if (opts->sample_weight) attr->sample_type |=PERF_SAMPLE_WEIGHT ; +if (opts->sample_transaction) + attr->sample_type |=PERF_SAMPLE_TRANSACTION ; + attr->mmap = track; attr->comm = track;
@@ -1116,6 +1119,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, array++; } + data->transaction =0 ; +if (type &PERF_SAMPLE_TRANSACTION ) { + data->transaction = *array; + array++; + } +return 0 ; }
tools/perf/util/session.c +3 -0
@@ -803,6 +803,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,if (sample_type &PERF_SAMPLE_WEIGHT )printf ("... weight: %" PRIu64"\n" , sample->weight); + +if (sample_type &PERF_SAMPLE_TRANSACTION ) +printf ("... transaction: %" PRIx64"\n" , sample->transaction); } static struct machine *
Signature · 1 line
1.7.7.6
PATCH 10/18 perf, tools: Add browser support for transaction flags v6
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Add histogram support for the transaction flags. Each flags instance becomes a separate histogram. Support sorting and displaying the flags in report and top.
The patch is fairly large, but it's really mostly just plumbing to pass the flags around.
v2: Increase column. Fix flags decoding. Use longer strings for flags to be more user friendly.
v3: Fix WERROR=1 build. Tidy display
v4: Readd sort keys to manpage
v5: Reimplement transaction flags display code
v6: Port to latest tree
--- tools/perf/Documentation/perf-report.txt | 1 + tools/perf/Documentation/perf-top.txt | 2 +- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-diff.c | 8 ++- tools/perf/builtin-report.c | 4 +- tools/perf/builtin-top.c | 4 +- tools/perf/tests/hists_link.c | 4 +- tools/perf/util/hist.c | 7 +++- tools/perf/util/hist.h | 4 +- tools/perf/util/sort.c | 73 ++++++++++++++++++++++++++++++ tools/perf/util/sort.h | 2 + 11 files changed, 98 insertions(+), 13 deletions(-)
tools/perf/Documentation/perf-report.txt +1 -0
@@ -75,6 +75,7 @@ OPTIONS - weight: Event specific weight, e.g. memory latency or transaction abort cost. This is the global weight. - local_weight: Local weight version of the weight above. + - transaction: Transaction abort flags. By default, comm, dso and symbol keys are used. (i.e. --sort comm,dso,symbol)
tools/perf/Documentation/perf-top.txt +1 -1
@@ -114,7 +114,7 @@ Default is to monitor all CPUS. --sort:: Sort by key(s): pid, comm, dso, symbol, parent, srcline, dso_from, dso_to, symbol_to, symbol_from, mispredict, - abort, intx, local_weight, weight + abort, intx, local_weight, weight, transaction -n:: --show-nr-samples::
tools/perf/builtin-annotate.c +1 -1
@@ -62,7 +62,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,return 0 ; } - he =__hists__add_entry (&evsel->hists, al,NULL ,1 ,1 ); + he =__hists__add_entry (&evsel->hists, al,NULL ,1 ,1 ,0 );if (he ==NULL )return -ENOMEM ;
tools/perf/builtin-diff.c +5 -3
@@ -232,9 +232,10 @@ int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair,static int hists__add_entry (struct hists *self,struct addr_location *al,u64 period, -u64 weight) +u64 weight,u64 transaction) { -if (__hists__add_entry (self, al,NULL , period, weight) !=NULL ) +if (__hists__add_entry (self, al,NULL , period, weight, transaction) + !=NULL )return 0 ;return -ENOMEM ; }
@@ -256,7 +257,8 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,if (al.filtered)return 0 ; -if (hists__add_entry (&evsel->hists, &al, sample->period, sample->weight)) { +if (hists__add_entry (&evsel->hists, &al, sample->period, sample->weight, + sample->transaction)) {pr_warning ("problem incrementing symbol period, skipping event\n" );return -1 ; }
tools/perf/builtin-report.c +2 -2
@@ -147,7 +147,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel, } he =__hists__add_entry (&evsel->hists, al, parent, sample->period, - sample->weight); + sample->weight, sample->transaction);if (he ==NULL )return -ENOMEM ;
@@ -598,7 +598,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)OPT_STRING ('s' ,"sort" , &sort_order,"key[,key2...]" ,"sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline," " dso_to, dso_from, symbol_to, symbol_from, mispredict, " -" abort, intx, weight, local_weight" ), +" abort, intx, weight, local_weight, transaction" ),OPT_BOOLEAN (0 ,"showcpuutilization" , &symbol_conf.show_cpu_utilization,"Show sample percentage for different cpu modes" ), OPT_STRING('p', "parent", &parent_pattern, "regex",
tools/perf/builtin-top.c +2 -2
@@ -250,7 +250,7 @@ static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel,struct hist_entry *he; he =__hists__add_entry (&evsel->hists, al,NULL , sample->period, - sample->weight); + sample->weight, sample->transaction);if (he ==NULL )return NULL ;
@@ -1081,7 +1081,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)OPT_STRING ('s' ,"sort" , &sort_order,"key[,key2...]" ,"sort by key(s): pid, comm, dso, symbol, parent, dso_to," " dso_from, symbol_to, symbol_from, mispredict, srcline," -" abort, intx, weight, local_weight" ), +" abort, intx, weight, local_weight, transaction" ),OPT_BOOLEAN ('n' ,"show-nr-samples" , &symbol_conf.show_nr_samples,"Show a column with the number of samples" ), OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts,
tools/perf/tests/hists_link.c +2 -2
@@ -223,7 +223,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) &sample, 0) < 0) goto out; - he =__hists__add_entry (&evsel->hists, &al,NULL ,1 ,0 ); + he =__hists__add_entry (&evsel->hists, &al,NULL ,1 ,0 ,0 );if (he ==NULL ) goto out;
@@ -247,7 +247,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) &sample, 0) < 0) goto out; - he =__hists__add_entry (&evsel->hists, &al,NULL ,1 ,0 ); + he =__hists__add_entry (&evsel->hists, &al,NULL ,1 ,0 ,0 );if (he ==NULL ) goto out;
tools/perf/util/hist.c +6 -1
@@ -115,6 +115,10 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)hists__set_unres_dso_col_len (hists,HISTC_DSO_TO ); } } + +if (h->transaction) +hists__new_col_len (hists,HISTC_TRANSACTION , +hist_entry__transaction_len ()); }void hists__output_recalc_col_len (struct hists *hists,int max_rows)
@@ -378,7 +382,7 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self,struct hist_entry *__hists__add_entry (struct hists *self,struct addr_location *al,struct symbol *sym_parent,u64 period, -u64 weight) +u64 weight,u64 transaction) {struct hist_entry entry = { .thread = al->thread,
@@ -397,6 +401,7 @@ struct hist_entry *__hists__add_entry(struct hists *self, .parent = sym_parent, .filtered = symbol__parent_filter(sym_parent), .hists = self, + .transaction = transaction, };return add_hist_entry (self, &entry, al, period, weight);
tools/perf/util/hist.h +3 -1
@@ -53,6 +53,7 @@ enum hist_column {HISTC_SRCLINE ,HISTC_LOCAL_WEIGHT ,HISTC_GLOBAL_WEIGHT , +HISTC_TRANSACTION , HISTC_NR_COLS, /* Last entry */ };
@@ -78,9 +79,10 @@ struct hists {struct hist_entry *__hists__add_entry (struct hists *self,struct addr_location *al,struct symbol *parent,u64 period, -u64 weight); +u64 weight,u64 transaction);int64_t hist_entry__cmp (struct hist_entry *left,struct hist_entry *right);int64_t hist_entry__collapse (struct hist_entry *left,struct hist_entry *right); +int hist_entry__transaction_len (void );int hist_entry__sort_snprintf (struct hist_entry *self,char *bf,size_t size,struct hists *hists);void hist_entry__free (struct hist_entry *);
tools/perf/util/sort.c +73 -0
85 lines not on this page · raw message
tools/perf/util/sort.h +2 -0
@@ -83,6 +83,7 @@ struct hist_entry {struct map_symbol ms;struct thread *thread;u64 ip; +u64 transaction;s32 cpu;struct hist_entry_diff diff;
@@ -133,6 +134,7 @@ enum sort_type {SORT_SRCLINE ,SORT_LOCAL_WEIGHT ,SORT_GLOBAL_WEIGHT , +SORT_TRANSACTION ,/* branch stack specific sort keys */ __SORT_BRANCH_STACK,
Signature · 1 line
1.7.7.6
PATCH 11/18 tools, perf: Add a precise event qualifier v2
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Add a precise qualifier, like cpu/event=0x3c,precise=1/
This is needed so that the kernel can request enabling PEBS for TSX events. The parser bails out on any sysfs parse errors, so this is needed in any case to handle any event on the TSX perf kernel.
v2: Allow 3 as value
--- tools/perf/util/parse-events.c | 6 ++++++ tools/perf/util/parse-events.h | 1 + tools/perf/util/parse-events.l | 1 + 3 files changed, 8 insertions(+), 0 deletions(-)
tools/perf/util/parse-events.c +6 -0
@@ -568,6 +568,12 @@ do { \case PARSE_EVENTS__TERM_TYPE_NAME :CHECK_TYPE_VAL (STR );break ; +case PARSE_EVENTS__TERM_TYPE_PRECISE : +CHECK_TYPE_VAL (NUM ); +if ((unsigned )term->val.num >3 ) +return -EINVAL ; + attr->precise_ip = term->val.num; +break ;default :return -EINVAL ; }
tools/perf/util/parse-events.h +1 -0
@@ -48,6 +48,7 @@ enum {PARSE_EVENTS__TERM_TYPE_NAME ,PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD ,PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE , + PARSE_EVENTS__TERM_TYPE_PRECISE, }; struct parse_events_term {
tools/perf/util/parse-events.l +1 -0
@@ -169,6 +169,7 @@ period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } , { return ','; } "/" { BEGIN(INITIAL); return '/'; } +precise { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_PRECISE); } {name_minus} { return str(yyscanner, PE_NAME); } }
Signature · 1 line
1.7.7.6
PATCH 12/18 perf, x86: improve sysfs event mapping with event string
In reply to Andi KleenFrom: Stephane Eranian <[email protected]>
This patch extends Jiri's changes to make generic events mapping visible via sysfs. The patch extends the mechanism to non-generic events by allowing the mappings to be hardcoded in strings.
This mechanism will be used by the PEBS-LL patch
later on.
--- arch/x86/kernel/cpu/perf_event.c | 28 +++++++++++++--------------- arch/x86/kernel/cpu/perf_event.h | 26 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 15 deletions(-)
arch/x86/kernel/cpu/perf_event.c +13 -15
@@ -1310,20 +1310,22 @@ static struct attribute_group x86_pmu_format_group = { .attrs = NULL, }; -struct perf_pmu_events_attr { -struct device_attribute attr; -u64 id; -}; -/* * Remove all undefined events (x86_pmu.event_map(id) == 0) * out of events_attr attributes. */ static void __init filter_events (struct attribute **attrs) { +struct device_attribute *d; +struct perf_pmu_events_attr *pmu_attr;int i, j;for (i =0 ; attrs[i]; i++) { + d = (struct device_attribute *)attrs[i]; + pmu_attr = container_of(d, struct perf_pmu_events_attr, attr); +/* str trumps id */ +if (pmu_attr->event_str) +continue ;if (x86_pmu.event_map (i))continue ;
@@ -1335,24 +1337,20 @@ static void __init filter_events(struct attribute **attrs) } } -static ssize_t events_sysfs_show (struct device *dev,struct device_attribute *attr, +ssize_t events_sysfs_show (struct device *dev,struct device_attribute *attr,char *page) {struct perf_pmu_events_attr *pmu_attr = \ container_of(attr, struct perf_pmu_events_attr, attr);u64 config = x86_pmu.event_map (pmu_attr->id); -return x86_pmu.events_sysfs_show (page, config); -} -#define EVENT_VAR (_id) event_attr_##_id -#define EVENT_PTR (_id) &event_attr_##_id.attr.attr +/* string trumps id */ +if (pmu_attr->event_str) +return sprintf (page,"%s" , pmu_attr->event_str); -#define EVENT_ATTR (_name, _id) \ -static struct perf_pmu_events_attr EVENT_VAR(_id) = { \ - .attr = __ATTR(_name, 0444, events_sysfs_show, NULL), \ - .id = PERF_COUNT_HW_##_id, \ -}; +return x86_pmu.events_sysfs_show (page, config); +}EVENT_ATTR (cpu-cycles,CPU_CYCLES );EVENT_ATTR (instructions,INSTRUCTIONS );
arch/x86/kernel/cpu/perf_event.h +26 -0
@@ -425,6 +425,29 @@ do { \#define ERF_NO_HT_SHARING 1#define ERF_HAS_RSP_1 2 +#define EVENT_VAR (_id) event_attr_##_id +#define EVENT_PTR (_id) &event_attr_##_id.attr.attr + +#define EVENT_ATTR (_name, _id) \ +static struct perf_pmu_events_attr EVENT_VAR(_id) = { \ + .attr = __ATTR(_name, 0444, events_sysfs_show, NULL), \ + .id = PERF_COUNT_HW_##_id, \ + .event_str = NULL, \ +}; + +#define EVENT_ATTR_STR (_name, v, str) \ +static struct perf_pmu_events_attr event_attr_##v = { \ + .attr = __ATTR(_name, 0444, events_sysfs_show, NULL),\ + .id = 0, \ + .event_str = str, \ +}; + +struct perf_pmu_events_attr { +struct device_attribute attr; +u64 id; +const char *event_str; +}; +extern struct x86_pmu x86_pmu__read_mostly ; DECLARE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
@@ -643,6 +666,9 @@ int p6_pmu_init(void);int knc_pmu_init (void ); +ssize_t events_sysfs_show (struct device *dev,struct device_attribute *attr, +char *page); +#else /* CONFIG_CPU_SUP_INTEL */ static inline void reserve_ds_buffers (void )
Signature · 1 line
1.7.7.6
PATCH 13/18 perf, x86: Support CPU specific sysfs events
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Add a way for the CPU initialization code to register additional events, and merge them into the events attribute directory. Used in the next patch.
--- arch/x86/kernel/cpu/perf_event.c | 29 +++++++++++++++++++++++++++++ arch/x86/kernel/cpu/perf_event.h | 1 + 2 files changed, 30 insertions(+), 0 deletions(-)
arch/x86/kernel/cpu/perf_event.c +29 -0
@@ -1337,6 +1337,30 @@ static void __init filter_events(struct attribute **attrs) } } +/* Merge two pointer arrays */ +static __init struct attribute **merge_attr (struct attribute **a, +struct attribute **b) +{ +struct attribute **new; +int j, i; + +for (j =0 ; a[j]; j++) + ; +for (i =0 ; b[i]; i++) + j++; + j++; + new =kmalloc (sizeof (struct attribute *) * j,GFP_KERNEL ); +if (!new) +return a; + j =0 ; +for (i =0 ; a[i]; i++) + new[j++] = a[i]; +for (i =0 ; b[i]; i++) + new[j++] = b[i]; + new[j] =NULL ; +return new; +} +ssize_t events_sysfs_show (struct device *dev,struct device_attribute *attr,char *page) {
@@ -1474,6 +1498,11 @@ static int __init init_hw_perf_events(void)else filter_events (x86_pmu_events_group.attrs); +if (x86_pmu.cpu_events) + x86_pmu_events_group.attrs = +merge_attr (x86_pmu_events_group.attrs, + x86_pmu.cpu_events); +pr_info ("... version: %d\n" , x86_pmu.version);pr_info ("... bit width: %d\n" , x86_pmu.cntval_bits);pr_info ("... generic registers: %d\n" , x86_pmu.num_counters);
arch/x86/kernel/cpu/perf_event.h +1 -0
@@ -360,6 +360,7 @@ struct x86_pmu {struct attribute **format_attrs;ssize_t (*events_sysfs_show)(char *page,u64 config); +struct attribute **cpu_events;/* * CPU Hotplug hooks
Signature · 1 line
1.7.7.6
PATCH 14/18 perf, x86: Add Haswell TSX event aliases v2
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Add infrastructure to generate event aliases in /sys/devices/cpu/events/
And use this to set up user friendly aliases for the common TSX events. TSX tuning relies heavily on the PMU, so it's important to be user friendly.
This replaces the generic transaction events in an earlier version of this patchkit.
tx-start/commit/abort to count RTM transactions
el-start/commit/abort to count HLE ("elision") transactions
tx-conflict/overflow to count conflict/overflow for both combined.The general abort events exist in precise and non precise variants Since the common case is sampling plain "tx-aborts" in precise.
This is very important because abort sampling only really works with PEBS enabled, otherwise it would report the IP after the abort, not the abort point. But counting with PEBS has more overhead, so also have tx/el-abort-count aliases that do not enable PEBS for perf stat.
It would be nice to switch automatically between those two, like in the previous version, but that would need more new infrastructure for sysfs first.
There is an tx-abort<->tx-aborts alias too, because I found myself using both variants.
Also added friendly aliases for cpu/cycles,intx=1/ and cpu/cycles,intx=1,intx_cp=1/ and the same for instructions. These will be used by perf stat -T, and are also useful for users directly.
So for example to get transactional cycles can use "perf stat -e cycles-t"
v2: Move to new sysfs infrastructure
--- arch/x86/kernel/cpu/perf_event_intel.c | 47 ++++++++++++++++++++++++++++++++ 1 files changed, 47 insertions(+), 0 deletions(-)
arch/x86/kernel/cpu/perf_event_intel.c +47 -0
@@ -2004,6 +2004,52 @@ static __init void intel_nehalem_quirk(void) } } +/* Haswell special events */ +EVENT_ATTR_STR (tx-start, tx_start,"event=0xc9,umask=0x1" ); +EVENT_ATTR_STR (tx-commit, tx_commit,"event=0xc9,umask=0x2" ); +EVENT_ATTR_STR (tx-abort, tx_abort,"event=0xc9,umask=0x4,precise=2" ); +EVENT_ATTR_STR (tx-abort-count, tx_abort_count,"event=0xc9,umask=0x4" ); +/* alias */ +EVENT_ATTR_STR (tx-aborts, tx_aborts,"event=0xc9,umask=0x4,precise=2" ); +EVENT_ATTR_STR (tx-capacity, tx_capacity,"event=0x54,umask=0x2" ); +EVENT_ATTR_STR (tx-conflict, tx_conflict,"event=0x54,umask=0x1" ); +EVENT_ATTR_STR (el-start, el_start,"event=0xc8,umask=0x1" ); +EVENT_ATTR_STR (el-commit, el_commit,"event=0xc8,umask=0x2" ); +EVENT_ATTR_STR (el-abort, el_abort,"event=0xc8,umask=0x4,precise=2" ); +EVENT_ATTR_STR (el-abort-count, el_abort_count,"event=0xc8,umask=0x4" ); +/* alias */ +EVENT_ATTR_STR (el-aborts, el_aborts,"event=0xc8,umask=0x4,precise=2" ); +/* shared with tx-* */ +EVENT_ATTR_STR (el-capacity, el_capacity,"event=0x54,umask=0x2" ); +/* shared with tx-* */ +EVENT_ATTR_STR (el-conflict, el_conflict,"event=0x54,umask=0x1" ); +EVENT_ATTR_STR (cycles-t, cycles_t,"event=0x3c,intx=1" ); +EVENT_ATTR_STR (cycles-ct, cycles_ct,"event=0x3c,intx=1,intx_cp=1" ); +EVENT_ATTR_STR (instructions-t, instructions_t,"event=0xc0,intx=1" ); +EVENT_ATTR_STR (instructions-ct,instructions_ct,"event=0xc0,intx=1,intx_cp=1" ); + +static struct attribute *hsw_events_attrs[] = { +EVENT_PTR (tx_start), +EVENT_PTR (tx_commit), +EVENT_PTR (tx_abort), +EVENT_PTR (tx_aborts), +EVENT_PTR (tx_abort_count), +EVENT_PTR (tx_capacity), +EVENT_PTR (tx_conflict), +EVENT_PTR (el_start), +EVENT_PTR (el_commit), +EVENT_PTR (el_abort), +EVENT_PTR (el_aborts), +EVENT_PTR (el_abort_count), +EVENT_PTR (el_capacity), +EVENT_PTR (el_conflict), +EVENT_PTR (cycles_t), +EVENT_PTR (cycles_ct), +EVENT_PTR (instructions_t), +EVENT_PTR (instructions_ct), +NULL +}; +__init int intel_pmu_init (void ) {union cpuid10_edx edx;
@@ -2229,6 +2275,7 @@ __init int intel_pmu_init(void) x86_pmu.get_event_constraints = hsw_get_event_constraints; x86_pmu.format_attrs = intel_hsw_formats_attr; x86_pmu.memory_lat_events = intel_hsw_memory_latency_events; + x86_pmu.cpu_events = hsw_events_attrs;pr_cont ("Haswell events, " );break ;
Signature · 1 line
1.7.7.6
PATCH 15/18 perf, tools: Add perf stat --transaction v3
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Add support to perf stat to print the basic transactional execution statistics:
Total cycles, Cycles in Transaction, Cycles in aborted transsactions using the intx and intx_checkpoint qualifiers.
Transaction Starts and Elision Starts, to compute the average transaction length.
This is a reasonable overview over the success of the transactions.
Enable with a new --transaction / -T option.
This requires measuring these events in a group, since they depend on each other.
This is implemented by using TM sysfs events exported by the kernel
v2: Only print the extended statistics when the option is enabled. This avoids negative output when the user specifies the -T events in separate groups.
v3: Port to latest tree
--- tools/perf/Documentation/perf-stat.txt | 4 + tools/perf/builtin-stat.c | 101 +++++++++++++++++++++++++++++++- tools/perf/util/evsel.h | 6 ++ 3 files changed, 108 insertions(+), 3 deletions(-)
tools/perf/Documentation/perf-stat.txt +4 -0
@@ -114,6 +114,10 @@ with it. --append may be used here. Examples: perf stat --repeat 10 --null --sync --pre 'make -s O=defconfig-build/clean' -- make -s -j64 O=defconfig-build/ bzImage +-T:: +--transaction:: + +Print statistics of transactional execution if supported. EXAMPLES --------
tools/perf/builtin-stat.c +98 -3
156 lines not on this page · raw message
tools/perf/util/evsel.h +6 -0
@@ -171,6 +171,12 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1, (e1->attr.config == e2->attr.config); } +#define perf_evsel__cmp (a, b) \ + ((a) && \ + (b) && \ + (a)->attr.type == (b)->attr.type && \ + (a)->attr.config == (b)->attr.config) +int __perf_evsel__read_on_cpu (struct perf_evsel *evsel,int cpu,int thread,bool scale);
Signature · 1 line
1.7.7.6
PATCH 16/18 perf, x86: Add a Haswell precise instructions event v2
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Add a instructions-p event alias that uses the PDIR randomized instruction retirement event. This is useful to avoid some systematic sampling shadow problems. Normally PEBS sampling has a systematic shadow. With PDIR enabled the hardware adds some randomization that statistically avoids this problem. In this sense, it's more precise over a whole sampling interval, but an individual sample can be less precise. But since we sample overall it's a more precise event.
This could be used before using the explicit event code syntax, but it's easier and more user friendly to use with an "instructions-p" alias. I expect this will eventually become a common use case.
Right now for Haswell, will add to Ivy Bridge later too.
v2: Use new sysfs infrastructure
--- arch/x86/kernel/cpu/perf_event_intel.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
arch/x86/kernel/cpu/perf_event_intel.c +2 -0
@@ -2027,6 +2027,7 @@ EVENT_ATTR_STR(cycles-t, cycles_t, "event=0x3c,intx=1");EVENT_ATTR_STR (cycles-ct, cycles_ct,"event=0x3c,intx=1,intx_cp=1" );EVENT_ATTR_STR (instructions-t, instructions_t,"event=0xc0,intx=1" );EVENT_ATTR_STR (instructions-ct,instructions_ct,"event=0xc0,intx=1,intx_cp=1" ); +EVENT_ATTR_STR (instructions-p, instructions_p,"event=0xc0,umask=0x01,precise=2" );static struct attribute *hsw_events_attrs[] = {EVENT_PTR (tx_start),
@@ -2047,6 +2048,7 @@ static struct attribute *hsw_events_attrs[] = {EVENT_PTR (cycles_ct),EVENT_PTR (instructions_t),EVENT_PTR (instructions_ct), +EVENT_PTR (instructions_p), NULL };
Signature · 1 line
1.7.7.6
PATCH 17/18 perf, tools: Default to cpu// for events v5
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
When an event fails to parse and it's not in a new style format, try to parse it again as a cpu event.
This allows to use sysfs exported events directly without //, so I can use
perf record -e tx-aborts ...
instead of
perf record -e cpu/tx-aborts/
v2: Handle multiple events
v3: Move to separate function
v4: Move library function to util/string.c
v5: Handle unhandleable errors
--- tools/perf/util/include/linux/string.h | 1 + tools/perf/util/parse-events.c | 32 ++++++++++++++++++++++++++++++-- tools/perf/util/string.c | 25 +++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-)
tools/perf/util/include/linux/string.h +1 -0
@@ -1,3 +1,4 @@#include <string.h> void *memdup (const void *src,size_t len); +int str_append (char **s,int *len,const char *a);
tools/perf/util/parse-events.c +30 -2
@@ -6,7 +6,7 @@#include "parse-options.h" #include "parse-events.h" #include "exec_cmd.h" -#include "string.h" +#include "linux/string.h" #include "symbol.h" #include "cache.h" #include "header.h"
@@ -834,6 +834,32 @@ int parse_events_name(struct list_head *list, char *name)return 0 ; } +static int parse_events__scanner (const char *str,void *data,int start_token); + +static int parse_events_fixup (int ret,const char *str,void *data, +int start_token) +{ +char *o =strdup (str); +char *s =NULL ; +char *t = o; +char *p; +int len =0 ; + +if (!o) +return ret; +while ((p =strsep (&t,"," )) !=NULL ) { +if (s) +str_append (&s, &len,"," ); +str_append (&s, &len,"cpu/" ); +str_append (&s, &len, p); +str_append (&s, &len,"/" ); + } +free (o); +if (!s) +return -ENOMEM ; +return parse_events__scanner (s, data, start_token); +} +static int parse_events__scanner (const char *str,void *data,int start_token) {YY_BUFFER_STATE buffer;
@@ -854,7 +880,9 @@ static int parse_events__scanner(const char *str, void *data, int start_token)parse_events__flush_buffer (buffer, scanner);parse_events__delete_buffer (buffer, scanner);parse_events_lex_destroy (scanner); -return ret; +if (ret && !strchr (str,'/' )) + ret =parse_events_fixup (ret, str, data, start_token); +return ret; }/*
tools/perf/util/string.c +25 -0
@@ -387,3 +387,28 @@ void *memdup(const void *src, size_t len)return p; } + +/** +* str_append - reallocate string and append another +* @s: pointer to string pointer +* @len: pointer to len (initialized) +* @a: string to append. +* Also allow the caller to mishandle unhandleable errors. +*/ +int str_append (char **s,int *len,const char *a) +{ +int olen = *s ?strlen (*s) :0 ; +int nlen = olen +strlen (a) +1 ; +if (*len < nlen) { + *len = *len *2 ; +if (*len < nlen) + *len = nlen; + *s =realloc (*s, *len); +if (!*s) +return -ENOMEM ; +if (olen ==0 ) + **s =0 ; + } +strcat (*s, a); +return 0 ; +}
Signature · 1 line
1.7.7.6
PATCH 18/18 perf, tools: List kernel supplied event aliases in perf list v3
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
List the kernel supplied pmu event aliases in perf list
It's better when the users can actually see them.
v2: Fix pattern matching
v3: perf_pmu__alias -> perf_pmu_alias
--- tools/perf/Documentation/perf-list.txt | 4 +- tools/perf/builtin-list.c | 3 + tools/perf/util/parse-events.c | 5 ++- tools/perf/util/pmu.c | 73 ++++++++++++++++++++++++++++++++ tools/perf/util/pmu.h | 3 + 5 files changed, 86 insertions(+), 2 deletions(-)
tools/perf/Documentation/perf-list.txt +3 -1
@@ -8,7 +8,7 @@ perf-list - List all symbolic event types SYNOPSIS -------- [verse] -'perf list' [hw|sw|cache|tracepoint|event_glob] +'perf list' [hw|sw|cache|tracepoint|pmu|event_glob] DESCRIPTION -----------
@@ -104,6 +104,8 @@ To limit the list use: 'subsys_glob:event_glob' to filter by tracepoint subsystems such as sched, block, etc. +. 'pmu' to print the kernel supplied PMU events. + . If none of the above is matched, it will apply the supplied glob to all events, printing the ones that match.
tools/perf/builtin-list.c +3 -0
@@ -13,6 +13,7 @@#include "util/parse-events.h" #include "util/cache.h" +#include "util/pmu.h" int cmd_list (int argc,const char **argv,const char *prefix__maybe_unused ) {
@@ -37,6 +38,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)else if (strcmp (argv[i],"cache" ) ==0 ||strcmp (argv[i],"hwcache" ) ==0 )print_hwcache_events (NULL , false); +else if (strcmp (argv[i],"pmu" ) ==0 ) +print_pmu_events (NULL , false);else if (strcmp (argv[i],"--raw-dump" ) ==0 )print_events (NULL , true);else {
tools/perf/util/parse-events.c +4 -1
@@ -1119,6 +1119,8 @@ int print_hwcache_events(const char *event_glob, bool name_only) } } +if (printed) +printf ("\n" );return printed; }
@@ -1173,11 +1175,12 @@ void print_events(const char *event_glob, bool name_only)print_hwcache_events (event_glob, name_only); +print_pmu_events (event_glob, name_only); +if (event_glob !=NULL )return ;if (!name_only) { -printf ("\n" );printf (" %-50s [%s]\n" ,"rNNN" , event_type_descriptors[PERF_TYPE_RAW ]);
tools/perf/util/pmu.c +73 -0
76 lines not on this page · raw message
tools/perf/util/pmu.h +3 -0
@@ -3,6 +3,7 @@#include <linux/bitops.h> #include <linux/perf_event.h> +#include <stdbool.h> enum {PERF_PMU_FORMAT_VALUE_CONFIG ,
@@ -40,5 +41,7 @@ int perf_pmu__format_parse(char *dir, struct list_head *head);struct perf_pmu *perf_pmu__scan (struct perf_pmu *pmu); +void print_pmu_events (const char *event_glob,bool name_only); +int perf_pmu__test (void );#endif /* __PMU_H */
Signature · 1 line
1.7.7.6