xtensa: provide custom CALLER_ADDR* implementations

Definition of CALLER_ADDR* through __builtin_return_address makes
compiler insert calls to __xtensa_libgcc_window_spill, which in turn
makes fast_syscall_spill_registers syscall that clobbers registers when
called from the kernel mode, leading to invalid opcode exceptions on
return to userspace.

Provide definition for CALLER_ADDR0 as MAKE_PC_FROM_RA(a0, a1) and in
case CONFIG_FRAME_POINTER is enabled extract CALLER_ADDR{1-3} from
stack.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Chris Zankel <chris@zankel.net>
diff --git a/arch/xtensa/kernel/stacktrace.c b/arch/xtensa/kernel/stacktrace.c
index e3aff95..7d2c317 100644
--- a/arch/xtensa/kernel/stacktrace.c
+++ b/arch/xtensa/kernel/stacktrace.c
@@ -85,3 +85,36 @@
 EXPORT_SYMBOL_GPL(save_stack_trace);
 
 #endif
+
+#ifdef CONFIG_FRAME_POINTER
+
+struct return_addr_data {
+	unsigned long addr;
+	unsigned skip;
+};
+
+static int return_address_cb(struct stackframe *frame, void *data)
+{
+	struct return_addr_data *r = data;
+
+	if (r->skip) {
+		--r->skip;
+		return 0;
+	}
+	if (!kernel_text_address(frame->pc))
+		return 0;
+	r->addr = frame->pc;
+	return 1;
+}
+
+unsigned long return_address(unsigned level)
+{
+	struct return_addr_data r = {
+		.skip = level + 1,
+	};
+	walk_stackframe(stack_pointer(NULL), return_address_cb, &r);
+	return r.addr;
+}
+EXPORT_SYMBOL(return_address);
+
+#endif