Messages in this thread Patch in this message |  | | From | Andi Kleen <> | Subject | [PATCH 09/29] perf, x86: Support LBR filtering by INTX/NOTX/ABORT v2 | Date | Thu, 17 Jan 2013 12:36:32 -0800 |
| |
From: Andi Kleen <ak@linux.intel.com>
Add LBR filtering for branch in transaction, branch not in transaction or transaction abort. This is exposed as new sample types.
v2: Rename ABORT to ABORTTX Signed-off-by: Andi Kleen <ak@linux.intel.com> --- arch/x86/kernel/cpu/perf_event_intel_lbr.c | 31 +++++++++++++++++++++++++-- include/uapi/linux/perf_event.h | 5 +++- 2 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c index ad5af13..5455a00 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c +++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c @@ -85,9 +85,13 @@ enum { X86_BR_JMP = 1 << 9, /* jump */ X86_BR_IRQ = 1 << 10,/* hw interrupt or trap or fault */ X86_BR_IND_CALL = 1 << 11,/* indirect calls */ + X86_BR_ABORT = 1 << 12,/* transaction abort */ + X86_BR_INTX = 1 << 13,/* in transaction */ + X86_BR_NOTX = 1 << 14,/* not in transaction */ }; #define X86_BR_PLM (X86_BR_USER | X86_BR_KERNEL) +#define X86_BR_ANYTX (X86_BR_NOTX | X86_BR_INTX) #define X86_BR_ANY \ (X86_BR_CALL |\ @@ -99,6 +103,7 @@ enum { X86_BR_JCC |\ X86_BR_JMP |\ X86_BR_IRQ |\ + X86_BR_ABORT |\ X86_BR_IND_CALL) #define X86_BR_ALL (X86_BR_PLM | X86_BR_ANY) @@ -347,6 +352,16 @@ static void intel_pmu_setup_sw_lbr_filter(struct perf_event *event) if (br_type & PERF_SAMPLE_BRANCH_IND_CALL) mask |= X86_BR_IND_CALL; + + if (br_type & PERF_SAMPLE_BRANCH_ABORTTX) + mask |= X86_BR_ABORT; + + if (br_type & PERF_SAMPLE_BRANCH_INTX) + mask |= X86_BR_INTX; + + if (br_type & PERF_SAMPLE_BRANCH_NOTX) + mask |= X86_BR_NOTX; + /* * stash actual user request into reg, it may * be used by fixup code for some CPU @@ -393,7 +408,8 @@ int intel_pmu_setup_lbr_filter(struct perf_event *event) /* * no LBR on this PMU */ - if (!x86_pmu.lbr_nr || x86_pmu.intel_cap.lbr_format > LBR_FORMAT_MAX_KNOWN) + if (!x86_pmu.lbr_nr || + x86_pmu.intel_cap.lbr_format > LBR_FORMAT_MAX_KNOWN) return -EOPNOTSUPP; /* @@ -421,7 +437,7 @@ int intel_pmu_setup_lbr_filter(struct perf_event *event) * decoded (e.g., text page not present), then X86_BR_NONE is * returned. */ -static int branch_type(unsigned long from, unsigned long to) +static int branch_type(unsigned long from, unsigned long to, int abort) { struct insn insn; void *addr; @@ -441,6 +457,9 @@ static int branch_type(unsigned long from, unsigned long to) if (from == 0 || to == 0) return X86_BR_NONE; + if (abort) + return X86_BR_ABORT | to_plm; + if (from_plm == X86_BR_USER) { /* * can happen if measuring at the user level only @@ -577,7 +596,13 @@ intel_pmu_lbr_filter(struct cpu_hw_events *cpuc) from = cpuc->lbr_entries[i].from; to = cpuc->lbr_entries[i].to; - type = branch_type(from, to); + type = branch_type(from, to, cpuc->lbr_entries[i].abort); + if (type != X86_BR_NONE && (br_sel & X86_BR_ANYTX)) { + if (cpuc->lbr_entries[i].intx) + type |= X86_BR_INTX; + else + type |= X86_BR_NOTX; + } /* if type does not correspond, then discard */ if (type == X86_BR_NONE || (br_sel & type) != type) { diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index 4f63c05..8e38823 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h @@ -155,8 +155,11 @@ enum perf_branch_sample_type { PERF_SAMPLE_BRANCH_ANY_CALL = 1U << 4, /* any call branch */ PERF_SAMPLE_BRANCH_ANY_RETURN = 1U << 5, /* any return branch */ PERF_SAMPLE_BRANCH_IND_CALL = 1U << 6, /* indirect calls */ + PERF_SAMPLE_BRANCH_ABORTTX = 1U << 7, /* transaction aborts */ + PERF_SAMPLE_BRANCH_INTX = 1U << 8, /* in transaction (flag) */ + PERF_SAMPLE_BRANCH_NOTX = 1U << 9, /* not in transaction (flag) */ - PERF_SAMPLE_BRANCH_MAX = 1U << 7, /* non-ABI */ + PERF_SAMPLE_BRANCH_MAX = 1U << 10, /* non-ABI */ }; #define PERF_SAMPLE_BRANCH_PLM_ALL \ -- 1.7.7.6
|  |