Skip to content

Commit

Permalink
xtensa: clean up access to spilled registers locations
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Max Filippov committed May 1, 2017
1 parent f984409 commit 062b1c1
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 36 deletions.
15 changes: 15 additions & 0 deletions arch/xtensa/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions arch/xtensa/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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.
Expand Down
10 changes: 5 additions & 5 deletions arch/xtensa/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,22 +91,22 @@ 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;
}

/* 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. */
Expand Down
35 changes: 8 additions & 27 deletions arch/xtensa/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand Down

0 comments on commit 062b1c1

Please sign in to comment.