Back to home page

LXR

 
 

    


0001 
0002 #ifndef __ASM_ARC_ENTRY_ARCV2_H
0003 #define __ASM_ARC_ENTRY_ARCV2_H
0004 
0005 #include <asm/asm-offsets.h>
0006 #include <asm/irqflags-arcv2.h>
0007 #include <asm/thread_info.h>    /* For THREAD_SIZE */
0008 
0009 /*------------------------------------------------------------------------*/
0010 .macro INTERRUPT_PROLOGUE   called_from
0011 
0012     ; Before jumping to Interrupt Vector, hardware micro-ops did following:
0013     ;   1. SP auto-switched to kernel mode stack
0014     ;   2. STATUS32.Z flag set to U mode at time of interrupt (U:1, K:0)
0015     ;   3. Auto saved: r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI, PC, STAT32
0016     ;
0017     ; Now manually save: r12, sp, fp, gp, r25
0018 
0019     PUSH    r30
0020     PUSH    r12
0021 
0022     ; Saving pt_regs->sp correctly requires some extra work due to the way
0023     ; Auto stack switch works
0024     ;  - U mode: retrieve it from AUX_USER_SP
0025     ;  - K mode: add the offset from current SP where H/w starts auto push
0026     ;
0027     ; Utilize the fact that Z bit is set if Intr taken in U mode
0028     mov.nz  r9, sp
0029     add.nz  r9, r9, SZ_PT_REGS - PT_sp - 4
0030     bnz 1f
0031 
0032     lr  r9, [AUX_USER_SP]
0033 1:
0034     PUSH    r9  ; SP
0035 
0036     PUSH    fp
0037     PUSH    gp
0038 
0039 #ifdef CONFIG_ARC_CURR_IN_REG
0040     PUSH    r25         ; user_r25
0041     GET_CURR_TASK_ON_CPU    r25
0042 #else
0043     sub sp, sp, 4
0044 #endif
0045 
0046 .ifnc \called_from, exception
0047     sub sp, sp, 12  ; BTA/ECR/orig_r0 placeholder per pt_regs
0048 .endif
0049 
0050 .endm
0051 
0052 /*------------------------------------------------------------------------*/
0053 .macro INTERRUPT_EPILOGUE   called_from
0054 
0055 .ifnc \called_from, exception
0056     add sp, sp, 12  ; skip BTA/ECR/orig_r0 placeholderss
0057 .endif
0058 
0059 #ifdef CONFIG_ARC_CURR_IN_REG
0060     POP r25
0061 #else
0062     add sp, sp, 4
0063 #endif
0064 
0065     POP gp
0066     POP fp
0067 
0068     ; Don't touch AUX_USER_SP if returning to K mode (Z bit set)
0069     ; (Z bit set on K mode is inverse of INTERRUPT_PROLOGUE)
0070     add.z   sp, sp, 4
0071     bz  1f
0072 
0073     POPAX   AUX_USER_SP
0074 1:
0075     POP r12
0076     POP r30
0077 
0078 .endm
0079 
0080 /*------------------------------------------------------------------------*/
0081 .macro EXCEPTION_PROLOGUE
0082 
0083     ; Before jumping to Exception Vector, hardware micro-ops did following:
0084     ;   1. SP auto-switched to kernel mode stack
0085     ;   2. STATUS32.Z flag set to U mode at time of interrupt (U:1,K:0)
0086     ;
0087     ; Now manually save the complete reg file
0088 
0089     PUSH    r9      ; freeup a register: slot of erstatus
0090 
0091     PUSHAX  eret
0092     sub sp, sp, 12  ; skip JLI, LDI, EI
0093     PUSH    lp_count
0094     PUSHAX  lp_start
0095     PUSHAX  lp_end
0096     PUSH    blink
0097 
0098     PUSH    r11
0099     PUSH    r10
0100 
0101     ld.as   r9,  [sp, 10]   ; load stashed r9 (status32 stack slot)
0102     lr  r10, [erstatus]
0103     st.as   r10, [sp, 10]   ; save status32 at it's right stack slot
0104 
0105     PUSH    r9
0106     PUSH    r8
0107     PUSH    r7
0108     PUSH    r6
0109     PUSH    r5
0110     PUSH    r4
0111     PUSH    r3
0112     PUSH    r2
0113     PUSH    r1
0114     PUSH    r0
0115 
0116     ; -- for interrupts, regs above are auto-saved by h/w in that order --
0117     ; Now do what ISR prologue does (manually save r12, sp, fp, gp, r25)
0118     ;
0119     ; Set Z flag if this was from U mode (expected by INTERRUPT_PROLOGUE)
0120     ; Although H/w exception micro-ops do set Z flag for U mode (just like
0121     ; for interrupts), it could get clobbered in case we soft land here from
0122     ; a TLB Miss exception handler (tlbex.S)
0123 
0124     and r10, r10, STATUS_U_MASK
0125     xor.f   0, r10, STATUS_U_MASK
0126 
0127     INTERRUPT_PROLOGUE  exception
0128 
0129     PUSHAX  erbta
0130     PUSHAX  ecr     ; r9 contains ECR, expected by EV_Trap
0131 
0132     PUSH    r0      ; orig_r0
0133 .endm
0134 
0135 /*------------------------------------------------------------------------*/
0136 .macro EXCEPTION_EPILOGUE
0137 
0138     ; Assumes r0 has PT_status32
0139     btst   r0, STATUS_U_BIT ; Z flag set if K, used in INTERRUPT_EPILOGUE
0140 
0141     add sp, sp, 8   ; orig_r0/ECR don't need restoring
0142     POPAX   erbta
0143 
0144     INTERRUPT_EPILOGUE  exception
0145 
0146     POP r0
0147     POP r1
0148     POP r2
0149     POP r3
0150     POP r4
0151     POP r5
0152     POP r6
0153     POP r7
0154     POP r8
0155     POP r9
0156     POP r10
0157     POP r11
0158 
0159     POP blink
0160     POPAX   lp_end
0161     POPAX   lp_start
0162 
0163     POP r9
0164     mov lp_count, r9
0165 
0166     add sp, sp, 12  ; skip JLI, LDI, EI
0167     POPAX   eret
0168     POPAX   erstatus
0169 
0170     ld.as   r9, [sp, -12]   ; reload r9 which got clobbered
0171 .endm
0172 
0173 .macro FAKE_RET_FROM_EXCPN
0174     lr      r9, [status32]
0175     bic     r9, r9, (STATUS_U_MASK|STATUS_DE_MASK|STATUS_AE_MASK)
0176     or      r9, r9, (STATUS_L_MASK|STATUS_IE_MASK)
0177     kflag   r9
0178 .endm
0179 
0180 /* Get thread_info of "current" tsk */
0181 .macro GET_CURR_THR_INFO_FROM_SP  reg
0182     bmskn \reg, sp, THREAD_SHIFT - 1
0183 .endm
0184 
0185 /* Get CPU-ID of this core */
0186 .macro  GET_CPU_ID  reg
0187     lr  \reg, [identity]
0188     xbfu \reg, \reg, 0xE8   /* 00111    01000 */
0189                 /* M = 8-1  N = 8 */
0190 .endm
0191 
0192 #endif