linux/arch/arc/include/asm/entry.h
<<
>>
Prefs
   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: March 2009 (Supporting 2 levels of Interrupts)
   9 *  Stack switching code can no longer reliably rely on the fact that
  10 *  if we are NOT in user mode, stack is switched to kernel mode.
  11 *  e.g. L2 IRQ interrupted a L1 ISR which had not yet completed
  12 *  it's prologue including stack switching from user mode
  13 *
  14 * Vineetg: Aug 28th 2008: Bug #94984
  15 *  -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
  16 *   Normally CPU does this automatically, however when doing FAKE rtie,
  17 *   we also need to explicitly do this. The problem in macros
  18 *   FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit
  19 *   was being "CLEARED" rather then "SET". Actually "SET" clears ZOL context
  20 *
  21 * Vineetg: May 5th 2008
  22 *  -Modified CALLEE_REG save/restore macros to handle the fact that
  23 *      r25 contains the kernel current task ptr
  24 *  - Defined Stack Switching Macro to be reused in all intr/excp hdlrs
  25 *  - Shaved off 11 instructions from RESTORE_ALL_INT1 by using the
  26 *      address Write back load ld.ab instead of seperate ld/add instn
  27 *
  28 * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
  29 */
  30
  31#ifndef __ASM_ARC_ENTRY_H
  32#define __ASM_ARC_ENTRY_H
  33
  34#ifdef __ASSEMBLY__
  35#include <asm/unistd.h>         /* For NR_syscalls defination */
  36#include <asm/asm-offsets.h>
  37#include <asm/arcregs.h>
  38#include <asm/ptrace.h>
  39#include <asm/processor.h>      /* For VMALLOC_START */
  40#include <asm/thread_info.h>    /* For THREAD_SIZE */
  41#include <asm/mmu.h>
  42
  43/* Note on the LD/ST addr modes with addr reg wback
  44 *
  45 * LD.a same as LD.aw
  46 *
  47 * LD.a    reg1, [reg2, x]  => Pre Incr
  48 *      Eff Addr for load = [reg2 + x]
  49 *
  50 * LD.ab   reg1, [reg2, x]  => Post Incr
  51 *      Eff Addr for load = [reg2]
  52 */
  53
  54.macro PUSH reg
  55        st.a    \reg, [sp, -4]
  56.endm
  57
  58.macro PUSHAX aux
  59        lr      r9, [\aux]
  60        PUSH    r9
  61.endm
  62
  63.macro POP reg
  64        ld.ab   \reg, [sp, 4]
  65.endm
  66
  67.macro POPAX aux
  68        POP     r9
  69        sr      r9, [\aux]
  70.endm
  71
  72/*--------------------------------------------------------------
  73 * Helpers to save/restore Scratch Regs:
  74 * used by Interrupt/Exception Prologue/Epilogue
  75 *-------------------------------------------------------------*/
  76.macro  SAVE_R0_TO_R12
  77        PUSH    r0
  78        PUSH    r1
  79        PUSH    r2
  80        PUSH    r3
  81        PUSH    r4
  82        PUSH    r5
  83        PUSH    r6
  84        PUSH    r7
  85        PUSH    r8
  86        PUSH    r9
  87        PUSH    r10
  88        PUSH    r11
  89        PUSH    r12
  90.endm
  91
  92.macro RESTORE_R12_TO_R0
  93        POP     r12
  94        POP     r11
  95        POP     r10
  96        POP     r9
  97        POP     r8
  98        POP     r7
  99        POP     r6
 100        POP     r5
 101        POP     r4
 102        POP     r3
 103        POP     r2
 104        POP     r1
 105        POP     r0
 106
 107#ifdef CONFIG_ARC_CURR_IN_REG
 108        ld      r25, [sp, 12]
 109#endif
 110.endm
 111
 112/*--------------------------------------------------------------
 113 * Helpers to save/restore callee-saved regs:
 114 * used by several macros below
 115 *-------------------------------------------------------------*/
 116.macro SAVE_R13_TO_R24
 117        PUSH    r13
 118        PUSH    r14
 119        PUSH    r15
 120        PUSH    r16
 121        PUSH    r17
 122        PUSH    r18
 123        PUSH    r19
 124        PUSH    r20
 125        PUSH    r21
 126        PUSH    r22
 127        PUSH    r23
 128        PUSH    r24
 129.endm
 130
 131.macro RESTORE_R24_TO_R13
 132        POP     r24
 133        POP     r23
 134        POP     r22
 135        POP     r21
 136        POP     r20
 137        POP     r19
 138        POP     r18
 139        POP     r17
 140        POP     r16
 141        POP     r15
 142        POP     r14
 143        POP     r13
 144.endm
 145
 146#define OFF_USER_R25_FROM_R24   (SZ_CALLEE_REGS + SZ_PT_REGS - 8)/4
 147
 148/*--------------------------------------------------------------
 149 * Collect User Mode callee regs as struct callee_regs - needed by
 150 * fork/do_signal/unaligned-access-emulation.
 151 * (By default only scratch regs are saved on entry to kernel)
 152 *
 153 * Special handling for r25 if used for caching Task Pointer.
 154 * It would have been saved in task->thread.user_r25 already, but to keep
 155 * the interface same it is copied into regular r25 placeholder in
 156 * struct callee_regs.
 157 *-------------------------------------------------------------*/
 158.macro SAVE_CALLEE_SAVED_USER
 159
 160        SAVE_R13_TO_R24
 161
 162#ifdef CONFIG_ARC_CURR_IN_REG
 163        ; Retrieve orig r25 and save it on stack
 164        ld.as   r12, [sp, OFF_USER_R25_FROM_R24]
 165        st.a    r12, [sp, -4]
 166#else
 167        PUSH    r25
 168#endif
 169
 170.endm
 171
 172/*--------------------------------------------------------------
 173 * Save kernel Mode callee regs at the time of Contect Switch.
 174 *
 175 * Special handling for r25 if used for caching Task Pointer.
 176 * Kernel simply skips saving it since it will be loaded with
 177 * incoming task pointer anyways
 178 *-------------------------------------------------------------*/
 179.macro SAVE_CALLEE_SAVED_KERNEL
 180
 181        SAVE_R13_TO_R24
 182
 183#ifdef CONFIG_ARC_CURR_IN_REG
 184        sub     sp, sp, 4
 185#else
 186        PUSH    r25
 187#endif
 188.endm
 189
 190/*--------------------------------------------------------------
 191 * Opposite of SAVE_CALLEE_SAVED_KERNEL
 192 *-------------------------------------------------------------*/
 193.macro RESTORE_CALLEE_SAVED_KERNEL
 194
 195#ifdef CONFIG_ARC_CURR_IN_REG
 196        add     sp, sp, 4  /* skip usual r25 placeholder */
 197#else
 198        POP     r25
 199#endif
 200        RESTORE_R24_TO_R13
 201.endm
 202
 203/*--------------------------------------------------------------
 204 * Opposite of SAVE_CALLEE_SAVED_USER
 205 *
 206 * ptrace tracer or unaligned-access fixup might have changed a user mode
 207 * callee reg which is saved back to usual r25 storage location
 208 *-------------------------------------------------------------*/
 209.macro RESTORE_CALLEE_SAVED_USER
 210
 211#ifdef CONFIG_ARC_CURR_IN_REG
 212        ld.ab   r12, [sp, 4]
 213        st.as   r12, [sp, OFF_USER_R25_FROM_R24]
 214#else
 215        POP     r25
 216#endif
 217        RESTORE_R24_TO_R13
 218.endm
 219
 220/*--------------------------------------------------------------
 221 * Super FAST Restore callee saved regs by simply re-adjusting SP
 222 *-------------------------------------------------------------*/
 223.macro DISCARD_CALLEE_SAVED_USER
 224        add     sp, sp, SZ_CALLEE_REGS
 225.endm
 226
 227/*-------------------------------------------------------------
 228 * given a tsk struct, get to the base of it's kernel mode stack
 229 * tsk->thread_info is really a PAGE, whose bottom hoists stack
 230 * which grows upwards towards thread_info
 231 *------------------------------------------------------------*/
 232
 233.macro GET_TSK_STACK_BASE tsk, out
 234
 235        /* Get task->thread_info (this is essentially start of a PAGE) */
 236        ld  \out, [\tsk, TASK_THREAD_INFO]
 237
 238        /* Go to end of page where stack begins (grows upwards) */
 239        add2 \out, \out, (THREAD_SIZE)/4
 240
 241.endm
 242
 243/*--------------------------------------------------------------
 244 * Switch to Kernel Mode stack if SP points to User Mode stack
 245 *
 246 * Entry   : r9 contains pre-IRQ/exception/trap status32
 247 * Exit    : SP is set to kernel mode stack pointer
 248 *           If CURR_IN_REG, r25 set to "current" task pointer
 249 * Clobbers: r9
 250 *-------------------------------------------------------------*/
 251
 252.macro SWITCH_TO_KERNEL_STK
 253
 254        /* User Mode when this happened ? Yes: Proceed to switch stack */
 255        bbit1   r9, STATUS_U_BIT, 88f
 256
 257        /* OK we were already in kernel mode when this event happened, thus can
 258         * assume SP is kernel mode SP. _NO_ need to do any stack switching
 259         */
 260
 261#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
 262        /* However....
 263         * If Level 2 Interrupts enabled, we may end up with a corner case:
 264         * 1. User Task executing
 265         * 2. L1 IRQ taken, ISR starts (CPU auto-switched to KERNEL mode)
 266         * 3. But before it could switch SP from USER to KERNEL stack
 267         *      a L2 IRQ "Interrupts" L1
 268         * Thay way although L2 IRQ happened in Kernel mode, stack is still
 269         * not switched.
 270         * To handle this, we may need to switch stack even if in kernel mode
 271         * provided SP has values in range of USER mode stack ( < 0x7000_0000 )
 272         */
 273        brlo sp, VMALLOC_START, 88f
 274
 275        /* TODO: vineetg:
 276         * We need to be a bit more cautious here. What if a kernel bug in
 277         * L1 ISR, caused SP to go whaco (some small value which looks like
 278         * USER stk) and then we take L2 ISR.
 279         * Above brlo alone would treat it as a valid L1-L2 sceanrio
 280         * instead of shouting alound
 281         * The only feasible way is to make sure this L2 happened in
 282         * L1 prelogue ONLY i.e. ilink2 is less than a pre-set marker in
 283         * L1 ISR before it switches stack
 284         */
 285
 286#endif
 287
 288        /* Save Pre Intr/Exception KERNEL MODE SP on kernel stack
 289         * safe-keeping not really needed, but it keeps the epilogue code
 290         * (SP restore) simpler/uniform.
 291         */
 292        b.d     66f
 293        mov     r9, sp
 294
 29588: /*------Intr/Ecxp happened in user mode, "switch" stack ------ */
 296
 297        GET_CURR_TASK_ON_CPU   r9
 298
 299        /* With current tsk in r9, get it's kernel mode stack base */
 300        GET_TSK_STACK_BASE  r9, r9
 301
 30266:
 303#ifdef CONFIG_ARC_CURR_IN_REG
 304        /*
 305         * Treat r25 as scratch reg, save it on stack first
 306         * Load it with current task pointer
 307         */
 308        st      r25, [r9, -4]
 309        GET_CURR_TASK_ON_CPU   r25
 310#endif
 311
 312        /* Save Pre Intr/Exception User SP on kernel stack */
 313        st.a    sp, [r9, -16]   ; Make room for orig_r0, ECR, user_r25
 314
 315        /* CAUTION:
 316         * SP should be set at the very end when we are done with everything
 317         * In case of 2 levels of interrupt we depend on value of SP to assume
 318         * that everything else is done (loading r25 etc)
 319         */
 320
 321        /* set SP to point to kernel mode stack */
 322        mov sp, r9
 323
 324        /* ----- Stack Switched to kernel Mode, Now save REG FILE ----- */
 325
 326.endm
 327
 328/*------------------------------------------------------------
 329 * "FAKE" a rtie to return from CPU Exception context
 330 * This is to re-enable Exceptions within exception
 331 * Look at EV_ProtV to see how this is actually used
 332 *-------------------------------------------------------------*/
 333
 334.macro FAKE_RET_FROM_EXCPN  reg
 335
 336        ld  \reg, [sp, PT_status32]
 337        bic  \reg, \reg, (STATUS_U_MASK|STATUS_DE_MASK)
 338        bset \reg, \reg, STATUS_L_BIT
 339        sr  \reg, [erstatus]
 340        mov \reg, 55f
 341        sr  \reg, [eret]
 342
 343        rtie
 34455:
 345.endm
 346
 347/*
 348 * @reg [OUT] &thread_info of "current"
 349 */
 350.macro GET_CURR_THR_INFO_FROM_SP  reg
 351        bic \reg, sp, (THREAD_SIZE - 1)
 352.endm
 353
 354/*
 355 * @reg [OUT] thread_info->flags of "current"
 356 */
 357.macro GET_CURR_THR_INFO_FLAGS  reg
 358        GET_CURR_THR_INFO_FROM_SP  \reg
 359        ld  \reg, [\reg, THREAD_INFO_FLAGS]
 360.endm
 361
 362/*--------------------------------------------------------------
 363 * For early Exception Prologue, a core reg is temporarily needed to
 364 * code the rest of prolog (stack switching). This is done by stashing
 365 * it to memory (non-SMP case) or SCRATCH0 Aux Reg (SMP).
 366 *
 367 * Before saving the full regfile - this reg is restored back, only
 368 * to be saved again on kernel mode stack, as part of ptregs.
 369 *-------------------------------------------------------------*/
 370.macro EXCPN_PROLOG_FREEUP_REG  reg
 371#ifdef CONFIG_SMP
 372        sr  \reg, [ARC_REG_SCRATCH_DATA0]
 373#else
 374        st  \reg, [@ex_saved_reg1]
 375#endif
 376.endm
 377
 378.macro EXCPN_PROLOG_RESTORE_REG reg
 379#ifdef CONFIG_SMP
 380        lr  \reg, [ARC_REG_SCRATCH_DATA0]
 381#else
 382        ld  \reg, [@ex_saved_reg1]
 383#endif
 384.endm
 385
 386/*--------------------------------------------------------------
 387 * Save all registers used by Exceptions (TLB Miss, Prot-V, Mem err etc)
 388 * Requires SP to be already switched to kernel mode Stack
 389 * sp points to the next free element on the stack at exit of this macro.
 390 * Registers are pushed / popped in the order defined in struct ptregs
 391 * in asm/ptrace.h
 392 * Note that syscalls are implemented via TRAP which is also a exception
 393 * from CPU's point of view
 394 *-------------------------------------------------------------*/
 395.macro SAVE_ALL_SYS
 396
 397        lr      r9, [ecr]
 398        st      r9, [sp, 8]    /* ECR */
 399        st      r0, [sp, 4]    /* orig_r0, needed only for sys calls */
 400
 401        /* Restore r9 used to code the early prologue */
 402        EXCPN_PROLOG_RESTORE_REG  r9
 403
 404        SAVE_R0_TO_R12
 405        PUSH    gp
 406        PUSH    fp
 407        PUSH    blink
 408        PUSHAX  eret
 409        PUSHAX  erstatus
 410        PUSH    lp_count
 411        PUSHAX  lp_end
 412        PUSHAX  lp_start
 413        PUSHAX  erbta
 414.endm
 415
 416/*--------------------------------------------------------------
 417 * Restore all registers used by system call or Exceptions
 418 * SP should always be pointing to the next free stack element
 419 * when entering this macro.
 420 *
 421 * NOTE:
 422 *
 423 * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
 424 * for memory load operations. If used in that way interrupts are deffered
 425 * by hardware and that is not good.
 426 *-------------------------------------------------------------*/
 427.macro RESTORE_ALL_SYS
 428        POPAX   erbta
 429        POPAX   lp_start
 430        POPAX   lp_end
 431
 432        POP     r9
 433        mov     lp_count, r9    ;LD to lp_count is not allowed
 434
 435        POPAX   erstatus
 436        POPAX   eret
 437        POP     blink
 438        POP     fp
 439        POP     gp
 440        RESTORE_R12_TO_R0
 441
 442        ld  sp, [sp] /* restore original sp */
 443        /* orig_r0, ECR, user_r25 skipped automatically */
 444.endm
 445
 446
 447/*--------------------------------------------------------------
 448 * Save all registers used by interrupt handlers.
 449 *-------------------------------------------------------------*/
 450.macro SAVE_ALL_INT1
 451
 452        /* restore original r9 to be saved as part of reg-file */
 453#ifdef CONFIG_SMP
 454        lr  r9, [ARC_REG_SCRATCH_DATA0]
 455#else
 456        ld  r9, [@int1_saved_reg]
 457#endif
 458
 459        /* now we are ready to save the remaining context :) */
 460        st      event_IRQ1, [sp, 8]    /* Dummy ECR */
 461        st      0, [sp, 4]    /* orig_r0 , N/A for IRQ */
 462
 463        SAVE_R0_TO_R12
 464        PUSH    gp
 465        PUSH    fp
 466        PUSH    blink
 467        PUSH    ilink1
 468        PUSHAX  status32_l1
 469        PUSH    lp_count
 470        PUSHAX  lp_end
 471        PUSHAX  lp_start
 472        PUSHAX  bta_l1
 473.endm
 474
 475.macro SAVE_ALL_INT2
 476
 477        /* TODO-vineetg: SMP we can't use global nor can we use
 478        *   SCRATCH0 as we do for int1 because while int1 is using
 479        *   it, int2 can come
 480        */
 481        /* retsore original r9 , saved in sys_saved_r9 */
 482        ld  r9, [@int2_saved_reg]
 483
 484        /* now we are ready to save the remaining context :) */
 485        st      event_IRQ2, [sp, 8]    /* Dummy ECR */
 486        st      0, [sp, 4]    /* orig_r0 , N/A for IRQ */
 487
 488        SAVE_R0_TO_R12
 489        PUSH    gp
 490        PUSH    fp
 491        PUSH    blink
 492        PUSH    ilink2
 493        PUSHAX  status32_l2
 494        PUSH    lp_count
 495        PUSHAX  lp_end
 496        PUSHAX  lp_start
 497        PUSHAX  bta_l2
 498.endm
 499
 500/*--------------------------------------------------------------
 501 * Restore all registers used by interrupt handlers.
 502 *
 503 * NOTE:
 504 *
 505 * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
 506 * for memory load operations. If used in that way interrupts are deffered
 507 * by hardware and that is not good.
 508 *-------------------------------------------------------------*/
 509
 510.macro RESTORE_ALL_INT1
 511        POPAX   bta_l1
 512        POPAX   lp_start
 513        POPAX   lp_end
 514
 515        POP     r9
 516        mov     lp_count, r9    ;LD to lp_count is not allowed
 517
 518        POPAX   status32_l1
 519        POP     ilink1
 520        POP     blink
 521        POP     fp
 522        POP     gp
 523        RESTORE_R12_TO_R0
 524
 525        ld  sp, [sp] /* restore original sp */
 526        /* orig_r0, ECR, user_r25 skipped automatically */
 527.endm
 528
 529.macro RESTORE_ALL_INT2
 530        POPAX   bta_l2
 531        POPAX   lp_start
 532        POPAX   lp_end
 533
 534        POP     r9
 535        mov     lp_count, r9    ;LD to lp_count is not allowed
 536
 537        POPAX   status32_l2
 538        POP     ilink2
 539        POP     blink
 540        POP     fp
 541        POP     gp
 542        RESTORE_R12_TO_R0
 543
 544        ld  sp, [sp] /* restore original sp */
 545        /* orig_r0, ECR, user_r25 skipped automatically */
 546.endm
 547
 548
 549/* Get CPU-ID of this core */
 550.macro  GET_CPU_ID  reg
 551        lr  \reg, [identity]
 552        lsr \reg, \reg, 8
 553        bmsk \reg, \reg, 7
 554.endm
 555
 556#ifdef CONFIG_SMP
 557
 558/*-------------------------------------------------
 559 * Retrieve the current running task on this CPU
 560 * 1. Determine curr CPU id.
 561 * 2. Use it to index into _current_task[ ]
 562 */
 563.macro  GET_CURR_TASK_ON_CPU   reg
 564        GET_CPU_ID  \reg
 565        ld.as  \reg, [@_current_task, \reg]
 566.endm
 567
 568/*-------------------------------------------------
 569 * Save a new task as the "current" task on this CPU
 570 * 1. Determine curr CPU id.
 571 * 2. Use it to index into _current_task[ ]
 572 *
 573 * Coded differently than GET_CURR_TASK_ON_CPU (which uses LD.AS)
 574 * because ST r0, [r1, offset] can ONLY have s9 @offset
 575 * while   LD can take s9 (4 byte insn) or LIMM (8 byte insn)
 576 */
 577
 578.macro  SET_CURR_TASK_ON_CPU    tsk, tmp
 579        GET_CPU_ID  \tmp
 580        add2 \tmp, @_current_task, \tmp
 581        st   \tsk, [\tmp]
 582#ifdef CONFIG_ARC_CURR_IN_REG
 583        mov r25, \tsk
 584#endif
 585
 586.endm
 587
 588
 589#else   /* Uniprocessor implementation of macros */
 590
 591.macro  GET_CURR_TASK_ON_CPU    reg
 592        ld  \reg, [@_current_task]
 593.endm
 594
 595.macro  SET_CURR_TASK_ON_CPU    tsk, tmp
 596        st  \tsk, [@_current_task]
 597#ifdef CONFIG_ARC_CURR_IN_REG
 598        mov r25, \tsk
 599#endif
 600.endm
 601
 602#endif /* SMP / UNI */
 603
 604/* ------------------------------------------------------------------
 605 * Get the ptr to some field of Current Task at @off in task struct
 606 *  -Uses r25 for Current task ptr if that is enabled
 607 */
 608
 609#ifdef CONFIG_ARC_CURR_IN_REG
 610
 611.macro GET_CURR_TASK_FIELD_PTR  off,  reg
 612        add \reg, r25, \off
 613.endm
 614
 615#else
 616
 617.macro GET_CURR_TASK_FIELD_PTR  off,  reg
 618        GET_CURR_TASK_ON_CPU  \reg
 619        add \reg, \reg, \off
 620.endm
 621
 622#endif  /* CONFIG_ARC_CURR_IN_REG */
 623
 624#endif  /* __ASSEMBLY__ */
 625
 626#endif  /* __ASM_ARC_ENTRY_H */
 627