linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Masami Hiramatsu <mhiramat@redhat.com>
To: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: mingo@elte.hu, linux-kernel@vger.kernel.org, paulus@samba.org,
	eranian@google.com, robert.richter@amd.com, fweisbec@gmail.com
Subject: Re: [RFC][PATCH 10/11] perf, x86: use LBR for PEBS IP+1 fixup
Date: Wed, 03 Mar 2010 13:05:13 -0500	[thread overview]
Message-ID: <4B8EA4D9.6000505@redhat.com> (raw)
In-Reply-To: <20100303164306.602529559@chello.nl>

Peter Zijlstra wrote:
> PEBS always reports the IP+1, that is the instruction after the one
> that got sampled, cure this by using the LBR to reliably rewind the
> instruction stream.

Hmm, does PEBS always report one byte after the end address of the
sampled instruction? Or the instruction which will be executed next
step?

[...]
> +#include <asm/insn.h>
> +
> +#define MAX_INSN_SIZE	16

Hmm, we'd better integrate these kinds of definitions into
asm/insn.h... (several features define it)

> +
> +static void intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
> +{
> +#if 0
> +	/*
> +	 * Borken, makes the machine expode at times trying to
> +	 * derefence funny userspace addresses.
> +	 *
> +	 * Should we always fwd decode from @to, instead of trying
> +	 * to rewind as implemented?
> +	 */
> +
> +	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
> +	unsigned long from = cpuc->lbr_entries[0].from;
> +	unsigned long to = cpuc->lbr_entries[0].to;

Ah, I see. For branch instruction case, we can use LBR to
find previous IP...

> +	unsigned long ip = regs->ip;
> +	u8 buf[2*MAX_INSN_SIZE];
> +	u8 *kaddr;
> +	int i;
> +
> +	if (from && to) {
> +		/*
> +		 * We sampled a branch insn, rewind using the LBR stack
> +		 */
> +		if (ip == to) {
> +			regs->ip = from;
> +			return;
> +		}
> +	}
> +
> +	if (user_mode(regs)) {
> +		int bytes = copy_from_user_nmi(buf,
> +				(void __user *)(ip - MAX_INSN_SIZE),
> +				2*MAX_INSN_SIZE);
> +

maybe, you'd better check the source address range is within
the user address range. e.g. ip < MAX_INSN_SIZE. 

> +		/*
> +		 * If we fail to copy the insn stream, give up
> +		 */
> +		if (bytes != 2*MAX_INSN_SIZE)
> +			return;
> +
> +		kaddr = buf;
> +	} else
> +		kaddr = (void *)(ip - MAX_INSN_SIZE);

It also needs to be checked this address within kernel text.

> +
> +	/*
> +	 * Try to find the longest insn ending up at the given IP
> +	 */
> +	for (i = MAX_INSN_SIZE; i > 0; i--) {
> +		struct insn insn;
> +
> +		kernel_insn_init(&insn, kaddr + MAX_INSN_SIZE - i);
> +		insn_get_length(&insn);
> +		if (insn.length == i) {
> +			regs->ip -= i;
> +			return;
> +		}
> +	}

Hmm, this will not work correctly on x86, since the decoder can
miss-decode the tail bytes of previous instruction as prefix bytes. :(

Thus, if you want to rewind instruction stream, you need to decode
a function (or basic block) entirely.

Thank you,

> +
> +	/*
> +	 * We failed to find a match for the previous insn.. give up
> +	 */
> +#endif
> +}
> +
>  static int intel_pmu_save_and_restart(struct perf_event *event);
>  static void intel_pmu_disable_event(struct perf_event *event);
>  
> @@ -458,6 +532,8 @@ static void intel_pmu_drain_pebs_core(st
>  
>  	PEBS_TO_REGS(at, &regs);
>  
> +	intel_pmu_pebs_fixup_ip(&regs);
> +
>  	if (perf_event_overflow(event, 1, data, &regs))
>  		intel_pmu_disable_event(event);
>  
> @@ -519,6 +595,7 @@ static void intel_pmu_drain_pebs_nhm(str
>  		data->period = event->hw.last_period;
>  
>  		PEBS_TO_REGS(at, &regs);
> +		intel_pmu_pebs_fixup_ip(&regs);
>  
>  		if (perf_event_overflow(event, 1, data, &regs))
>  			intel_pmu_disable_event(event);
> 
> -- 

-- 
Masami Hiramatsu
e-mail: mhiramat@redhat.com

  reply	other threads:[~2010-03-03 18:07 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-03-03 16:39 [RFC][PATCH 00/11] Another stab at PEBS and LBR support Peter Zijlstra
2010-03-03 16:39 ` [RFC][PATCH 01/11] perf, x86: Remove superfluous arguments to x86_perf_event_set_period() Peter Zijlstra
2010-03-03 16:39 ` [RFC][PATCH 02/11] perf, x86: Remove superfluous arguments to x86_perf_event_update() Peter Zijlstra
2010-03-03 16:39 ` [RFC][PATCH 03/11] perf, x86: Change x86_pmu.{enable,disable} calling convention Peter Zijlstra
2010-03-03 16:39 ` [RFC][PATCH 04/11] perf, x86: Use unlocked bitops Peter Zijlstra
2010-03-03 16:39 ` [RFC][PATCH 05/11] perf: Generic perf_sample_data initialization Peter Zijlstra
2010-03-03 16:49   ` David Miller
2010-03-03 21:14   ` Frederic Weisbecker
2010-03-05  8:44   ` Jean Pihet
2010-03-03 16:39 ` [RFC][PATCH 06/11] perf, x86: PEBS infrastructure Peter Zijlstra
2010-03-03 17:38   ` Robert Richter
2010-03-03 17:42     ` Peter Zijlstra
2010-03-04  8:50       ` Robert Richter
2010-03-03 16:39 ` [RFC][PATCH 07/11] perf: Provide PERF_SAMPLE_REGS Peter Zijlstra
2010-03-03 17:30   ` Stephane Eranian
2010-03-03 17:39     ` Peter Zijlstra
2010-03-03 17:49       ` Stephane Eranian
2010-03-03 17:55         ` David Miller
2010-03-03 18:18           ` Stephane Eranian
2010-03-03 19:18           ` Peter Zijlstra
2010-03-04  2:59           ` Ingo Molnar
2010-03-04 12:58             ` Arnaldo Carvalho de Melo
2010-03-03 22:02   ` Frederic Weisbecker
2010-03-04  8:58     ` Peter Zijlstra
2010-03-04 11:04       ` Ingo Molnar
2010-03-03 16:39 ` [RFC][PATCH 08/11] perf, x86: Implement simple LBR support Peter Zijlstra
2010-03-03 21:52   ` Stephane Eranian
2010-03-04  8:58     ` Peter Zijlstra
2010-03-03 21:57   ` Stephane Eranian
2010-03-04  8:58     ` Peter Zijlstra
2010-03-04 17:54       ` Stephane Eranian
2010-03-04 18:18         ` Peter Zijlstra
2010-03-04 20:23           ` Peter Zijlstra
2010-03-04 20:57             ` Stephane Eranian
2010-03-03 16:39 ` [RFC][PATCH 09/11] perf, x86: Implement PERF_SAMPLE_BRANCH_STACK Peter Zijlstra
2010-03-03 21:08   ` Frederic Weisbecker
2010-03-03 16:39 ` [RFC][PATCH 10/11] perf, x86: use LBR for PEBS IP+1 fixup Peter Zijlstra
2010-03-03 18:05   ` Masami Hiramatsu [this message]
2010-03-03 19:37     ` Peter Zijlstra
2010-03-03 21:11       ` Masami Hiramatsu
2010-03-03 21:50         ` Stephane Eranian
2010-03-04  8:57           ` Peter Zijlstra
2010-03-09  1:41             ` Stephane Eranian
2010-03-03 16:39 ` [RFC][PATCH 11/11] perf, x86: Clean up IA32_PERF_CAPABILITIES usage Peter Zijlstra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4B8EA4D9.6000505@redhat.com \
    --to=mhiramat@redhat.com \
    --cc=a.p.zijlstra@chello.nl \
    --cc=eranian@google.com \
    --cc=fweisbec@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=paulus@samba.org \
    --cc=robert.richter@amd.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).