ARC: pt_regs update #3: Remove unused gutter at start of callee_regs
This is trickier than prev two: * context switching code saves kernel mode callee regs in the format of struct callee_regs thus needs adjustment. This also reduces the height of topmost kernel stack frame by 1 word. * Since kernel stack unwinder is sensitive to height of topmost kernel stack frame, that needs a word of adjustment too. ptrace needs a bit of updating since pt_regs now diverges from user_regs_struct. Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
This commit is contained in:
parent
2fa919045b
commit
16f9afe651
|
@ -124,8 +124,6 @@
|
||||||
st.a r25, [sp, -4]
|
st.a r25, [sp, -4]
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* move up by 1 word to "create" callee_regs->"stack_place_holder" */
|
|
||||||
sub sp, sp, 4
|
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
/*--------------------------------------------------------------
|
||||||
|
@ -148,10 +146,9 @@
|
||||||
st.a r23, [sp, -4]
|
st.a r23, [sp, -4]
|
||||||
st.a r24, [sp, -4]
|
st.a r24, [sp, -4]
|
||||||
#ifdef CONFIG_ARC_CURR_IN_REG
|
#ifdef CONFIG_ARC_CURR_IN_REG
|
||||||
sub sp, sp, 8
|
sub sp, sp, 4
|
||||||
#else
|
#else
|
||||||
st.a r25, [sp, -4]
|
st.a r25, [sp, -4]
|
||||||
sub sp, sp, 4
|
|
||||||
#endif
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
@ -168,14 +165,11 @@
|
||||||
*-------------------------------------------------------------*/
|
*-------------------------------------------------------------*/
|
||||||
.macro RESTORE_CALLEE_SAVED_KERNEL
|
.macro RESTORE_CALLEE_SAVED_KERNEL
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_ARC_CURR_IN_REG
|
#ifdef CONFIG_ARC_CURR_IN_REG
|
||||||
add sp, sp, 8 /* skip callee_reg gutter and user r25 placeholder */
|
add sp, sp, 4 /* skip usual r25 placeholder */
|
||||||
#else
|
#else
|
||||||
add sp, sp, 4 /* skip "callee_regs->stack_place_holder" */
|
|
||||||
ld.ab r25, [sp, 4]
|
ld.ab r25, [sp, 4]
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ld.ab r24, [sp, 4]
|
ld.ab r24, [sp, 4]
|
||||||
ld.ab r23, [sp, 4]
|
ld.ab r23, [sp, 4]
|
||||||
ld.ab r22, [sp, 4]
|
ld.ab r22, [sp, 4]
|
||||||
|
@ -203,8 +197,6 @@
|
||||||
*-------------------------------------------------------------*/
|
*-------------------------------------------------------------*/
|
||||||
.macro RESTORE_CALLEE_SAVED_USER
|
.macro RESTORE_CALLEE_SAVED_USER
|
||||||
|
|
||||||
add sp, sp, 4 /* skip "callee_regs->stack_place_holder" */
|
|
||||||
|
|
||||||
#ifdef CONFIG_ARC_CURR_IN_REG
|
#ifdef CONFIG_ARC_CURR_IN_REG
|
||||||
ld.ab r12, [sp, 4]
|
ld.ab r12, [sp, 4]
|
||||||
st r12, [r25, TASK_THREAD + THREAD_USER_R25]
|
st r12, [r25, TASK_THREAD + THREAD_USER_R25]
|
||||||
|
@ -230,7 +222,7 @@
|
||||||
* Super FAST Restore callee saved regs by simply re-adjusting SP
|
* Super FAST Restore callee saved regs by simply re-adjusting SP
|
||||||
*-------------------------------------------------------------*/
|
*-------------------------------------------------------------*/
|
||||||
.macro DISCARD_CALLEE_SAVED_USER
|
.macro DISCARD_CALLEE_SAVED_USER
|
||||||
add sp, sp, 14 * 4
|
add sp, sp, SZ_CALLEE_REGS
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
/*--------------------------------------------------------------
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#include <asm/arcregs.h> /* for STATUS_E1_MASK et all */
|
#include <asm/arcregs.h> /* for STATUS_E1_MASK et all */
|
||||||
|
#include <asm/ptrace.h>
|
||||||
|
|
||||||
/* Arch specific stuff which needs to be saved per task.
|
/* Arch specific stuff which needs to be saved per task.
|
||||||
* However these items are not so important so as to earn a place in
|
* However these items are not so important so as to earn a place in
|
||||||
|
@ -75,11 +76,15 @@ unsigned long thread_saved_pc(struct task_struct *t);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Where abouts of Task's sp, fp, blink when it was last seen in kernel mode.
|
* Where abouts of Task's sp, fp, blink when it was last seen in kernel mode.
|
||||||
* These can't be derived from pt_regs as that would give correp user-mode val
|
* Look in process.c for details of kernel stack layout
|
||||||
*/
|
*/
|
||||||
#define KSTK_ESP(tsk) (tsk->thread.ksp)
|
#define KSTK_ESP(tsk) (tsk->thread.ksp)
|
||||||
#define KSTK_BLINK(tsk) (*((unsigned int *)((KSTK_ESP(tsk)) + (13+1+1)*4)))
|
|
||||||
#define KSTK_FP(tsk) (*((unsigned int *)((KSTK_ESP(tsk)) + (13+1)*4)))
|
#define KSTK_REG(tsk, off) (*((unsigned int *)(KSTK_ESP(tsk) + \
|
||||||
|
sizeof(struct callee_regs) + off)))
|
||||||
|
|
||||||
|
#define KSTK_BLINK(tsk) KSTK_REG(tsk, 4)
|
||||||
|
#define KSTK_FP(tsk) KSTK_REG(tsk, 0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do necessary setup to start up a newly executed thread.
|
* Do necessary setup to start up a newly executed thread.
|
||||||
|
|
|
@ -59,7 +59,6 @@ struct pt_regs {
|
||||||
/* Callee saved registers - need to be saved only when you are scheduled out */
|
/* Callee saved registers - need to be saved only when you are scheduled out */
|
||||||
|
|
||||||
struct callee_regs {
|
struct callee_regs {
|
||||||
long res; /* Again this is not needed */
|
|
||||||
long r25;
|
long r25;
|
||||||
long r24;
|
long r24;
|
||||||
long r23;
|
long r23;
|
||||||
|
|
|
@ -38,8 +38,8 @@ struct user_regs_struct {
|
||||||
long r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r1, r0;
|
long r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r1, r0;
|
||||||
long sp;
|
long sp;
|
||||||
} scratch;
|
} scratch;
|
||||||
|
long pad2;
|
||||||
struct {
|
struct {
|
||||||
long pad;
|
|
||||||
long r25, r24, r23, r22, r21, r20;
|
long r25, r24, r23, r22, r21, r20;
|
||||||
long r19, r18, r17, r16, r15, r14, r13;
|
long r19, r18, r17, r16, r15, r14, r13;
|
||||||
} callee;
|
} callee;
|
||||||
|
|
|
@ -60,5 +60,6 @@ int main(void)
|
||||||
DEFINE(PT_r6, offsetof(struct pt_regs, r6));
|
DEFINE(PT_r6, offsetof(struct pt_regs, r6));
|
||||||
DEFINE(PT_r7, offsetof(struct pt_regs, r7));
|
DEFINE(PT_r7, offsetof(struct pt_regs, r7));
|
||||||
|
|
||||||
|
DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,6 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task)
|
||||||
unsigned int tmp;
|
unsigned int tmp;
|
||||||
unsigned int prev = (unsigned int)prev_task;
|
unsigned int prev = (unsigned int)prev_task;
|
||||||
unsigned int next = (unsigned int)next_task;
|
unsigned int next = (unsigned int)next_task;
|
||||||
int num_words_to_skip = 1;
|
|
||||||
#ifdef CONFIG_ARC_CURR_IN_REG
|
|
||||||
num_words_to_skip++;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
/* FP/BLINK save generated by gcc (standard function prologue */
|
/* FP/BLINK save generated by gcc (standard function prologue */
|
||||||
|
@ -44,8 +40,9 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task)
|
||||||
"st.a r24, [sp, -4] \n\t"
|
"st.a r24, [sp, -4] \n\t"
|
||||||
#ifndef CONFIG_ARC_CURR_IN_REG
|
#ifndef CONFIG_ARC_CURR_IN_REG
|
||||||
"st.a r25, [sp, -4] \n\t"
|
"st.a r25, [sp, -4] \n\t"
|
||||||
|
#else
|
||||||
|
"sub sp, sp, 4 \n\t" /* usual r25 placeholder */
|
||||||
#endif
|
#endif
|
||||||
"sub sp, sp, %4 \n\t" /* create gutter at top */
|
|
||||||
|
|
||||||
/* set ksp of outgoing task in tsk->thread.ksp */
|
/* set ksp of outgoing task in tsk->thread.ksp */
|
||||||
"st.as sp, [%3, %1] \n\t"
|
"st.as sp, [%3, %1] \n\t"
|
||||||
|
@ -76,10 +73,10 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task)
|
||||||
|
|
||||||
/* start loading it's CALLEE reg file */
|
/* start loading it's CALLEE reg file */
|
||||||
|
|
||||||
"add sp, sp, %4 \n\t" /* skip gutter at top */
|
|
||||||
|
|
||||||
#ifndef CONFIG_ARC_CURR_IN_REG
|
#ifndef CONFIG_ARC_CURR_IN_REG
|
||||||
"ld.ab r25, [sp, 4] \n\t"
|
"ld.ab r25, [sp, 4] \n\t"
|
||||||
|
#else
|
||||||
|
"add sp, sp, 4 \n\t"
|
||||||
#endif
|
#endif
|
||||||
"ld.ab r24, [sp, 4] \n\t"
|
"ld.ab r24, [sp, 4] \n\t"
|
||||||
"ld.ab r23, [sp, 4] \n\t"
|
"ld.ab r23, [sp, 4] \n\t"
|
||||||
|
@ -100,8 +97,7 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task)
|
||||||
/* FP/BLINK restore generated by gcc (standard func epilogue */
|
/* FP/BLINK restore generated by gcc (standard func epilogue */
|
||||||
|
|
||||||
: "=r"(tmp)
|
: "=r"(tmp)
|
||||||
: "n"((TASK_THREAD + THREAD_KSP) / 4), "r"(next), "r"(prev),
|
: "n"((TASK_THREAD + THREAD_KSP) / 4), "r"(next), "r"(prev)
|
||||||
"n"(num_words_to_skip * 4)
|
|
||||||
: "blink"
|
: "blink"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -55,10 +55,8 @@ asmlinkage void ret_from_fork(void);
|
||||||
* | ... |
|
* | ... |
|
||||||
* | unused |
|
* | unused |
|
||||||
* | |
|
* | |
|
||||||
* ------------------ <==== top of Stack (thread.ksp)
|
|
||||||
* | UNUSED 1 word|
|
|
||||||
* ------------------
|
* ------------------
|
||||||
* | r25 |
|
* | r25 | <==== top of Stack (thread.ksp)
|
||||||
* ~ ~
|
* ~ ~
|
||||||
* | --to-- | (CALLEE Regs of user mode)
|
* | --to-- | (CALLEE Regs of user mode)
|
||||||
* | r13 |
|
* | r13 |
|
||||||
|
|
|
@ -48,6 +48,7 @@ static int genregs_get(struct task_struct *target,
|
||||||
|
|
||||||
REG_O_ZERO(pad);
|
REG_O_ZERO(pad);
|
||||||
REG_O_CHUNK(scratch, callee, ptregs);
|
REG_O_CHUNK(scratch, callee, ptregs);
|
||||||
|
REG_O_ZERO(pad2);
|
||||||
REG_O_CHUNK(callee, efa, cregs);
|
REG_O_CHUNK(callee, efa, cregs);
|
||||||
REG_O_CHUNK(efa, stop_pc, &target->thread.fault_address);
|
REG_O_CHUNK(efa, stop_pc, &target->thread.fault_address);
|
||||||
|
|
||||||
|
@ -96,8 +97,9 @@ static int genregs_set(struct task_struct *target,
|
||||||
offsetof(struct user_regs_struct, LOC) + 4);
|
offsetof(struct user_regs_struct, LOC) + 4);
|
||||||
|
|
||||||
REG_IGNORE_ONE(pad);
|
REG_IGNORE_ONE(pad);
|
||||||
/* TBD: disallow updates to STATUS32, orig_r8 etc*/
|
/* TBD: disallow updates to STATUS32 etc*/
|
||||||
REG_IN_CHUNK(scratch, callee, ptregs); /* pt_regs[bta..orig_r8] */
|
REG_IN_CHUNK(scratch, pad2, ptregs); /* pt_regs[bta..sp] */
|
||||||
|
REG_IGNORE_ONE(pad2);
|
||||||
REG_IN_CHUNK(callee, efa, cregs); /* callee_regs[r25..r13] */
|
REG_IN_CHUNK(callee, efa, cregs); /* callee_regs[r25..r13] */
|
||||||
REG_IGNORE_ONE(efa); /* efa update invalid */
|
REG_IGNORE_ONE(efa); /* efa update invalid */
|
||||||
REG_IN_ONE(stop_pc, &ptregs->ret); /* stop_pc: PC update */
|
REG_IN_ONE(stop_pc, &ptregs->ret); /* stop_pc: PC update */
|
||||||
|
|
|
@ -79,7 +79,7 @@ static void seed_unwind_frame_info(struct task_struct *tsk,
|
||||||
* assembly code
|
* assembly code
|
||||||
*/
|
*/
|
||||||
frame_info->regs.r27 = 0;
|
frame_info->regs.r27 = 0;
|
||||||
frame_info->regs.r28 += 64;
|
frame_info->regs.r28 += 60;
|
||||||
frame_info->call_frame = 0;
|
frame_info->call_frame = 0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue