Commit 062b1c19 authored by Max Filippov's avatar Max Filippov

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: default avatarMax Filippov <jcmvbkbc@gmail.com>
parent f984409a
...@@ -113,6 +113,21 @@ ...@@ -113,6 +113,21 @@
*/ */
#define MAKE_PC_FROM_RA(ra,sp) (((ra) & 0x3fffffff) | ((sp) & 0xc0000000)) #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 { typedef struct {
unsigned long seg; unsigned long seg;
} mm_segment_t; } mm_segment_t;
......
...@@ -204,8 +204,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, ...@@ -204,8 +204,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
#endif #endif
/* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */ /* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */
*((int*)childregs - 3) = (unsigned long)childregs; SPILL_SLOT(childregs, 1) = (unsigned long)childregs;
*((int*)childregs - 4) = 0; SPILL_SLOT(childregs, 0) = 0;
p->thread.sp = (unsigned long)childregs; p->thread.sp = (unsigned long)childregs;
...@@ -266,8 +266,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, ...@@ -266,8 +266,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
/* pass parameters to ret_from_kernel_thread: /* pass parameters to ret_from_kernel_thread:
* a2 = thread_fn, a3 = thread_fn arg * a2 = thread_fn, a3 = thread_fn arg
*/ */
*((int *)childregs - 1) = thread_fn_arg; SPILL_SLOT(childregs, 3) = thread_fn_arg;
*((int *)childregs - 2) = usp_thread_fn; SPILL_SLOT(childregs, 2) = usp_thread_fn;
/* Childregs are only used when we're going to userspace /* Childregs are only used when we're going to userspace
* in which case start_thread will set them up. * in which case start_thread will set them up.
......
...@@ -91,14 +91,14 @@ flush_window_regs_user(struct pt_regs *regs) ...@@ -91,14 +91,14 @@ flush_window_regs_user(struct pt_regs *regs)
inc = 1; inc = 1;
} else if (m & 4) { /* call8 */ } else if (m & 4) { /* call8 */
if (copy_to_user((void*)(sp - 32), if (copy_to_user(&SPILL_SLOT_CALL8(sp, 4),
&regs->areg[(base + 1) * 4], 16)) &regs->areg[(base + 1) * 4], 16))
goto errout; goto errout;
inc = 2; inc = 2;
} else if (m & 8) { /* call12 */ } else if (m & 8) { /* call12 */
if (copy_to_user((void*)(sp - 48), if (copy_to_user(&SPILL_SLOT_CALL12(sp, 4),
&regs->areg[(base + 1) * 4], 32)) &regs->areg[(base + 1) * 4], 32))
goto errout; goto errout;
inc = 3; inc = 3;
} }
...@@ -106,7 +106,7 @@ flush_window_regs_user(struct pt_regs *regs) ...@@ -106,7 +106,7 @@ flush_window_regs_user(struct pt_regs *regs)
/* Save current frame a0..a3 under next SP */ /* Save current frame a0..a3 under next SP */
sp = regs->areg[((base + inc) * 4 + 1) % XCHAL_NUM_AREGS]; 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; goto errout;
/* Get current stack pointer for next loop iteration. */ /* Get current stack pointer for next loop iteration. */
......
...@@ -23,14 +23,6 @@ ...@@ -23,14 +23,6 @@
*/ */
extern int common_exception_return; 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, void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth,
int (*ufn)(struct stackframe *frame, void *data), int (*ufn)(struct stackframe *frame, void *data),
void *data) void *data)
...@@ -96,26 +88,16 @@ void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth, ...@@ -96,26 +88,16 @@ void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth,
/* Start from the a1 register. */ /* Start from the a1 register. */
/* a1 = regs->areg[1]; */ /* a1 = regs->areg[1]; */
while (a0 != 0 && depth--) { while (a0 != 0 && depth--) {
struct frame_start frame_start; pc = MAKE_PC_FROM_RA(a0, pc);
/* Get the location for a1, a0 for the
* previous frame from the current a1.
*/
unsigned long *psp = (unsigned long *)a1;
psp -= 4;
/* Check if the region is OK to access. */ /* 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; return;
/* Copy a1, a0 from user space stack frame. */ /* Copy a1, a0 from user space stack frame. */
if (__copy_from_user_inatomic(&frame_start, psp, if (__get_user(a0, &SPILL_SLOT(a1, 0)) ||
sizeof(frame_start))) __get_user(a1, &SPILL_SLOT(a1, 1)))
return; return;
pc = MAKE_PC_FROM_RA(a0, pc);
a0 = frame_start.a0;
a1 = frame_start.a1;
frame.pc = pc; frame.pc = pc;
frame.sp = a1; frame.sp = a1;
...@@ -147,7 +129,6 @@ void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth, ...@@ -147,7 +129,6 @@ void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth,
*/ */
while (a1 > sp_start && a1 < sp_end && depth--) { while (a1 > sp_start && a1 < sp_end && depth--) {
struct stackframe frame; struct stackframe frame;
unsigned long *psp = (unsigned long *)a1;
frame.pc = pc; frame.pc = pc;
frame.sp = a1; frame.sp = a1;
...@@ -171,8 +152,8 @@ void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth, ...@@ -171,8 +152,8 @@ void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth,
sp_start = a1; sp_start = a1;
pc = MAKE_PC_FROM_RA(a0, pc); pc = MAKE_PC_FROM_RA(a0, pc);
a0 = *(psp - 4); a0 = SPILL_SLOT(a1, 0);
a1 = *(psp - 3); a1 = SPILL_SLOT(a1, 1);
} }
} }
EXPORT_SYMBOL(xtensa_backtrace_kernel); EXPORT_SYMBOL(xtensa_backtrace_kernel);
...@@ -196,8 +177,8 @@ void walk_stackframe(unsigned long *sp, ...@@ -196,8 +177,8 @@ void walk_stackframe(unsigned long *sp,
sp = (unsigned long *)a1; sp = (unsigned long *)a1;
a0 = *(sp - 4); a0 = SPILL_SLOT(a1, 0);
a1 = *(sp - 3); a1 = SPILL_SLOT(a1, 1);
if (a1 <= (unsigned long)sp) if (a1 <= (unsigned long)sp)
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment