xtensa: clean up access to spilled registers locations
authorMax Filippov <jcmvbkbc@gmail.com>
Mon, 26 Jan 2015 22:15:10 +0000 (01:15 +0300)
committerMax Filippov <jcmvbkbc@gmail.com>
Mon, 1 May 2017 17:34:43 +0000 (10:34 -0700)
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>
arch/xtensa/include/asm/processor.h
arch/xtensa/kernel/process.c
arch/xtensa/kernel/signal.c
arch/xtensa/kernel/stacktrace.c

index 86ffcd68e49616e62d693bad4cae85ffbae0582e..003eeee3fbc636d91aed849aaa39bb0c24370227 100644 (file)
  */
 #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;
index 58f96d1230d4d57e8bebb6417834581690b61f1a..ff4f0ecb03dd1e9dfcab581eaa2afd55d7a1b374 100644 (file)
@@ -204,8 +204,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
 #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 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
                /* 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.
index 70a131945443841358c56b35fd157e66b2d22290..d427e784ab44cd018b4a3b1aaa7739987e51b6cd 100644 (file)
@@ -91,14 +91,14 @@ flush_window_regs_user(struct pt_regs *regs)
                        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 @@ flush_window_regs_user(struct pt_regs *regs)
                /* 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. */
index e7d30ee0fd482794a21f72c85ca2feb2ec4b5500..0df4080fa20f2276563eb64f8694959548a3f557 100644 (file)
  */
 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 @@ void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth,
        /* 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 @@ void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth,
         */
        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 @@ void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth,
                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 @@ void walk_stackframe(unsigned long *sp,
 
                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;