1 /* 2 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 * Vineetg: Aug 28th 2008: Bug #94984 9 * -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap 10 * Normally CPU does this automatically, however when doing FAKE rtie, 11 * we also need to explicitly do this. The problem in macros 12 * FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit 13 * was being "CLEARED" rather then "SET". Actually "SET" clears ZOL context 14 * 15 * Vineetg: May 5th 2008 16 * - Defined Stack Switching Macro to be reused in all intr/excp hdlrs 17 * - Shaved off 11 instructions from RESTORE_ALL_INT1 by using the 18 * address Write back load ld.ab instead of seperate ld/add instn 19 * 20 * Amit Bhor, Sameer Dhavale: Codito Technologies 2004 21 */ 22 23 #ifndef __ASM_ARC_ENTRY_H 24 #define __ASM_ARC_ENTRY_H 25 26 #ifdef __ASSEMBLY__ 27 #include <asm/unistd.h> /* For NR_syscalls defination */ 28 #include <asm/asm-offsets.h> 29 #include <asm/arcregs.h> 30 #include <asm/ptrace.h> 31 #include <asm/thread_info.h> /* For THREAD_SIZE */ 32 33 /* Note on the LD/ST addr modes with addr reg wback 34 * 35 * LD.a same as LD.aw 36 * 37 * LD.a reg1, [reg2, x] => Pre Incr 38 * Eff Addr for load = [reg2 + x] 39 * 40 * LD.ab reg1, [reg2, x] => Post Incr 41 * Eff Addr for load = [reg2] 42 */ 43 44 /*-------------------------------------------------------------- 45 * Save caller saved registers (scratch registers) ( r0 - r12 ) 46 * Registers are pushed / popped in the order defined in struct ptregs 47 * in asm/ptrace.h 48 *-------------------------------------------------------------*/ 49 .macro SAVE_CALLER_SAVED 50 st.a r0, [sp, -4] 51 st.a r1, [sp, -4] 52 st.a r2, [sp, -4] 53 st.a r3, [sp, -4] 54 st.a r4, [sp, -4] 55 st.a r5, [sp, -4] 56 st.a r6, [sp, -4] 57 st.a r7, [sp, -4] 58 st.a r8, [sp, -4] 59 st.a r9, [sp, -4] 60 st.a r10, [sp, -4] 61 st.a r11, [sp, -4] 62 st.a r12, [sp, -4] 63 .endm 64 65 /*-------------------------------------------------------------- 66 * Restore caller saved registers (scratch registers) 67 *-------------------------------------------------------------*/ 68 .macro RESTORE_CALLER_SAVED 69 ld.ab r12, [sp, 4] 70 ld.ab r11, [sp, 4] 71 ld.ab r10, [sp, 4] 72 ld.ab r9, [sp, 4] 73 ld.ab r8, [sp, 4] 74 ld.ab r7, [sp, 4] 75 ld.ab r6, [sp, 4] 76 ld.ab r5, [sp, 4] 77 ld.ab r4, [sp, 4] 78 ld.ab r3, [sp, 4] 79 ld.ab r2, [sp, 4] 80 ld.ab r1, [sp, 4] 81 ld.ab r0, [sp, 4] 82 .endm 83 84 85 /*-------------------------------------------------------------- 86 * Save callee saved registers (non scratch registers) ( r13 - r25 ) 87 * on kernel stack. 88 * User mode callee regs need to be saved in case of 89 * -fork and friends for replicating from parent to child 90 * -before going into do_signal( ) for ptrace/core-dump 91 * Special case handling is required for r25 in case it is used by kernel 92 * for caching task ptr. Low level exception/ISR save user mode r25 93 * into task->thread.user_r25. So it needs to be retrieved from there and 94 * saved into kernel stack with rest of callee reg-file 95 *-------------------------------------------------------------*/ 96 .macro SAVE_CALLEE_SAVED_USER 97 st.a r13, [sp, -4] 98 st.a r14, [sp, -4] 99 st.a r15, [sp, -4] 100 st.a r16, [sp, -4] 101 st.a r17, [sp, -4] 102 st.a r18, [sp, -4] 103 st.a r19, [sp, -4] 104 st.a r20, [sp, -4] 105 st.a r21, [sp, -4] 106 st.a r22, [sp, -4] 107 st.a r23, [sp, -4] 108 st.a r24, [sp, -4] 109 st.a r25, [sp, -4] 110 111 /* move up by 1 word to "create" callee_regs->"stack_place_holder" */ 112 sub sp, sp, 4 113 .endm 114 115 /*-------------------------------------------------------------- 116 * Save callee saved registers (non scratch registers) ( r13 - r25 ) 117 * kernel mode callee regs needed to be saved in case of context switch 118 * If r25 is used for caching task pointer then that need not be saved 119 * as it can be re-created from current task global 120 *-------------------------------------------------------------*/ 121 .macro SAVE_CALLEE_SAVED_KERNEL 122 st.a r13, [sp, -4] 123 st.a r14, [sp, -4] 124 st.a r15, [sp, -4] 125 st.a r16, [sp, -4] 126 st.a r17, [sp, -4] 127 st.a r18, [sp, -4] 128 st.a r19, [sp, -4] 129 st.a r20, [sp, -4] 130 st.a r21, [sp, -4] 131 st.a r22, [sp, -4] 132 st.a r23, [sp, -4] 133 st.a r24, [sp, -4] 134 st.a r25, [sp, -4] 135 sub sp, sp, 4 136 .endm 137 138 /*-------------------------------------------------------------- 139 * RESTORE_CALLEE_SAVED_KERNEL: 140 * Loads callee (non scratch) Reg File by popping from Kernel mode stack. 141 * This is reverse of SAVE_CALLEE_SAVED, 142 * 143 * NOTE: 144 * Ideally this shd only be called in switch_to for loading 145 * switched-IN task's CALLEE Reg File. 146 * For all other cases RESTORE_CALLEE_SAVED_FAST must be used 147 * which simply pops the stack w/o touching regs. 148 *-------------------------------------------------------------*/ 149 .macro RESTORE_CALLEE_SAVED_KERNEL 150 151 add sp, sp, 4 /* skip "callee_regs->stack_place_holder" */ 152 ld.ab r25, [sp, 4] 153 ld.ab r24, [sp, 4] 154 ld.ab r23, [sp, 4] 155 ld.ab r22, [sp, 4] 156 ld.ab r21, [sp, 4] 157 ld.ab r20, [sp, 4] 158 ld.ab r19, [sp, 4] 159 ld.ab r18, [sp, 4] 160 ld.ab r17, [sp, 4] 161 ld.ab r16, [sp, 4] 162 ld.ab r15, [sp, 4] 163 ld.ab r14, [sp, 4] 164 ld.ab r13, [sp, 4] 165 166 .endm 167 168 /*-------------------------------------------------------------- 169 * RESTORE_CALLEE_SAVED_USER: 170 * This is called after do_signal where tracer might have changed callee regs 171 * thus we need to restore the reg file. 172 * Special case handling is required for r25 in case it is used by kernel 173 * for caching task ptr. Ptrace would have modified on-kernel-stack value of 174 * r25, which needs to be shoved back into task->thread.user_r25 where from 175 * Low level exception/ISR return code will retrieve to populate with rest of 176 * callee reg-file. 177 *-------------------------------------------------------------*/ 178 .macro RESTORE_CALLEE_SAVED_USER 179 180 add sp, sp, 4 /* skip "callee_regs->stack_place_holder" */ 181 182 #ifdef CONFIG_ARC_CURR_IN_REG 183 ld.ab r12, [sp, 4] 184 st r12, [r25, TASK_THREAD + THREAD_USER_R25] 185 #else 186 ld.ab r25, [sp, 4] 187 #endif 188 189 ld.ab r24, [sp, 4] 190 ld.ab r23, [sp, 4] 191 ld.ab r22, [sp, 4] 192 ld.ab r21, [sp, 4] 193 ld.ab r20, [sp, 4] 194 ld.ab r19, [sp, 4] 195 ld.ab r18, [sp, 4] 196 ld.ab r17, [sp, 4] 197 ld.ab r16, [sp, 4] 198 ld.ab r15, [sp, 4] 199 ld.ab r14, [sp, 4] 200 ld.ab r13, [sp, 4] 201 .endm 202 203 /*-------------------------------------------------------------- 204 * Super FAST Restore callee saved regs by simply re-adjusting SP 205 *-------------------------------------------------------------*/ 206 .macro DISCARD_CALLEE_SAVED_USER 207 add sp, sp, 14 * 4 208 .endm 209 210 /*-------------------------------------------------------------- 211 * Restore User mode r25 saved in task_struct->thread.user_r25 212 *-------------------------------------------------------------*/ 213 .macro RESTORE_USER_R25 214 ld r25, [r25, TASK_THREAD + THREAD_USER_R25] 215 .endm 216 217 /*------------------------------------------------------------- 218 * given a tsk struct, get to the base of it's kernel mode stack 219 * tsk->thread_info is really a PAGE, whose bottom hoists stack 220 * which grows upwards towards thread_info 221 *------------------------------------------------------------*/ 222 223 .macro GET_TSK_STACK_BASE tsk, out 224 225 /* Get task->thread_info (this is essentially start of a PAGE) */ 226 ld \out, [\tsk, TASK_THREAD_INFO] 227 228 /* Go to end of page where stack begins (grows upwards) */ 229 add2 \out, \out, (THREAD_SIZE - 4)/4 /* one word GUTTER */ 230 231 .endm 232 233 /*-------------------------------------------------------------- 234 * Switch to Kernel Mode stack if SP points to User Mode stack 235 * 236 * Entry : r9 contains pre-IRQ/exception/trap status32 237 * Exit : SP is set to kernel mode stack pointer 238 * Clobbers: r9 239 *-------------------------------------------------------------*/ 240 241 .macro SWITCH_TO_KERNEL_STK 242 243 /* User Mode when this happened ? Yes: Proceed to switch stack */ 244 bbit1 r9, STATUS_U_BIT, 88f 245 246 /* OK we were already in kernel mode when this event happened, thus can 247 * assume SP is kernel mode SP. _NO_ need to do any stack switching 248 */ 249 250 /* Save Pre Intr/Exception KERNEL MODE SP on kernel stack 251 * safe-keeping not really needed, but it keeps the epilogue code 252 * (SP restore) simpler/uniform. 253 */ 254 b.d 77f 255 256 st.a sp, [sp, -12] ; Make room for orig_r0 and orig_r8 257 258 88: /*------Intr/Ecxp happened in user mode, "switch" stack ------ */ 259 260 GET_CURR_TASK_ON_CPU r9 261 262 /* With current tsk in r9, get it's kernel mode stack base */ 263 GET_TSK_STACK_BASE r9, r9 264 265 #ifdef PT_REGS_CANARY 266 st 0xabcdabcd, [r9, 0] 267 #endif 268 269 /* Save Pre Intr/Exception User SP on kernel stack */ 270 st.a sp, [r9, -12] ; Make room for orig_r0 and orig_r8 271 272 /* CAUTION: 273 * SP should be set at the very end when we are done with everything 274 * In case of 2 levels of interrupt we depend on value of SP to assume 275 * that everything else is done (loading r25 etc) 276 */ 277 278 /* set SP to point to kernel mode stack */ 279 mov sp, r9 280 281 77: /* ----- Stack Switched to kernel Mode, Now save REG FILE ----- */ 282 283 .endm 284 285 /*------------------------------------------------------------ 286 * "FAKE" a rtie to return from CPU Exception context 287 * This is to re-enable Exceptions within exception 288 * Look at EV_ProtV to see how this is actually used 289 *-------------------------------------------------------------*/ 290 291 .macro FAKE_RET_FROM_EXCPN reg 292 293 ld \reg, [sp, PT_status32] 294 bic \reg, \reg, (STATUS_U_MASK|STATUS_DE_MASK) 295 bset \reg, \reg, STATUS_L_BIT 296 sr \reg, [erstatus] 297 mov \reg, 55f 298 sr \reg, [eret] 299 300 rtie 301 55: 302 .endm 303 304 /* 305 * @reg [OUT] &thread_info of "current" 306 */ 307 .macro GET_CURR_THR_INFO_FROM_SP reg 308 and \reg, sp, ~(THREAD_SIZE - 1) 309 .endm 310 311 /* 312 * @reg [OUT] thread_info->flags of "current" 313 */ 314 .macro GET_CURR_THR_INFO_FLAGS reg 315 GET_CURR_THR_INFO_FROM_SP \reg 316 ld \reg, [\reg, THREAD_INFO_FLAGS] 317 .endm 318 319 /*-------------------------------------------------------------- 320 * For early Exception Prologue, a core reg is temporarily needed to 321 * code the rest of prolog (stack switching). This is done by stashing 322 * it to memory (non-SMP case) or SCRATCH0 Aux Reg (SMP). 323 * 324 * Before saving the full regfile - this reg is restored back, only 325 * to be saved again on kernel mode stack, as part of ptregs. 326 *-------------------------------------------------------------*/ 327 .macro EXCPN_PROLOG_FREEUP_REG reg 328 st \reg, [@ex_saved_reg1] 329 .endm 330 331 .macro EXCPN_PROLOG_RESTORE_REG reg 332 ld \reg, [@ex_saved_reg1] 333 .endm 334 335 /*-------------------------------------------------------------- 336 * Save all registers used by Exceptions (TLB Miss, Prot-V, Mem err etc) 337 * Requires SP to be already switched to kernel mode Stack 338 * sp points to the next free element on the stack at exit of this macro. 339 * Registers are pushed / popped in the order defined in struct ptregs 340 * in asm/ptrace.h 341 * Note that syscalls are implemented via TRAP which is also a exception 342 * from CPU's point of view 343 *-------------------------------------------------------------*/ 344 .macro SAVE_ALL_EXCEPTION marker 345 346 /* Restore r9 used to code the early prologue */ 347 EXCPN_PROLOG_RESTORE_REG r9 348 349 /* Save the complete regfile now */ 350 351 /* orig_r8 marker: 352 * syscalls -> 1 to NR_SYSCALLS 353 * Exceptions -> NR_SYSCALLS + 1 354 * Break-point-> NR_SYSCALLS + 2 355 */ 356 st \marker, [sp, 8] 357 st r0, [sp, 4] /* orig_r0, needed only for sys calls */ 358 SAVE_CALLER_SAVED 359 st.a r26, [sp, -4] /* gp */ 360 st.a fp, [sp, -4] 361 st.a blink, [sp, -4] 362 lr r9, [eret] 363 st.a r9, [sp, -4] 364 lr r9, [erstatus] 365 st.a r9, [sp, -4] 366 st.a lp_count, [sp, -4] 367 lr r9, [lp_end] 368 st.a r9, [sp, -4] 369 lr r9, [lp_start] 370 st.a r9, [sp, -4] 371 lr r9, [erbta] 372 st.a r9, [sp, -4] 373 374 #ifdef PT_REGS_CANARY 375 mov r9, 0xdeadbeef 376 st r9, [sp, -4] 377 #endif 378 379 /* move up by 1 word to "create" pt_regs->"stack_place_holder" */ 380 sub sp, sp, 4 381 .endm 382 383 /*-------------------------------------------------------------- 384 * Save scratch regs for exceptions 385 *-------------------------------------------------------------*/ 386 .macro SAVE_ALL_SYS 387 SAVE_ALL_EXCEPTION (NR_syscalls + 1) 388 .endm 389 390 /*-------------------------------------------------------------- 391 * Save scratch regs for sys calls 392 *-------------------------------------------------------------*/ 393 .macro SAVE_ALL_TRAP 394 SAVE_ALL_EXCEPTION r8 395 .endm 396 397 /*-------------------------------------------------------------- 398 * Restore all registers used by system call or Exceptions 399 * SP should always be pointing to the next free stack element 400 * when entering this macro. 401 * 402 * NOTE: 403 * 404 * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg 405 * for memory load operations. If used in that way interrupts are deffered 406 * by hardware and that is not good. 407 *-------------------------------------------------------------*/ 408 .macro RESTORE_ALL_SYS 409 410 add sp, sp, 4 /* hop over unused "pt_regs->stack_place_holder" */ 411 412 ld.ab r9, [sp, 4] 413 sr r9, [erbta] 414 ld.ab r9, [sp, 4] 415 sr r9, [lp_start] 416 ld.ab r9, [sp, 4] 417 sr r9, [lp_end] 418 ld.ab r9, [sp, 4] 419 mov lp_count, r9 420 ld.ab r9, [sp, 4] 421 sr r9, [erstatus] 422 ld.ab r9, [sp, 4] 423 sr r9, [eret] 424 ld.ab blink, [sp, 4] 425 ld.ab fp, [sp, 4] 426 ld.ab r26, [sp, 4] /* gp */ 427 RESTORE_CALLER_SAVED 428 429 ld sp, [sp] /* restore original sp */ 430 /* orig_r0 and orig_r8 skipped automatically */ 431 .endm 432 433 434 /*-------------------------------------------------------------- 435 * Save all registers used by interrupt handlers. 436 *-------------------------------------------------------------*/ 437 .macro SAVE_ALL_INT1 438 439 /* restore original r9 , saved in int1_saved_reg 440 * It will be saved on stack in macro: SAVE_CALLER_SAVED 441 */ 442 ld r9, [@int1_saved_reg] 443 444 /* now we are ready to save the remaining context :) */ 445 st -1, [sp, 8] /* orig_r8, -1 for interuppt level one */ 446 st 0, [sp, 4] /* orig_r0 , N/A for IRQ */ 447 SAVE_CALLER_SAVED 448 st.a r26, [sp, -4] /* gp */ 449 st.a fp, [sp, -4] 450 st.a blink, [sp, -4] 451 st.a ilink1, [sp, -4] 452 lr r9, [status32_l1] 453 st.a r9, [sp, -4] 454 st.a lp_count, [sp, -4] 455 lr r9, [lp_end] 456 st.a r9, [sp, -4] 457 lr r9, [lp_start] 458 st.a r9, [sp, -4] 459 lr r9, [bta_l1] 460 st.a r9, [sp, -4] 461 462 #ifdef PT_REGS_CANARY 463 mov r9, 0xdeadbee1 464 st r9, [sp, -4] 465 #endif 466 /* move up by 1 word to "create" pt_regs->"stack_place_holder" */ 467 sub sp, sp, 4 468 .endm 469 470 /*-------------------------------------------------------------- 471 * Restore all registers used by interrupt handlers. 472 * 473 * NOTE: 474 * 475 * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg 476 * for memory load operations. If used in that way interrupts are deffered 477 * by hardware and that is not good. 478 *-------------------------------------------------------------*/ 479 480 .macro RESTORE_ALL_INT1 481 add sp, sp, 4 /* hop over unused "pt_regs->stack_place_holder" */ 482 483 ld.ab r9, [sp, 4] /* Actual reg file */ 484 sr r9, [bta_l1] 485 ld.ab r9, [sp, 4] 486 sr r9, [lp_start] 487 ld.ab r9, [sp, 4] 488 sr r9, [lp_end] 489 ld.ab r9, [sp, 4] 490 mov lp_count, r9 491 ld.ab r9, [sp, 4] 492 sr r9, [status32_l1] 493 ld.ab r9, [sp, 4] 494 mov ilink1, r9 495 ld.ab blink, [sp, 4] 496 ld.ab fp, [sp, 4] 497 ld.ab r26, [sp, 4] /* gp */ 498 RESTORE_CALLER_SAVED 499 500 ld sp, [sp] /* restore original sp */ 501 /* orig_r0 and orig_r8 skipped automatically */ 502 .endm 503 504 /* Get CPU-ID of this core */ 505 .macro GET_CPU_ID reg 506 lr \reg, [identity] 507 lsr \reg, \reg, 8 508 bmsk \reg, \reg, 7 509 .endm 510 511 .macro GET_CURR_TASK_ON_CPU reg 512 ld \reg, [@_current_task] 513 .endm 514 515 .macro SET_CURR_TASK_ON_CPU tsk, tmp 516 st \tsk, [@_current_task] 517 .endm 518 519 /* ------------------------------------------------------------------ 520 * Get the ptr to some field of Current Task at @off in task struct 521 */ 522 523 .macro GET_CURR_TASK_FIELD_PTR off, reg 524 GET_CURR_TASK_ON_CPU \reg 525 add \reg, \reg, \off 526 .endm 527 528 #endif /* __ASSEMBLY__ */ 529 530 #endif /* __ASM_ARC_ENTRY_H */ 531