xtensa: clean up access to spilled registers locations

Define macros SPILL_SLOT* that return a reference to the stack location
of the spill slot for specific register and use them instead of opencoded
address calculations.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h
index 86ffcd6..003eeee 100644
--- a/arch/xtensa/include/asm/processor.h
+++ b/arch/xtensa/include/asm/processor.h
@@ -113,6 +113,21 @@
  */
 #define MAKE_PC_FROM_RA(ra,sp)    (((ra) & 0x3fffffff) | ((sp) & 0xc0000000))
 
+/* Spill slot location for the register reg in the spill area under the stack
+ * pointer sp. reg must be in the range [0..4).
+ */
+#define SPILL_SLOT(sp, reg) (*(((unsigned long *)(sp)) - 4 + (reg)))
+
+/* Spill slot location for the register reg in the spill area under the stack
+ * pointer sp for the call8. reg must be in the range [4..8).
+ */
+#define SPILL_SLOT_CALL8(sp, reg) (*(((unsigned long *)(sp)) - 12 + (reg)))
+
+/* Spill slot location for the register reg in the spill area under the stack
+ * pointer sp for the call12. reg must be in the range [4..12).
+ */
+#define SPILL_SLOT_CALL12(sp, reg) (*(((unsigned long *)(sp)) - 16 + (reg)))
+
 typedef struct {
 	unsigned long seg;
 } mm_segment_t;
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index 58f96d1..ff4f0ec 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -204,8 +204,8 @@
 #endif
 
 	/* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */
-	*((int*)childregs - 3) = (unsigned long)childregs;
-	*((int*)childregs - 4) = 0;
+	SPILL_SLOT(childregs, 1) = (unsigned long)childregs;
+	SPILL_SLOT(childregs, 0) = 0;
 
 	p->thread.sp = (unsigned long)childregs;
 
@@ -266,8 +266,8 @@
 		/* pass parameters to ret_from_kernel_thread:
 		 * a2 = thread_fn, a3 = thread_fn arg
 		 */
-		*((int *)childregs - 1) = thread_fn_arg;
-		*((int *)childregs - 2) = usp_thread_fn;
+		SPILL_SLOT(childregs, 3) = thread_fn_arg;
+		SPILL_SLOT(childregs, 2) = usp_thread_fn;
 
 		/* Childregs are only used when we're going to userspace
 		 * in which case start_thread will set them up.
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index 70a1319..d427e78 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -91,14 +91,14 @@
 			inc = 1;
 
 		} else if (m & 4) {		/* call8 */
-			if (copy_to_user((void*)(sp - 32),
-					   &regs->areg[(base + 1) * 4], 16))
+			if (copy_to_user(&SPILL_SLOT_CALL8(sp, 4),
+					 &regs->areg[(base + 1) * 4], 16))
 				goto errout;
 			inc = 2;
 
 		} else if (m & 8) {	/* call12 */
-			if (copy_to_user((void*)(sp - 48),
-					   &regs->areg[(base + 1) * 4], 32))
+			if (copy_to_user(&SPILL_SLOT_CALL12(sp, 4),
+					 &regs->areg[(base + 1) * 4], 32))
 				goto errout;
 			inc = 3;
 		}
@@ -106,7 +106,7 @@
 		/* Save current frame a0..a3 under next SP */
 
 		sp = regs->areg[((base + inc) * 4 + 1) % XCHAL_NUM_AREGS];
-		if (copy_to_user((void*)(sp - 16), &regs->areg[base * 4], 16))
+		if (copy_to_user(&SPILL_SLOT(sp, 0), &regs->areg[base * 4], 16))
 			goto errout;
 
 		/* Get current stack pointer for next loop iteration. */
diff --git a/arch/xtensa/kernel/stacktrace.c b/arch/xtensa/kernel/stacktrace.c
index e7d30ee..0df4080 100644
--- a/arch/xtensa/kernel/stacktrace.c
+++ b/arch/xtensa/kernel/stacktrace.c
@@ -23,14 +23,6 @@
  */
 extern int common_exception_return;
 
-/* A struct that maps to the part of the frame containing the a0 and
- * a1 registers.
- */
-struct frame_start {
-	unsigned long a0;
-	unsigned long a1;
-};
-
 void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth,
 			   int (*ufn)(struct stackframe *frame, void *data),
 			   void *data)
@@ -96,26 +88,16 @@
 	/* Start from the a1 register. */
 	/* a1 = regs->areg[1]; */
 	while (a0 != 0 && depth--) {
-		struct frame_start frame_start;
-		/* Get the location for a1, a0 for the
-		 * previous frame from the current a1.
-		 */
-		unsigned long *psp = (unsigned long *)a1;
-
-		psp -= 4;
+		pc = MAKE_PC_FROM_RA(a0, pc);
 
 		/* Check if the region is OK to access. */
-		if (!access_ok(VERIFY_READ, psp, sizeof(frame_start)))
+		if (!access_ok(VERIFY_READ, &SPILL_SLOT(a1, 0), 8))
 			return;
 		/* Copy a1, a0 from user space stack frame. */
-		if (__copy_from_user_inatomic(&frame_start, psp,
-					      sizeof(frame_start)))
+		if (__get_user(a0, &SPILL_SLOT(a1, 0)) ||
+		    __get_user(a1, &SPILL_SLOT(a1, 1)))
 			return;
 
-		pc = MAKE_PC_FROM_RA(a0, pc);
-		a0 = frame_start.a0;
-		a1 = frame_start.a1;
-
 		frame.pc = pc;
 		frame.sp = a1;
 
@@ -147,7 +129,6 @@
 	 */
 	while (a1 > sp_start && a1 < sp_end && depth--) {
 		struct stackframe frame;
-		unsigned long *psp = (unsigned long *)a1;
 
 		frame.pc = pc;
 		frame.sp = a1;
@@ -171,8 +152,8 @@
 		sp_start = a1;
 
 		pc = MAKE_PC_FROM_RA(a0, pc);
-		a0 = *(psp - 4);
-		a1 = *(psp - 3);
+		a0 = SPILL_SLOT(a1, 0);
+		a1 = SPILL_SLOT(a1, 1);
 	}
 }
 EXPORT_SYMBOL(xtensa_backtrace_kernel);
@@ -196,8 +177,8 @@
 
 		sp = (unsigned long *)a1;
 
-		a0 = *(sp - 4);
-		a1 = *(sp - 3);
+		a0 = SPILL_SLOT(a1, 0);
+		a1 = SPILL_SLOT(a1, 1);
 
 		if (a1 <= (unsigned long)sp)
 			break;