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 * Vineetg: March 2009 (Supporting 2 levels of Interrupts) 7 * Stack switching code can no longer reliably rely on the fact that 8 * if we are NOT in user mode, stack is switched to kernel mode. 9 * e.g. L2 IRQ interrupted a L1 ISR which had not yet completed 10 * it's prologue including stack switching from user mode 11 * 12 * Vineetg: Aug 28th 2008: Bug #94984 13 * -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap 14 * Normally CPU does this automatically, however when doing FAKE rtie, 15 * we also need to explicitly do this. The problem in macros 16 * FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit 17 * was being "CLEARED" rather then "SET". Actually "SET" clears ZOL context 18 * 19 * Vineetg: May 5th 2008 20 * -Modified CALLEE_REG save/restore macros to handle the fact that 21 * r25 contains the kernel current task ptr 22 * - Defined Stack Switching Macro to be reused in all intr/excp hdlrs 23 * - Shaved off 11 instructions from RESTORE_ALL_INT1 by using the 24 * address Write back load ld.ab instead of separate ld/add instn 25 * 26 * Amit Bhor, Sameer Dhavale: Codito Technologies 2004 27 */ 28 29 #ifndef __ASM_ARC_ENTRY_COMPACT_H 30 #define __ASM_ARC_ENTRY_COMPACT_H 31 32 #include <asm/asm-offsets.h> 33 #include <asm/irqflags-compact.h> 34 #include <asm/thread_info.h> /* For THREAD_SIZE */ 35 36 /* Note on the LD/ST addr modes with addr reg wback 37 * 38 * LD.a same as LD.aw 39 * 40 * LD.a reg1, [reg2, x] => Pre Incr 41 * Eff Addr for load = [reg2 + x] 42 * 43 * LD.ab reg1, [reg2, x] => Post Incr 44 * Eff Addr for load = [reg2] 45 */ 46 47 .macro PUSHAX aux 48 lr r9, [\aux] 49 push r9 50 .endm 51 52 .macro POPAX aux 53 pop r9 54 sr r9, [\aux] 55 .endm 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 .endm 88 89 .macro SAVE_ABI_CALLEE_REGS 90 push r13 91 push r14 92 push r15 93 push r16 94 push r17 95 push r18 96 push r19 97 push r20 98 push r21 99 push r22 100 push r23 101 push r24 102 push r25 103 .endm 104 105 .macro RESTORE_ABI_CALLEE_REGS 106 pop r25 107 pop r24 108 pop r23 109 pop r22 110 pop r21 111 pop r20 112 pop r19 113 pop r18 114 pop r17 115 pop r16 116 pop r15 117 pop r14 118 pop r13 119 .endm 120 121 /*-------------------------------------------------------------- 122 * Switch to Kernel Mode stack if SP points to User Mode stack 123 * 124 * Entry : r9 contains pre-IRQ/exception/trap status32 125 * Exit : SP set to K mode stack 126 * SP at the time of entry (K/U) saved @ pt_regs->sp 127 * Clobbers: r9 128 *-------------------------------------------------------------*/ 129 130 .macro SWITCH_TO_KERNEL_STK 131 132 /* User Mode when this happened ? Yes: Proceed to switch stack */ 133 bbit1 r9, STATUS_U_BIT, 88f 134 135 /* OK we were already in kernel mode when this event happened, thus can 136 * assume SP is kernel mode SP. _NO_ need to do any stack switching 137 */ 138 139 #ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS 140 /* However.... 141 * If Level 2 Interrupts enabled, we may end up with a corner case: 142 * 1. User Task executing 143 * 2. L1 IRQ taken, ISR starts (CPU auto-switched to KERNEL mode) 144 * 3. But before it could switch SP from USER to KERNEL stack 145 * a L2 IRQ "Interrupts" L1 146 * Thay way although L2 IRQ happened in Kernel mode, stack is still 147 * not switched. 148 * To handle this, we may need to switch stack even if in kernel mode 149 * provided SP has values in range of USER mode stack ( < 0x7000_0000 ) 150 */ 151 brlo sp, VMALLOC_START, 88f 152 153 /* TODO: vineetg: 154 * We need to be a bit more cautious here. What if a kernel bug in 155 * L1 ISR, caused SP to go whaco (some small value which looks like 156 * USER stk) and then we take L2 ISR. 157 * Above brlo alone would treat it as a valid L1-L2 scenario 158 * instead of shouting around 159 * The only feasible way is to make sure this L2 happened in 160 * L1 prelogue ONLY i.e. ilink2 is less than a pre-set marker in 161 * L1 ISR before it switches stack 162 */ 163 164 #endif 165 166 /*------Intr/Ecxp happened in kernel mode, SP already setup ------ */ 167 /* save it nevertheless @ pt_regs->sp for uniformity */ 168 169 b.d 66f 170 st sp, [sp, PT_sp - SZ_PT_REGS] 171 172 88: /*------Intr/Ecxp happened in user mode, "switch" stack ------ */ 173 174 GET_CURR_TASK_ON_CPU r9 175 176 /* With current tsk in r9, get it's kernel mode stack base */ 177 GET_TSK_STACK_BASE r9, r9 178 179 /* save U mode SP @ pt_regs->sp */ 180 st sp, [r9, PT_sp - SZ_PT_REGS] 181 182 /* final SP switch */ 183 mov sp, r9 184 66: 185 .endm 186 187 /*------------------------------------------------------------ 188 * "FAKE" a rtie to return from CPU Exception context 189 * This is to re-enable Exceptions within exception 190 * Look at EV_ProtV to see how this is actually used 191 *-------------------------------------------------------------*/ 192 193 .macro FAKE_RET_FROM_EXCPN 194 195 lr r9, [status32] 196 bclr r9, r9, STATUS_AE_BIT 197 or r9, r9, (STATUS_E1_MASK|STATUS_E2_MASK) 198 sr r9, [erstatus] 199 mov r9, 55f 200 sr r9, [eret] 201 rtie 202 55: 203 .endm 204 205 /*-------------------------------------------------------------- 206 * For early Exception/ISR Prologue, a core reg is temporarily needed to 207 * code the rest of prolog (stack switching). This is done by stashing 208 * it to memory (non-SMP case) or SCRATCH0 Aux Reg (SMP). 209 * 210 * Before saving the full regfile - this reg is restored back, only 211 * to be saved again on kernel mode stack, as part of pt_regs. 212 *-------------------------------------------------------------*/ 213 .macro PROLOG_FREEUP_REG reg, mem 214 st \reg, [\mem] 215 .endm 216 217 .macro PROLOG_RESTORE_REG reg, mem 218 ld \reg, [\mem] 219 .endm 220 221 /*-------------------------------------------------------------- 222 * Exception Entry prologue 223 * -Switches stack to K mode (if not already) 224 * -Saves the register file 225 * 226 * After this it is safe to call the "C" handlers 227 *-------------------------------------------------------------*/ 228 .macro EXCEPTION_PROLOGUE_KEEP_AE 229 230 /* Need at least 1 reg to code the early exception prologue */ 231 PROLOG_FREEUP_REG r9, @ex_saved_reg1 232 233 /* U/K mode at time of exception (stack not switched if already K) */ 234 lr r9, [erstatus] 235 236 /* ARC700 doesn't provide auto-stack switching */ 237 SWITCH_TO_KERNEL_STK 238 239 st.a r0, [sp, -8] /* orig_r0 needed for syscall (skip ECR slot) */ 240 sub sp, sp, 4 /* skip pt_regs->sp, already saved above */ 241 242 /* Restore r9 used to code the early prologue */ 243 PROLOG_RESTORE_REG r9, @ex_saved_reg1 244 245 /* now we are ready to save the regfile */ 246 SAVE_R0_TO_R12 247 PUSH gp 248 PUSH fp 249 PUSH blink 250 PUSHAX eret 251 PUSHAX erstatus 252 PUSH lp_count 253 PUSHAX lp_end 254 PUSHAX lp_start 255 PUSHAX erbta 256 257 lr r10, [ecr] 258 st r10, [sp, PT_event] 259 260 #ifdef CONFIG_ARC_CURR_IN_REG 261 /* gp already saved on stack: now load with "current" */ 262 GET_CURR_TASK_ON_CPU gp 263 #endif 264 ; OUTPUT: r10 has ECR expected by EV_Trap 265 .endm 266 267 .macro EXCEPTION_PROLOGUE 268 269 EXCEPTION_PROLOGUE_KEEP_AE ; return ECR in r10 270 271 lr r0, [efa] 272 mov r1, sp 273 274 FAKE_RET_FROM_EXCPN ; clobbers r9 275 .endm 276 277 /*-------------------------------------------------------------- 278 * Restore all registers used by system call or Exceptions 279 * SP should always be pointing to the next free stack element 280 * when entering this macro. 281 * 282 * NOTE: 283 * 284 * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg 285 * for memory load operations. If used in that way interrupts are deffered 286 * by hardware and that is not good. 287 *-------------------------------------------------------------*/ 288 .macro EXCEPTION_EPILOGUE 289 290 POPAX erbta 291 POPAX lp_start 292 POPAX lp_end 293 294 POP r9 295 mov lp_count, r9 ;LD to lp_count is not allowed 296 297 POPAX erstatus 298 POPAX eret 299 POP blink 300 POP fp 301 POP gp 302 RESTORE_R12_TO_R0 303 304 ld sp, [sp] /* restore original sp */ 305 /* orig_r0, ECR skipped automatically */ 306 .endm 307 308 /* Dummy ECR values for Interrupts */ 309 #define event_IRQ1 0x0031abcd 310 #define event_IRQ2 0x0032abcd 311 312 .macro INTERRUPT_PROLOGUE LVL 313 314 /* free up r9 as scratchpad */ 315 PROLOG_FREEUP_REG r9, @int\LVL\()_saved_reg 316 317 /* Which mode (user/kernel) was the system in when intr occurred */ 318 lr r9, [status32_l\LVL\()] 319 320 SWITCH_TO_KERNEL_STK 321 322 323 st.a 0x003\LVL\()abcd, [sp, -4] /* Dummy ECR */ 324 sub sp, sp, 8 /* skip orig_r0 (not needed) 325 skip pt_regs->sp, already saved above */ 326 327 /* Restore r9 used to code the early prologue */ 328 PROLOG_RESTORE_REG r9, @int\LVL\()_saved_reg 329 330 SAVE_R0_TO_R12 331 PUSH gp 332 PUSH fp 333 PUSH blink 334 PUSH ilink\LVL\() 335 PUSHAX status32_l\LVL\() 336 PUSH lp_count 337 PUSHAX lp_end 338 PUSHAX lp_start 339 PUSHAX bta_l\LVL\() 340 341 #ifdef CONFIG_ARC_CURR_IN_REG 342 /* gp already saved on stack: now load with "current" */ 343 GET_CURR_TASK_ON_CPU gp 344 #endif 345 .endm 346 347 /*-------------------------------------------------------------- 348 * Restore all registers used by interrupt handlers. 349 * 350 * NOTE: 351 * 352 * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg 353 * for memory load operations. If used in that way interrupts are deffered 354 * by hardware and that is not good. 355 *-------------------------------------------------------------*/ 356 .macro INTERRUPT_EPILOGUE LVL 357 358 POPAX bta_l\LVL\() 359 POPAX lp_start 360 POPAX lp_end 361 362 POP r9 363 mov lp_count, r9 ;LD to lp_count is not allowed 364 365 POPAX status32_l\LVL\() 366 POP ilink\LVL\() 367 POP blink 368 POP fp 369 POP gp 370 RESTORE_R12_TO_R0 371 372 ld sp, [sp] /* restore original sp; orig_r0, ECR skipped implicitly */ 373 .endm 374 375 /* Get thread_info of "current" tsk */ 376 .macro GET_CURR_THR_INFO_FROM_SP reg 377 bic \reg, sp, (THREAD_SIZE - 1) 378 .endm 379 380 /* Get CPU-ID of this core */ 381 .macro GET_CPU_ID reg 382 lr \reg, [identity] 383 lsr \reg, \reg, 8 384 bmsk \reg, \reg, 7 385 .endm 386 387 #endif /* __ASM_ARC_ENTRY_COMPACT_H */ 388