1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com) 4 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 5 */ 6 7 #ifndef __ASM_ARC_ENTRY_H 8 #define __ASM_ARC_ENTRY_H 9 10 #include <asm/unistd.h> /* For NR_syscalls defination */ 11 #include <asm/arcregs.h> 12 #include <asm/ptrace.h> 13 #include <asm/processor.h> /* For VMALLOC_START */ 14 #include <asm/mmu.h> 15 16 #ifdef __ASSEMBLY__ 17 18 #ifdef CONFIG_ISA_ARCOMPACT 19 #include <asm/entry-compact.h> /* ISA specific bits */ 20 #else 21 #include <asm/entry-arcv2.h> 22 #endif 23 24 /* Note on the LD/ST addr modes with addr reg wback 25 * 26 * LD.a same as LD.aw 27 * 28 * LD.a reg1, [reg2, x] => Pre Incr 29 * Eff Addr for load = [reg2 + x] 30 * 31 * LD.ab reg1, [reg2, x] => Post Incr 32 * Eff Addr for load = [reg2] 33 */ 34 35 .macro PUSH reg 36 st.a \reg, [sp, -4] 37 .endm 38 39 .macro PUSHAX aux 40 lr r9, [\aux] 41 PUSH r9 42 .endm 43 44 .macro POP reg 45 ld.ab \reg, [sp, 4] 46 .endm 47 48 .macro POPAX aux 49 POP r9 50 sr r9, [\aux] 51 .endm 52 53 /*-------------------------------------------------------------- 54 * Helpers to save/restore Scratch Regs: 55 * used by Interrupt/Exception Prologue/Epilogue 56 *-------------------------------------------------------------*/ 57 .macro SAVE_R0_TO_R12 58 PUSH r0 59 PUSH r1 60 PUSH r2 61 PUSH r3 62 PUSH r4 63 PUSH r5 64 PUSH r6 65 PUSH r7 66 PUSH r8 67 PUSH r9 68 PUSH r10 69 PUSH r11 70 PUSH r12 71 .endm 72 73 .macro RESTORE_R12_TO_R0 74 POP r12 75 POP r11 76 POP r10 77 POP r9 78 POP r8 79 POP r7 80 POP r6 81 POP r5 82 POP r4 83 POP r3 84 POP r2 85 POP r1 86 POP r0 87 88 .endm 89 90 /*-------------------------------------------------------------- 91 * Helpers to save/restore callee-saved regs: 92 * used by several macros below 93 *-------------------------------------------------------------*/ 94 .macro SAVE_R13_TO_R24 95 PUSH r13 96 PUSH r14 97 PUSH r15 98 PUSH r16 99 PUSH r17 100 PUSH r18 101 PUSH r19 102 PUSH r20 103 PUSH r21 104 PUSH r22 105 PUSH r23 106 PUSH r24 107 .endm 108 109 .macro RESTORE_R24_TO_R13 110 POP r24 111 POP r23 112 POP r22 113 POP r21 114 POP r20 115 POP r19 116 POP r18 117 POP r17 118 POP r16 119 POP r15 120 POP r14 121 POP r13 122 .endm 123 124 /*-------------------------------------------------------------- 125 * Collect User Mode callee regs as struct callee_regs - needed by 126 * fork/do_signal/unaligned-access-emulation. 127 * (By default only scratch regs are saved on entry to kernel) 128 * 129 * Special handling for r25 if used for caching Task Pointer. 130 * It would have been saved in task->thread.user_r25 already, but to keep 131 * the interface same it is copied into regular r25 placeholder in 132 * struct callee_regs. 133 *-------------------------------------------------------------*/ 134 .macro SAVE_CALLEE_SAVED_USER 135 136 mov r12, sp ; save SP as ref to pt_regs 137 SAVE_R13_TO_R24 138 139 #ifdef CONFIG_ARC_CURR_IN_REG 140 ; Retrieve orig r25 and save it with rest of callee_regs 141 ld r12, [r12, PT_user_r25] 142 PUSH r12 143 #else 144 PUSH r25 145 #endif 146 147 .endm 148 149 /*-------------------------------------------------------------- 150 * Save kernel Mode callee regs at the time of Contect Switch. 151 * 152 * Special handling for r25 if used for caching Task Pointer. 153 * Kernel simply skips saving it since it will be loaded with 154 * incoming task pointer anyways 155 *-------------------------------------------------------------*/ 156 .macro SAVE_CALLEE_SAVED_KERNEL 157 158 SAVE_R13_TO_R24 159 160 #ifdef CONFIG_ARC_CURR_IN_REG 161 sub sp, sp, 4 162 #else 163 PUSH r25 164 #endif 165 .endm 166 167 /*-------------------------------------------------------------- 168 * Opposite of SAVE_CALLEE_SAVED_KERNEL 169 *-------------------------------------------------------------*/ 170 .macro RESTORE_CALLEE_SAVED_KERNEL 171 172 #ifdef CONFIG_ARC_CURR_IN_REG 173 add sp, sp, 4 /* skip usual r25 placeholder */ 174 #else 175 POP r25 176 #endif 177 RESTORE_R24_TO_R13 178 .endm 179 180 /*-------------------------------------------------------------- 181 * Opposite of SAVE_CALLEE_SAVED_USER 182 * 183 * ptrace tracer or unaligned-access fixup might have changed a user mode 184 * callee reg which is saved back to usual r25 storage location 185 *-------------------------------------------------------------*/ 186 .macro RESTORE_CALLEE_SAVED_USER 187 188 #ifdef CONFIG_ARC_CURR_IN_REG 189 POP r12 190 #else 191 POP r25 192 #endif 193 RESTORE_R24_TO_R13 194 195 ; SP is back to start of pt_regs 196 #ifdef CONFIG_ARC_CURR_IN_REG 197 st r12, [sp, PT_user_r25] 198 #endif 199 .endm 200 201 /*-------------------------------------------------------------- 202 * Super FAST Restore callee saved regs by simply re-adjusting SP 203 *-------------------------------------------------------------*/ 204 .macro DISCARD_CALLEE_SAVED_USER 205 add sp, sp, SZ_CALLEE_REGS 206 .endm 207 208 /*------------------------------------------------------------- 209 * given a tsk struct, get to the base of it's kernel mode stack 210 * tsk->thread_info is really a PAGE, whose bottom hoists stack 211 * which grows upwards towards thread_info 212 *------------------------------------------------------------*/ 213 214 .macro GET_TSK_STACK_BASE tsk, out 215 216 /* Get task->thread_info (this is essentially start of a PAGE) */ 217 ld \out, [\tsk, TASK_THREAD_INFO] 218 219 /* Go to end of page where stack begins (grows upwards) */ 220 add2 \out, \out, (THREAD_SIZE)/4 221 222 .endm 223 224 /* 225 * @reg [OUT] thread_info->flags of "current" 226 */ 227 .macro GET_CURR_THR_INFO_FLAGS reg 228 GET_CURR_THR_INFO_FROM_SP \reg 229 ld \reg, [\reg, THREAD_INFO_FLAGS] 230 .endm 231 232 #ifdef CONFIG_SMP 233 234 /*------------------------------------------------- 235 * Retrieve the current running task on this CPU 236 * 1. Determine curr CPU id. 237 * 2. Use it to index into _current_task[ ] 238 */ 239 .macro GET_CURR_TASK_ON_CPU reg 240 GET_CPU_ID \reg 241 ld.as \reg, [@_current_task, \reg] 242 .endm 243 244 /*------------------------------------------------- 245 * Save a new task as the "current" task on this CPU 246 * 1. Determine curr CPU id. 247 * 2. Use it to index into _current_task[ ] 248 * 249 * Coded differently than GET_CURR_TASK_ON_CPU (which uses LD.AS) 250 * because ST r0, [r1, offset] can ONLY have s9 @offset 251 * while LD can take s9 (4 byte insn) or LIMM (8 byte insn) 252 */ 253 254 .macro SET_CURR_TASK_ON_CPU tsk, tmp 255 GET_CPU_ID \tmp 256 add2 \tmp, @_current_task, \tmp 257 st \tsk, [\tmp] 258 #ifdef CONFIG_ARC_CURR_IN_REG 259 mov r25, \tsk 260 #endif 261 262 .endm 263 264 265 #else /* Uniprocessor implementation of macros */ 266 267 .macro GET_CURR_TASK_ON_CPU reg 268 ld \reg, [@_current_task] 269 .endm 270 271 .macro SET_CURR_TASK_ON_CPU tsk, tmp 272 st \tsk, [@_current_task] 273 #ifdef CONFIG_ARC_CURR_IN_REG 274 mov r25, \tsk 275 #endif 276 .endm 277 278 #endif /* SMP / UNI */ 279 280 /* ------------------------------------------------------------------ 281 * Get the ptr to some field of Current Task at @off in task struct 282 * -Uses r25 for Current task ptr if that is enabled 283 */ 284 285 #ifdef CONFIG_ARC_CURR_IN_REG 286 287 .macro GET_CURR_TASK_FIELD_PTR off, reg 288 add \reg, r25, \off 289 .endm 290 291 #else 292 293 .macro GET_CURR_TASK_FIELD_PTR off, reg 294 GET_CURR_TASK_ON_CPU \reg 295 add \reg, \reg, \off 296 .endm 297 298 #endif /* CONFIG_ARC_CURR_IN_REG */ 299 300 #else /* !__ASSEMBLY__ */ 301 302 extern void do_signal(struct pt_regs *); 303 extern void do_notify_resume(struct pt_regs *); 304 extern int do_privilege_fault(unsigned long, struct pt_regs *); 305 extern int do_extension_fault(unsigned long, struct pt_regs *); 306 extern int insterror_is_error(unsigned long, struct pt_regs *); 307 extern int do_memory_error(unsigned long, struct pt_regs *); 308 extern int trap_is_brkpt(unsigned long, struct pt_regs *); 309 extern int do_misaligned_error(unsigned long, struct pt_regs *); 310 extern int do_trap5_error(unsigned long, struct pt_regs *); 311 extern int do_misaligned_access(unsigned long, struct pt_regs *, struct callee_regs *); 312 extern void do_machine_check_fault(unsigned long, struct pt_regs *); 313 extern void do_non_swi_trap(unsigned long, struct pt_regs *); 314 extern void do_insterror_or_kprobe(unsigned long, struct pt_regs *); 315 extern void do_page_fault(unsigned long, struct pt_regs *); 316 317 #endif 318 319 #endif /* __ASM_ARC_ENTRY_H */ 320