[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <tip-a562b1871f7f7d2f3a835c3c1e07fa58d473cfb7@git.kernel.org>
Date: Wed, 10 Mar 2010 13:21:45 GMT
From: tip-bot for Peter Zijlstra <a.p.zijlstra@...llo.nl>
To: linux-tip-commits@...r.kernel.org
Cc: linux-kernel@...r.kernel.org, hpa@...or.com, mingo@...hat.com,
acme@...radead.org, a.p.zijlstra@...llo.nl, tglx@...utronix.de,
mingo@...e.hu
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@...llo.nl>
AuthorDate: Fri, 5 Mar 2010 16:29:14 +0100
Committer: Ingo Molnar <mingo@...e.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@...llo.nl>
Cc: Arnaldo Carvalho de Melo <acme@...radead.org>
Cc: paulus@...ba.org
Cc: eranian@...gle.com
Cc: robert.richter@....com
Cc: fweisbec@...il.com
LKML-Reference: <20100305154129.042271287@...llo.nl>
Signed-off-by: Ingo Molnar <mingo@...e.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;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists