Tony Jones 5f7d20
From: Ravi Bangoria <ravi.bangoria@amd.com>
Tony Jones 5f7d20
Date: Fri, 29 Apr 2022 10:44:41 +0530
Tony Jones 5f7d20
Subject: perf/amd/ibs: Use interrupt regs ip for stack unwinding
Tony Jones 5f7d20
Git-commit: 3d47083b9ff46863e8374ad3bb5edb5e464c75f8
Tony Jones 5f7d20
Patch-mainline: v5.19-rc1
Tony Jones 5f7d20
References: jsc#PED-1755
Tony Jones 5f7d20
Tony Jones 5f7d20
IbsOpRip is recorded when IBS interrupt is triggered. But there is
Tony Jones 5f7d20
a skid from the time IBS interrupt gets triggered to the time the
Tony Jones 5f7d20
interrupt is presented to the core. Meanwhile processor would have
Tony Jones 5f7d20
moved ahead and thus IbsOpRip will be inconsistent with rsp and rbp
Tony Jones 5f7d20
recorded as part of the interrupt regs. This causes issues while
Tony Jones 5f7d20
unwinding stack using the ORC unwinder as it needs consistent rip,
Tony Jones 5f7d20
rsp and rbp. Fix this by using rip from interrupt regs instead of
Tony Jones 5f7d20
IbsOpRip for stack unwinding.
Tony Jones 5f7d20
Tony Jones 5f7d20
Fixes: ee9f8fce99640 ("x86/unwind: Add the ORC unwinder")
Tony Jones 5f7d20
Reported-by: Dmitry Monakhov <dmtrmonakhov@yandex-team.ru>
Tony Jones 5f7d20
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Tony Jones 5f7d20
Signed-off-by: Ravi Bangoria <ravi.bangoria@amd.com>
Tony Jones 5f7d20
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Tony Jones 5f7d20
Link: https://lkml.kernel.org/r/20220429051441.14251-1-ravi.bangoria@amd.com
Tony Jones 5f7d20
Tony Jones 5f7d20
Signed-off-by: Tony Jones <tonyj@suse.de>
Tony Jones 5f7d20
---
Tony Jones 5f7d20
 arch/x86/events/amd/ibs.c | 18 ++++++++++++++++++
Tony Jones 5f7d20
 1 file changed, 18 insertions(+)
Tony Jones 5f7d20
Tony Jones 5f7d20
diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c
Tony Jones 5f7d20
index 9739019d4b67..11e8b493e015 100644
Tony Jones 5f7d20
--- a/arch/x86/events/amd/ibs.c
Tony Jones 5f7d20
+++ b/arch/x86/events/amd/ibs.c
Tony Jones 5f7d20
@@ -304,6 +304,16 @@ static int perf_ibs_init(struct perf_event *event)
Tony Jones 5f7d20
 	hwc->config_base = perf_ibs->msr;
Tony Jones 5f7d20
 	hwc->config = config;
Tony Jones 5f7d20
 
Tony Jones 5f7d20
+	/*
Tony Jones 5f7d20
+	 * rip recorded by IbsOpRip will not be consistent with rsp and rbp
Tony Jones 5f7d20
+	 * recorded as part of interrupt regs. Thus we need to use rip from
Tony Jones 5f7d20
+	 * interrupt regs while unwinding call stack. Setting _EARLY flag
Tony Jones 5f7d20
+	 * makes sure we unwind call-stack before perf sample rip is set to
Tony Jones 5f7d20
+	 * IbsOpRip.
Tony Jones 5f7d20
+	 */
Tony Jones 5f7d20
+	if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)
Tony Jones 5f7d20
+		event->attr.sample_type |= __PERF_SAMPLE_CALLCHAIN_EARLY;
Tony Jones 5f7d20
+
Tony Jones 5f7d20
 	return 0;
Tony Jones 5f7d20
 }
Tony Jones 5f7d20
 
Tony Jones 5f7d20
@@ -687,6 +697,14 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)
Tony Jones 5f7d20
 		data.raw = &raw;
Tony Jones 5f7d20
 	}
Tony Jones 5f7d20
 
Tony Jones 5f7d20
+	/*
Tony Jones 5f7d20
+	 * rip recorded by IbsOpRip will not be consistent with rsp and rbp
Tony Jones 5f7d20
+	 * recorded as part of interrupt regs. Thus we need to use rip from
Tony Jones 5f7d20
+	 * interrupt regs while unwinding call stack.
Tony Jones 5f7d20
+	 */
Tony Jones 5f7d20
+	if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)
Tony Jones 5f7d20
+		data.callchain = perf_callchain(event, iregs);
Tony Jones 5f7d20
+
Tony Jones 5f7d20
 	throttle = perf_event_overflow(event, &data, ®s;;
Tony Jones 5f7d20
 out:
Tony Jones 5f7d20
 	if (throttle) {
Tony Jones 5f7d20