Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a562b187 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar
Browse files

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: default avatarPeter 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: default avatarIngo Molnar <mingo@elte.hu>
parent 74846d35
Loading
Loading
Loading
Loading
+19 −2
Original line number Original line Diff line number Diff line
@@ -399,10 +399,23 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
	if (!x86_pmu.intel_cap.pebs_trap)
	if (!x86_pmu.intel_cap.pebs_trap)
		return 1;
		return 1;


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


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


		old_to = to;
		old_to = to;
		if (!kernel_ip(ip)) {
		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);
			bytes = copy_from_user_nmi(buf, (void __user *)to, size);
			if (bytes != size)
			if (bytes != size)
@@ -440,6 +453,10 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
		return 1;
		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;
	return 0;
}
}