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