perf, x86: use LBR for PEBS IP+1 fixup
Use the LBR to fix up the PEBS IP+1 issue. As said, PEBS reports the next instruction, here we use the LBR to find the last branch and from that construct the actual IP. If the IP matches the LBR-TO, we use LBR-FROM, otherwise we use the LBR-TO address as the beginning of the last basic block and decode forward. Once we find a match to the current IP, we use the previous location. This patch introduces a new ABI element: PERF_RECORD_MISC_EXACT, which conveys that the reported IP (PERF_SAMPLE_IP) is the exact instruction that caused the event (barring CPU errata). The fixup can fail due to various reasons: 1) LBR contains invalid data (quite possible) 2) part of the basic block got paged out 3) the reported IP isn't part of the basic block (see 1) Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Arnaldo Carvalho de Melo <acme@infradead.org> Cc: Masami Hiramatsu <mhiramat@redhat.com> Cc: "Zhang, Yanmin" <yanmin_zhang@linux.intel.com> Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: <20100304140100.619375431@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:

committed by
Ingo Molnar

parent
caff2befff
commit
ef21f683a0
@@ -136,6 +136,25 @@ extern void perf_events_lapic_init(void);
|
||||
|
||||
#define PERF_EVENT_INDEX_OFFSET 0
|
||||
|
||||
/*
|
||||
* Abuse bit 3 of the cpu eflags register to indicate proper PEBS IP fixups.
|
||||
* This flag is otherwise unused and ABI specified to be 0, so nobody should
|
||||
* care what we do with it.
|
||||
*/
|
||||
#define PERF_EFLAGS_EXACT (1UL << 3)
|
||||
|
||||
#define perf_misc_flags(regs) \
|
||||
({ int misc = 0; \
|
||||
if (user_mode(regs)) \
|
||||
misc |= PERF_RECORD_MISC_USER; \
|
||||
else \
|
||||
misc |= PERF_RECORD_MISC_KERNEL; \
|
||||
if (regs->flags & PERF_EFLAGS_EXACT) \
|
||||
misc |= PERF_RECORD_MISC_EXACT; \
|
||||
misc; })
|
||||
|
||||
#define perf_instruction_pointer(regs) ((regs)->ip)
|
||||
|
||||
#else
|
||||
static inline void init_hw_perf_events(void) { }
|
||||
static inline void perf_events_lapic_init(void) { }
|
||||
|
Reference in New Issue
Block a user