lkml.org 
[lkml]   [2010]   [Mar]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[tip:perf/pebs] perf, x86: Robustify PEBS fixup
    Commit-ID:  a562b1871f7f7d2f3a835c3c1e07fa58d473cfb7
    Gitweb: http://git.kernel.org/tip/a562b1871f7f7d2f3a835c3c1e07fa58d473cfb7
    Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
    AuthorDate: Fri, 5 Mar 2010 16:29:14 +0100
    Committer: Ingo Molnar <mingo@elte.hu>
    CommitDate: Wed, 10 Mar 2010 13:23:35 +0100

    perf, x86: Robustify PEBS fixup

    It turns out the LBR is massively unreliable on certain CPUs, so code the
    fixup a little more defensive to avoid crashing the kernel.

    Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
    Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
    Cc: paulus@samba.org
    Cc: eranian@google.com
    Cc: robert.richter@amd.com
    Cc: fweisbec@gmail.com
    LKML-Reference: <20100305154129.042271287@chello.nl>
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    ---
    arch/x86/kernel/cpu/perf_event_intel_ds.c | 21 +++++++++++++++++++--
    1 files changed, 19 insertions(+), 2 deletions(-)

    diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
    index a67fff1..e7ac517 100644
    --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
    +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
    @@ -399,10 +399,23 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
    if (!x86_pmu.intel_cap.pebs_trap)
    return 1;

    + /*
    + * No LBR entry, no basic block, no rewinding
    + */
    if (!cpuc->lbr_stack.nr || !from || !to)
    return 0;

    - if (ip < to)
    + /*
    + * Basic blocks should never cross user/kernel boundaries
    + */
    + if (kernel_ip(ip) != kernel_ip(to))
    + return 0;
    +
    + /*
    + * unsigned math, either ip is before the start (impossible) or
    + * the basic block is larger than 1 page (sanity)
    + */
    + if ((ip - to) > PAGE_SIZE)
    return 0;

    /*
    @@ -420,7 +433,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)

    old_to = to;
    if (!kernel_ip(ip)) {
    - int bytes, size = min_t(int, MAX_INSN_SIZE, ip - to);
    + int bytes, size = MAX_INSN_SIZE;

    bytes = copy_from_user_nmi(buf, (void __user *)to, size);
    if (bytes != size)
    @@ -440,6 +453,10 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
    return 1;
    }

    + /*
    + * Even though we decoded the basic block, the instruction stream
    + * never matched the given IP, either the TO or the IP got corrupted.
    + */
    return 0;
    }


    \
     
     \ /
      Last update: 2010-03-10 14:25    [W:4.047 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site