Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+60 -156
+3 -3
arch/arc/Kconfig
··· 492 492 kernel-user gutter) 493 493 494 494 config ARC_CURR_IN_REG 495 - bool "Dedicate Register r25 for current_task pointer" 495 + bool "cache current task pointer in gp" 496 496 default y 497 497 help 498 - This reserved Register R25 to point to Current Task in 499 - kernel mode. This saves memory access for each such access 498 + This reserves gp register to point to Current Task in 499 + kernel mode eliding memory access for each access 500 500 501 501 502 502 config ARC_EMUL_UNALIGNED
+3 -3
arch/arc/Makefile
··· 28 28 endif 29 29 endif 30 30 31 - 32 31 ifdef CONFIG_ARC_CURR_IN_REG 33 32 # For a global register definition, make sure it gets passed to every file 34 33 # We had a customer reported bug where some code built in kernel was NOT using 35 - # any kernel headers, and missing the r25 global register 34 + # any kernel headers, and missing the global register 36 35 # Can't do unconditionally because of recursive include issues 37 36 # due to <linux/thread_info.h> 38 37 LINUXINCLUDE += -include $(srctree)/arch/arc/include/asm/current.h 38 + cflags-y += -ffixed-gp 39 39 endif 40 40 41 41 cflags-y += -fsection-anchors ··· 67 67 # small data is default for elf32 tool-chain. If not usable, disable it 68 68 # This also allows repurposing GP as scratch reg to gcc reg allocator 69 69 disable_small_data := y 70 - cflags-$(disable_small_data) += -mno-sdata -fcall-used-gp 70 + cflags-$(disable_small_data) += -mno-sdata 71 71 72 72 cflags-$(CONFIG_CPU_BIG_ENDIAN) += -mbig-endian 73 73 ldflags-$(CONFIG_CPU_BIG_ENDIAN) += -EB
+1 -1
arch/arc/include/asm/current.h
··· 13 13 14 14 #ifdef CONFIG_ARC_CURR_IN_REG 15 15 16 - register struct task_struct *curr_arc asm("r25"); 16 + register struct task_struct *curr_arc asm("gp"); 17 17 #define current (curr_arc) 18 18 19 19 #else
+6 -11
arch/arc/include/asm/entry-arcv2.h
··· 18 18 * | orig_r0 | 19 19 * | event/ECR | 20 20 * | bta | 21 - * | user_r25 | 22 21 * | gp | 23 22 * | fp | 24 23 * | sp | ··· 55 56 ; hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE 56 57 ; 4. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI 57 58 ; 58 - ; (B) Manually saved some regs: r12,r25,r30, sp,fp,gp, ACCL pair 59 + ; (B) Manually saved some regs: r12,r30, sp,fp,gp, ACCL pair 59 60 60 61 #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE 61 62 ; carve pt_regs on stack (case #3), PC/STAT32 already on stack ··· 156 157 157 158 st r10, [sp, PT_sp] ; SP (pt_regs->sp) 158 159 159 - #ifdef CONFIG_ARC_CURR_IN_REG 160 - st r25, [sp, PT_user_r25] 161 - GET_CURR_TASK_ON_CPU r25 162 - #endif 163 - 164 160 #ifdef CONFIG_ARC_HAS_ACCL_REGS 165 161 ST2 r58, r59, PT_r58 166 162 #endif 167 163 168 164 /* clobbers r10, r11 registers pair */ 169 165 DSP_SAVE_REGFILE_IRQ 166 + 167 + #ifdef CONFIG_ARC_CURR_IN_REG 168 + GET_CURR_TASK_ON_CPU gp 169 + #endif 170 + 170 171 .endm 171 172 172 173 /*------------------------------------------------------------------------*/ ··· 186 187 ld r10, [sp, PT_sp] ; SP (pt_regs->sp) 187 188 sr r10, [AUX_USER_SP] 188 189 1: 189 - 190 - #ifdef CONFIG_ARC_CURR_IN_REG 191 - ld r25, [sp, PT_user_r25] 192 - #endif 193 190 194 191 /* clobbers r10, r11 registers pair */ 195 192 DSP_RESTORE_REGFILE_IRQ
+11 -24
arch/arc/include/asm/entry-compact.h
··· 151 151 /* ARC700 doesn't provide auto-stack switching */ 152 152 SWITCH_TO_KERNEL_STK 153 153 154 - #ifdef CONFIG_ARC_CURR_IN_REG 155 - /* Treat r25 as scratch reg (save on stack) and load with "current" */ 156 - PUSH r25 157 - GET_CURR_TASK_ON_CPU r25 158 - #else 159 - sub sp, sp, 4 160 - #endif 161 - 162 154 st.a r0, [sp, -8] /* orig_r0 needed for syscall (skip ECR slot) */ 163 155 sub sp, sp, 4 /* skip pt_regs->sp, already saved above */ 164 156 ··· 171 179 172 180 lr r10, [ecr] 173 181 st r10, [sp, PT_event] /* EV_Trap expects r10 to have ECR */ 182 + 183 + #ifdef CONFIG_ARC_CURR_IN_REG 184 + /* gp already saved on stack: now load with "current" */ 185 + GET_CURR_TASK_ON_CPU gp 186 + #endif 174 187 .endm 175 188 176 189 /*-------------------------------------------------------------- ··· 205 208 POP gp 206 209 RESTORE_R12_TO_R0 207 210 208 - #ifdef CONFIG_ARC_CURR_IN_REG 209 - ld r25, [sp, 12] 210 - #endif 211 211 ld sp, [sp] /* restore original sp */ 212 - /* orig_r0, ECR, user_r25 skipped automatically */ 212 + /* orig_r0, ECR skipped automatically */ 213 213 .endm 214 214 215 215 /* Dummy ECR values for Interrupts */ ··· 223 229 224 230 SWITCH_TO_KERNEL_STK 225 231 226 - #ifdef CONFIG_ARC_CURR_IN_REG 227 - /* Treat r25 as scratch reg (save on stack) and load with "current" */ 228 - PUSH r25 229 - GET_CURR_TASK_ON_CPU r25 230 - #else 231 - sub sp, sp, 4 232 - #endif 233 232 234 233 PUSH 0x003\LVL\()abcd /* Dummy ECR */ 235 234 sub sp, sp, 8 /* skip orig_r0 (not needed) ··· 242 255 PUSHAX lp_start 243 256 PUSHAX bta_l\LVL\() 244 257 258 + #ifdef CONFIG_ARC_CURR_IN_REG 259 + /* gp already saved on stack: now load with "current" */ 260 + GET_CURR_TASK_ON_CPU gp 261 + #endif 245 262 .endm 246 263 247 264 /*-------------------------------------------------------------- ··· 273 282 POP gp 274 283 RESTORE_R12_TO_R0 275 284 276 - #ifdef CONFIG_ARC_CURR_IN_REG 277 - ld r25, [sp, 12] 278 - #endif 279 - ld sp, [sp] /* restore original sp */ 280 - /* orig_r0, ECR, user_r25 skipped automatically */ 285 + ld sp, [sp] /* restore original sp; orig_r0, ECR skipped implicitly */ 281 286 .endm 282 287 283 288 /* Get thread_info of "current" tsk */
+31 -80
arch/arc/include/asm/entry.h
··· 91 91 * Helpers to save/restore callee-saved regs: 92 92 * used by several macros below 93 93 *-------------------------------------------------------------*/ 94 - .macro SAVE_R13_TO_R24 94 + .macro SAVE_R13_TO_R25 95 95 PUSH r13 96 96 PUSH r14 97 97 PUSH r15 ··· 104 104 PUSH r22 105 105 PUSH r23 106 106 PUSH r24 107 + PUSH r25 107 108 .endm 108 109 109 - .macro RESTORE_R24_TO_R13 110 + .macro RESTORE_R25_TO_R13 111 + POP r25 110 112 POP r24 111 113 POP r23 112 114 POP r22 ··· 123 121 POP r13 124 122 .endm 125 123 126 - /*-------------------------------------------------------------- 127 - * Collect User Mode callee regs as struct callee_regs - needed by 128 - * fork/do_signal/unaligned-access-emulation. 129 - * (By default only scratch regs are saved on entry to kernel) 130 - * 131 - * Special handling for r25 if used for caching Task Pointer. 132 - * It would have been saved in task->thread.user_r25 already, but to keep 133 - * the interface same it is copied into regular r25 placeholder in 134 - * struct callee_regs. 135 - *-------------------------------------------------------------*/ 124 + /* 125 + * save user mode callee regs as struct callee_regs 126 + * - needed by fork/do_signal/unaligned-access-emulation. 127 + */ 136 128 .macro SAVE_CALLEE_SAVED_USER 137 - 138 - mov r12, sp ; save SP as ref to pt_regs 139 - SAVE_R13_TO_R24 140 - 141 - #ifdef CONFIG_ARC_CURR_IN_REG 142 - ; Retrieve orig r25 and save it with rest of callee_regs 143 - ld r12, [r12, PT_user_r25] 144 - PUSH r12 145 - #else 146 - PUSH r25 147 - #endif 148 - 129 + SAVE_R13_TO_R25 149 130 .endm 150 131 151 - /*-------------------------------------------------------------- 152 - * Save kernel Mode callee regs at the time of Contect Switch. 153 - * 154 - * Special handling for r25 if used for caching Task Pointer. 155 - * Kernel simply skips saving it since it will be loaded with 156 - * incoming task pointer anyways 157 - *-------------------------------------------------------------*/ 158 - .macro SAVE_CALLEE_SAVED_KERNEL 159 - 160 - SAVE_R13_TO_R24 161 - 162 - #ifdef CONFIG_ARC_CURR_IN_REG 163 - sub sp, sp, 4 164 - #else 165 - PUSH r25 166 - #endif 167 - .endm 168 - 169 - /*-------------------------------------------------------------- 170 - * Opposite of SAVE_CALLEE_SAVED_KERNEL 171 - *-------------------------------------------------------------*/ 172 - .macro RESTORE_CALLEE_SAVED_KERNEL 173 - 174 - #ifdef CONFIG_ARC_CURR_IN_REG 175 - add sp, sp, 4 /* skip usual r25 placeholder */ 176 - #else 177 - POP r25 178 - #endif 179 - RESTORE_R24_TO_R13 180 - .endm 181 - 182 - /*-------------------------------------------------------------- 183 - * Opposite of SAVE_CALLEE_SAVED_USER 184 - * 185 - * ptrace tracer or unaligned-access fixup might have changed a user mode 186 - * callee reg which is saved back to usual r25 storage location 187 - *-------------------------------------------------------------*/ 132 + /* 133 + * restore user mode callee regs as struct callee_regs 134 + * - could have been changed by ptrace tracer or unaligned-access fixup 135 + */ 188 136 .macro RESTORE_CALLEE_SAVED_USER 137 + RESTORE_R25_TO_R13 138 + .endm 189 139 190 - #ifdef CONFIG_ARC_CURR_IN_REG 191 - POP r12 192 - #else 193 - POP r25 194 - #endif 195 - RESTORE_R24_TO_R13 140 + /* 141 + * save/restore kernel mode callee regs at the time of context switch 142 + */ 143 + .macro SAVE_CALLEE_SAVED_KERNEL 144 + SAVE_R13_TO_R25 145 + .endm 196 146 197 - ; SP is back to start of pt_regs 198 - #ifdef CONFIG_ARC_CURR_IN_REG 199 - st r12, [sp, PT_user_r25] 200 - #endif 147 + .macro RESTORE_CALLEE_SAVED_KERNEL 148 + RESTORE_R25_TO_R13 201 149 .endm 202 150 203 151 /*-------------------------------------------------------------- ··· 183 231 184 232 #ifdef CONFIG_SMP 185 233 186 - /*------------------------------------------------- 234 + /* 187 235 * Retrieve the current running task on this CPU 188 - * 1. Determine curr CPU id. 189 - * 2. Use it to index into _current_task[ ] 236 + * - loads it from backing _current_task[] (and can't use the 237 + * caching reg for current task 190 238 */ 191 239 .macro GET_CURR_TASK_ON_CPU reg 192 240 GET_CPU_ID \reg ··· 208 256 add2 \tmp, @_current_task, \tmp 209 257 st \tsk, [\tmp] 210 258 #ifdef CONFIG_ARC_CURR_IN_REG 211 - mov r25, \tsk 259 + mov gp, \tsk 212 260 #endif 213 261 214 262 .endm ··· 223 271 .macro SET_CURR_TASK_ON_CPU tsk, tmp 224 272 st \tsk, [@_current_task] 225 273 #ifdef CONFIG_ARC_CURR_IN_REG 226 - mov r25, \tsk 274 + mov gp, \tsk 227 275 #endif 228 276 .endm 229 277 230 278 #endif /* SMP / UNI */ 231 279 232 - /* ------------------------------------------------------------------ 280 + /* 233 281 * Get the ptr to some field of Current Task at @off in task struct 234 - * -Uses r25 for Current task ptr if that is enabled 282 + * - Uses current task cached in reg if enabled 235 283 */ 236 - 237 284 #ifdef CONFIG_ARC_CURR_IN_REG 238 285 239 286 .macro GET_CURR_TASK_FIELD_PTR off, reg 240 - add \reg, r25, \off 287 + add \reg, gp, \off 241 288 .endm 242 289 243 290 #else
+1 -5
arch/arc/include/asm/ptrace.h
··· 52 52 }; 53 53 unsigned long event; 54 54 }; 55 - 56 - unsigned long user_r25; 57 55 }; 58 56 59 - #define MAX_REG_OFFSET offsetof(struct pt_regs, user_r25) 57 + #define MAX_REG_OFFSET offsetof(struct pt_regs, event) 60 58 61 59 #else 62 60 ··· 76 78 }; 77 79 78 80 unsigned long bta; /* bta_l1, bta_l2, erbta */ 79 - 80 - unsigned long user_r25; 81 81 82 82 unsigned long r26; /* gp */ 83 83 unsigned long fp;
-2
arch/arc/kernel/asm-offsets.c
··· 63 63 DEFINE(PT_blink, offsetof(struct pt_regs, blink)); 64 64 DEFINE(PT_lpe, offsetof(struct pt_regs, lp_end)); 65 65 DEFINE(PT_lpc, offsetof(struct pt_regs, lp_count)); 66 - DEFINE(PT_user_r25, offsetof(struct pt_regs, user_r25)); 67 - 68 66 DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs)); 69 67 DEFINE(SZ_PT_REGS, sizeof(struct pt_regs)); 70 68
+2 -11
arch/arc/kernel/ctx_sw.c
··· 38 38 "st.a r22, [sp, -4] \n\t" 39 39 "st.a r23, [sp, -4] \n\t" 40 40 "st.a r24, [sp, -4] \n\t" 41 - #ifndef CONFIG_ARC_CURR_IN_REG 42 41 "st.a r25, [sp, -4] \n\t" 43 - #else 44 - "sub sp, sp, 4 \n\t" /* usual r25 placeholder */ 45 - #endif 46 42 47 43 /* set ksp of outgoing task in tsk->thread.ksp */ 48 44 #if KSP_WORD_OFF <= 255 ··· 54 58 55 59 /* 56 60 * setup _current_task with incoming tsk. 57 - * optionally, set r25 to that as well 61 + * optionally, set caching reg to that as well 58 62 * For SMP extra work to get to &_current_task[cpu] 59 63 * (open coded SET_CURR_TASK_ON_CPU) 60 64 */ ··· 68 72 "st %2, [r24] \n\t" 69 73 #endif 70 74 #ifdef CONFIG_ARC_CURR_IN_REG 71 - "mov r25, %2 \n\t" 75 + "mov gp, %2 \n\t" 72 76 #endif 73 77 74 78 /* get ksp of incoming task from tsk->thread.ksp */ 75 79 "ld.as sp, [%2, %1] \n\t" 76 80 77 81 /* start loading it's CALLEE reg file */ 78 - 79 - #ifndef CONFIG_ARC_CURR_IN_REG 80 82 "ld.ab r25, [sp, 4] \n\t" 81 - #else 82 - "add sp, sp, 4 \n\t" 83 - #endif 84 83 "ld.ab r24, [sp, 4] \n\t" 85 84 "ld.ab r23, [sp, 4] \n\t" 86 85 "ld.ab r22, [sp, 4] \n\t"
+1 -1
arch/arc/kernel/ctx_sw_asm.S
··· 49 49 SET_CURR_TASK_ON_CPU r1, r3 50 50 51 51 /* reload SP with kernel mode stack pointer in task->thread.ksp */ 52 - ld.as sp, [r1, (TASK_THREAD + THREAD_KSP)/4] 52 + ld.as sp, [r1, KSP_WORD_OFF] 53 53 54 54 /* restore the registers */ 55 55 RESTORE_CALLEE_SAVED_KERNEL
+1 -2
arch/arc/kernel/entry.S
··· 210 210 211 211 ; Save callee regs in case gdb wants to have a look 212 212 ; SP will grow up by size of CALLEE Reg-File 213 - ; NOTE: clobbers r12 214 213 SAVE_CALLEE_SAVED_USER 215 214 216 215 ; save location of saved Callee Regs @ thread_struct->pc ··· 317 318 ; tracer might call PEEKUSR(CALLEE reg) 318 319 ; 319 320 ; NOTE: SP will grow up by size of CALLEE Reg-File 320 - SAVE_CALLEE_SAVED_USER ; clobbers r12 321 + SAVE_CALLEE_SAVED_USER 321 322 322 323 ; save location of saved Callee Regs @ thread_struct->callee 323 324 GET_CURR_TASK_FIELD_PTR TASK_THREAD, r10
-11
arch/arc/kernel/process.c
··· 162 162 * | SP | 163 163 * | orig_r0 | 164 164 * | event/ECR | 165 - * | user_r25 | 166 165 * ------------------ <===== END of PAGE 167 166 */ 168 167 int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) ··· 241 242 * ensures those regs are not clobbered all the way to RTIE to usermode 242 243 */ 243 244 c_callee->r25 = task_thread_info(p)->thr_ptr; 244 - 245 - #ifdef CONFIG_ARC_CURR_IN_REG 246 - /* 247 - * setup usermode thread pointer #2: 248 - * however for this special use of r25 in kernel, __switch_to() sets 249 - * r25 for kernel needs and only in the final return path is usermode 250 - * r25 setup, from pt_regs->user_r25. So set that up as well 251 - */ 252 - c_regs->user_r25 = c_callee->r25; 253 - #endif 254 245 255 246 return 0; 256 247 }
-2
arch/arc/kernel/ptrace.c
··· 47 47 REG_OFFSET_NAME(sp), 48 48 REG_OFFSET_NAME(orig_r0), 49 49 REG_OFFSET_NAME(event), 50 - REG_OFFSET_NAME(user_r25), 51 50 REG_OFFSET_END, 52 51 }; 53 52 ··· 56 57 REG_OFFSET_NAME(orig_r0), 57 58 REG_OFFSET_NAME(event), 58 59 REG_OFFSET_NAME(bta), 59 - REG_OFFSET_NAME(user_r25), 60 60 REG_OFFSET_NAME(r26), 61 61 REG_OFFSET_NAME(fp), 62 62 REG_OFFSET_NAME(sp),