ARC: entry: use gp to cache task pointer (vs. r25)

The motivation is eventual ABI considerations for ARCv3 but even without
it this change us worthwhile as diffstat reduces 100 net lines

r25 is a callee saved register, normally not saved by entry code in
pt_regs. However because of its usage in CONFIG_ARC_CURR_IN_REG it needs
to be. This in turn requires a whole bunch of special casing when we
need to access r25. Then there is distinction between user mode r25 vs.
kernel mode r25 - hence distinct SAVE_CALLEE_SAVED_{USER,KERNEL}

Instead use gp which is a scratch register and thus saved already in entry
code. This cleans things up significantly and much nocer on eyes:

 - SAVE_CALLEE_SAVED_{USER,KERNEL} are now exactly same
 - no special user_r25 slot in pt_reggs

Note that typical global asm registers are callee-saved (r25), but gp is
not callee-saved thus needs additional -ffixed-<reg> toggle

Signed-off-by: Vineet Gupta <vgupta@kernel.org>
This commit is contained in:
Vineet Gupta
2020-05-12 22:18:08 -07:00
parent fad84e39f1
commit cfca4b5abe
13 changed files with 60 additions and 156 deletions
+1 -1
View File
@@ -13,7 +13,7 @@
#ifdef CONFIG_ARC_CURR_IN_REG
register struct task_struct *curr_arc asm("r25");
register struct task_struct *curr_arc asm("gp");
#define current (curr_arc)
#else
+6 -11
View File
@@ -18,7 +18,6 @@
* | orig_r0 |
* | event/ECR |
* | bta |
* | user_r25 |
* | gp |
* | fp |
* | sp |
@@ -56,7 +55,7 @@
; hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE
; 4. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI
;
; (B) Manually saved some regs: r12,r25,r30, sp,fp,gp, ACCL pair
; (B) Manually saved some regs: r12,r30, sp,fp,gp, ACCL pair
#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
; carve pt_regs on stack (case #3), PC/STAT32 already on stack
@@ -157,17 +156,17 @@
st r10, [sp, PT_sp] ; SP (pt_regs->sp)
#ifdef CONFIG_ARC_CURR_IN_REG
st r25, [sp, PT_user_r25]
GET_CURR_TASK_ON_CPU r25
#endif
#ifdef CONFIG_ARC_HAS_ACCL_REGS
ST2 r58, r59, PT_r58
#endif
/* clobbers r10, r11 registers pair */
DSP_SAVE_REGFILE_IRQ
#ifdef CONFIG_ARC_CURR_IN_REG
GET_CURR_TASK_ON_CPU gp
#endif
.endm
/*------------------------------------------------------------------------*/
@@ -188,10 +187,6 @@
sr r10, [AUX_USER_SP]
1:
#ifdef CONFIG_ARC_CURR_IN_REG
ld r25, [sp, PT_user_r25]
#endif
/* clobbers r10, r11 registers pair */
DSP_RESTORE_REGFILE_IRQ
+11 -24
View File
@@ -151,14 +151,6 @@
/* ARC700 doesn't provide auto-stack switching */
SWITCH_TO_KERNEL_STK
#ifdef CONFIG_ARC_CURR_IN_REG
/* Treat r25 as scratch reg (save on stack) and load with "current" */
PUSH r25
GET_CURR_TASK_ON_CPU r25
#else
sub sp, sp, 4
#endif
st.a r0, [sp, -8] /* orig_r0 needed for syscall (skip ECR slot) */
sub sp, sp, 4 /* skip pt_regs->sp, already saved above */
@@ -179,6 +171,11 @@
lr r10, [ecr]
st r10, [sp, PT_event] /* EV_Trap expects r10 to have ECR */
#ifdef CONFIG_ARC_CURR_IN_REG
/* gp already saved on stack: now load with "current" */
GET_CURR_TASK_ON_CPU gp
#endif
.endm
/*--------------------------------------------------------------
@@ -208,11 +205,8 @@
POP gp
RESTORE_R12_TO_R0
#ifdef CONFIG_ARC_CURR_IN_REG
ld r25, [sp, 12]
#endif
ld sp, [sp] /* restore original sp */
/* orig_r0, ECR, user_r25 skipped automatically */
/* orig_r0, ECR skipped automatically */
.endm
/* Dummy ECR values for Interrupts */
@@ -229,13 +223,6 @@
SWITCH_TO_KERNEL_STK
#ifdef CONFIG_ARC_CURR_IN_REG
/* Treat r25 as scratch reg (save on stack) and load with "current" */
PUSH r25
GET_CURR_TASK_ON_CPU r25
#else
sub sp, sp, 4
#endif
PUSH 0x003\LVL\()abcd /* Dummy ECR */
sub sp, sp, 8 /* skip orig_r0 (not needed)
@@ -255,6 +242,10 @@
PUSHAX lp_start
PUSHAX bta_l\LVL\()
#ifdef CONFIG_ARC_CURR_IN_REG
/* gp already saved on stack: now load with "current" */
GET_CURR_TASK_ON_CPU gp
#endif
.endm
/*--------------------------------------------------------------
@@ -282,11 +273,7 @@
POP gp
RESTORE_R12_TO_R0
#ifdef CONFIG_ARC_CURR_IN_REG
ld r25, [sp, 12]
#endif
ld sp, [sp] /* restore original sp */
/* orig_r0, ECR, user_r25 skipped automatically */
ld sp, [sp] /* restore original sp; orig_r0, ECR skipped implicitly */
.endm
/* Get thread_info of "current" tsk */
+31 -80
View File
@@ -91,7 +91,7 @@
* Helpers to save/restore callee-saved regs:
* used by several macros below
*-------------------------------------------------------------*/
.macro SAVE_R13_TO_R24
.macro SAVE_R13_TO_R25
PUSH r13
PUSH r14
PUSH r15
@@ -104,9 +104,11 @@
PUSH r22
PUSH r23
PUSH r24
PUSH r25
.endm
.macro RESTORE_R24_TO_R13
.macro RESTORE_R25_TO_R13
POP r25
POP r24
POP r23
POP r22
@@ -121,81 +123,31 @@
POP r13
.endm
/*--------------------------------------------------------------
* Collect User Mode callee regs as struct callee_regs - needed by
* fork/do_signal/unaligned-access-emulation.
* (By default only scratch regs are saved on entry to kernel)
*
* Special handling for r25 if used for caching Task Pointer.
* It would have been saved in task->thread.user_r25 already, but to keep
* the interface same it is copied into regular r25 placeholder in
* struct callee_regs.
*-------------------------------------------------------------*/
/*
* save user mode callee regs as struct callee_regs
* - needed by fork/do_signal/unaligned-access-emulation.
*/
.macro SAVE_CALLEE_SAVED_USER
mov r12, sp ; save SP as ref to pt_regs
SAVE_R13_TO_R24
#ifdef CONFIG_ARC_CURR_IN_REG
; Retrieve orig r25 and save it with rest of callee_regs
ld r12, [r12, PT_user_r25]
PUSH r12
#else
PUSH r25
#endif
SAVE_R13_TO_R25
.endm
/*--------------------------------------------------------------
* Save kernel Mode callee regs at the time of Contect Switch.
*
* Special handling for r25 if used for caching Task Pointer.
* Kernel simply skips saving it since it will be loaded with
* incoming task pointer anyways
*-------------------------------------------------------------*/
.macro SAVE_CALLEE_SAVED_KERNEL
SAVE_R13_TO_R24
#ifdef CONFIG_ARC_CURR_IN_REG
sub sp, sp, 4
#else
PUSH r25
#endif
.endm
/*--------------------------------------------------------------
* Opposite of SAVE_CALLEE_SAVED_KERNEL
*-------------------------------------------------------------*/
.macro RESTORE_CALLEE_SAVED_KERNEL
#ifdef CONFIG_ARC_CURR_IN_REG
add sp, sp, 4 /* skip usual r25 placeholder */
#else
POP r25
#endif
RESTORE_R24_TO_R13
.endm
/*--------------------------------------------------------------
* Opposite of SAVE_CALLEE_SAVED_USER
*
* ptrace tracer or unaligned-access fixup might have changed a user mode
* callee reg which is saved back to usual r25 storage location
*-------------------------------------------------------------*/
/*
* restore user mode callee regs as struct callee_regs
* - could have been changed by ptrace tracer or unaligned-access fixup
*/
.macro RESTORE_CALLEE_SAVED_USER
RESTORE_R25_TO_R13
.endm
#ifdef CONFIG_ARC_CURR_IN_REG
POP r12
#else
POP r25
#endif
RESTORE_R24_TO_R13
/*
* save/restore kernel mode callee regs at the time of context switch
*/
.macro SAVE_CALLEE_SAVED_KERNEL
SAVE_R13_TO_R25
.endm
; SP is back to start of pt_regs
#ifdef CONFIG_ARC_CURR_IN_REG
st r12, [sp, PT_user_r25]
#endif
.macro RESTORE_CALLEE_SAVED_KERNEL
RESTORE_R25_TO_R13
.endm
/*--------------------------------------------------------------
@@ -231,10 +183,10 @@
#ifdef CONFIG_SMP
/*-------------------------------------------------
/*
* Retrieve the current running task on this CPU
* 1. Determine curr CPU id.
* 2. Use it to index into _current_task[ ]
* - loads it from backing _current_task[] (and can't use the
* caching reg for current task
*/
.macro GET_CURR_TASK_ON_CPU reg
GET_CPU_ID \reg
@@ -256,7 +208,7 @@
add2 \tmp, @_current_task, \tmp
st \tsk, [\tmp]
#ifdef CONFIG_ARC_CURR_IN_REG
mov r25, \tsk
mov gp, \tsk
#endif
.endm
@@ -271,21 +223,20 @@
.macro SET_CURR_TASK_ON_CPU tsk, tmp
st \tsk, [@_current_task]
#ifdef CONFIG_ARC_CURR_IN_REG
mov r25, \tsk
mov gp, \tsk
#endif
.endm
#endif /* SMP / UNI */
/* ------------------------------------------------------------------
/*
* Get the ptr to some field of Current Task at @off in task struct
* -Uses r25 for Current task ptr if that is enabled
* - Uses current task cached in reg if enabled
*/
#ifdef CONFIG_ARC_CURR_IN_REG
.macro GET_CURR_TASK_FIELD_PTR off, reg
add \reg, r25, \off
add \reg, gp, \off
.endm
#else
+1 -5
View File
@@ -52,11 +52,9 @@ struct pt_regs {
};
unsigned long event;
};
unsigned long user_r25;
};
#define MAX_REG_OFFSET offsetof(struct pt_regs, user_r25)
#define MAX_REG_OFFSET offsetof(struct pt_regs, event)
#else
@@ -79,8 +77,6 @@ struct pt_regs {
unsigned long bta; /* bta_l1, bta_l2, erbta */
unsigned long user_r25;
unsigned long r26; /* gp */
unsigned long fp;
unsigned long sp; /* user/kernel sp depending on where we came from */