0001
0002
0003 #ifndef __ASM_ARC_ENTRY_ARCV2_H
0004 #define __ASM_ARC_ENTRY_ARCV2_H
0005
0006 #include <asm/asm-offsets.h>
0007 #include <asm/dsp-impl.h>
0008 #include <asm/irqflags-arcv2.h>
0009 #include <asm/thread_info.h> /* For THREAD_SIZE */
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050 .macro INTERRUPT_PROLOGUE
0051
0052 ; (A) Before jumping to Interrupt Vector, hardware micro-ops did following:
0053 ; 1. SP auto-switched to kernel mode stack
0054 ; 2. STATUS32.Z flag set if in U mode at time of interrupt (U:1,K:0)
0055 ; 3. Auto save: (mandatory) Push PC and STAT32 on stack
0056 ; hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE
0057 ; 4. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI
0058 ;
0059 ; (B) Manually saved some regs: r12,r25,r30, sp,fp,gp, ACCL pair
0060
0061 #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
0062 ; carve pt_regs on stack (case #3), PC/STAT32 already on stack
0063 sub sp, sp, SZ_PT_REGS - 8
0064
0065 __SAVE_REGFILE_HARD
0066 #else
0067 ; carve pt_regs on stack (case #4), which grew partially already
0068 sub sp, sp, PT_r0
0069 #endif
0070
0071 __SAVE_REGFILE_SOFT
0072 .endm
0073
0074
0075 .macro EXCEPTION_PROLOGUE
0076
0077 ; (A) Before jumping to Exception Vector, hardware micro-ops did following:
0078 ; 1. SP auto-switched to kernel mode stack
0079 ; 2. STATUS32.Z flag set if in U mode at time of exception (U:1,K:0)
0080 ;
0081 ; (B) Manually save the complete reg file below
0082
0083 sub sp, sp, SZ_PT_REGS ; carve pt_regs
0084
0085 ; _HARD saves r10 clobbered by _SOFT as scratch hence comes first
0086
0087 __SAVE_REGFILE_HARD
0088 __SAVE_REGFILE_SOFT
0089
0090 st r0, [sp] ; orig_r0
0091
0092 lr r10, [eret]
0093 lr r11, [erstatus]
0094 ST2 r10, r11, PT_ret
0095
0096 lr r10, [ecr]
0097 lr r11, [erbta]
0098 ST2 r10, r11, PT_event
0099
0100 ; OUTPUT: r10 has ECR expected by EV_Trap
0101 .endm
0102
0103
0104
0105
0106
0107
0108
0109 .macro __SAVE_REGFILE_HARD
0110
0111 ST2 r0, r1, PT_r0
0112 ST2 r2, r3, PT_r2
0113 ST2 r4, r5, PT_r4
0114 ST2 r6, r7, PT_r6
0115 ST2 r8, r9, PT_r8
0116 ST2 r10, r11, PT_r10
0117
0118 st blink, [sp, PT_blink]
0119
0120 lr r10, [lp_end]
0121 lr r11, [lp_start]
0122 ST2 r10, r11, PT_lpe
0123
0124 st lp_count, [sp, PT_lpc]
0125
0126 ; skip JLI, LDI, EI for now
0127 .endm
0128
0129
0130
0131
0132
0133
0134
0135
0136 .macro __SAVE_REGFILE_SOFT
0137
0138 ST2 gp, fp, PT_r26 ; gp (r26), fp (r27)
0139
0140 st r12, [sp, PT_sp + 4]
0141 st r30, [sp, PT_sp + 8]
0142
0143 ; Saving pt_regs->sp correctly requires some extra work due to the way
0144 ; Auto stack switch works
0145 ; - U mode: retrieve it from AUX_USER_SP
0146 ; - K mode: add the offset from current SP where H/w starts auto push
0147 ;
0148 ; 1. Utilize the fact that Z bit is set if Intr taken in U mode
0149 ; 2. Upon entry SP is always saved (for any inspection, unwinding etc),
0150 ; but on return, restored only if U mode
0151
0152 lr r10, [AUX_USER_SP] ; U mode SP
0153
0154 ; ISA requires ADD.nz to have same dest and src reg operands
0155 mov.nz r10, sp
0156 add.nz r10, r10, SZ_PT_REGS ; K mode SP
0157
0158 st r10, [sp, PT_sp] ; SP (pt_regs->sp)
0159
0160 #ifdef CONFIG_ARC_CURR_IN_REG
0161 st r25, [sp, PT_user_r25]
0162 GET_CURR_TASK_ON_CPU r25
0163 #endif
0164
0165 #ifdef CONFIG_ARC_HAS_ACCL_REGS
0166 ST2 r58, r59, PT_r58
0167 #endif
0168
0169
0170 DSP_SAVE_REGFILE_IRQ
0171 .endm
0172
0173
0174 .macro __RESTORE_REGFILE_SOFT
0175
0176 LD2 gp, fp, PT_r26 ; gp (r26), fp (r27)
0177
0178 ld r12, [sp, PT_r12]
0179 ld r30, [sp, PT_r30]
0180
0181 ; Restore SP (into AUX_USER_SP) only if returning to U mode
0182 ; - for K mode, it will be implicitly restored as stack is unwound
0183 ; - Z flag set on K is inverse of what hardware does on interrupt entry
0184 ; but that doesn't really matter
0185 bz 1f
0186
0187 ld r10, [sp, PT_sp] ; SP (pt_regs->sp)
0188 sr r10, [AUX_USER_SP]
0189 1:
0190
0191 #ifdef CONFIG_ARC_CURR_IN_REG
0192 ld r25, [sp, PT_user_r25]
0193 #endif
0194
0195 /* clobbers r10, r11 registers pair */
0196 DSP_RESTORE_REGFILE_IRQ
0197
0198 #ifdef CONFIG_ARC_HAS_ACCL_REGS
0199 LD2 r58, r59, PT_r58
0200 #endif
0201 .endm
0202
0203 /*------------------------------------------------------------------------*/
0204 .macro __RESTORE_REGFILE_HARD
0205
0206 ld blink, [sp, PT_blink]
0207
0208 LD2 r10, r11, PT_lpe
0209 sr r10, [lp_end]
0210 sr r11, [lp_start]
0211
0212 ld r10, [sp, PT_lpc] ; lp_count can't be target of LD
0213 mov lp_count, r10
0214
0215 LD2 r0, r1, PT_r0
0216 LD2 r2, r3, PT_r2
0217 LD2 r4, r5, PT_r4
0218 LD2 r6, r7, PT_r6
0219 LD2 r8, r9, PT_r8
0220 LD2 r10, r11, PT_r10
0221 .endm
0222
0223
0224
0225 .macro INTERRUPT_EPILOGUE
0226
0227 ; INPUT: r0 has STAT32 of calling context
0228 ; INPUT: Z flag set if returning to K mode
0229
0230 ; _SOFT clobbers r10 restored by _HARD hence the order
0231
0232 __RESTORE_REGFILE_SOFT
0233
0234 #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
0235 __RESTORE_REGFILE_HARD
0236
0237 ; SP points to PC/STAT32: hw restores them despite NO_AUTOSAVE
0238 add sp, sp, SZ_PT_REGS - 8
0239 #else
0240 add sp, sp, PT_r0
0241 #endif
0242
0243 .endm
0244
0245
0246 .macro EXCEPTION_EPILOGUE
0247
0248 ; INPUT: r0 has STAT32 of calling context
0249
0250 btst r0, STATUS_U_BIT ; Z flag set if K, used in restoring SP
0251
0252 ld r10, [sp, PT_event + 4]
0253 sr r10, [erbta]
0254
0255 LD2 r10, r11, PT_ret
0256 sr r10, [eret]
0257 sr r11, [erstatus]
0258
0259 __RESTORE_REGFILE_SOFT
0260 __RESTORE_REGFILE_HARD
0261
0262 add sp, sp, SZ_PT_REGS
0263 .endm
0264
0265 .macro FAKE_RET_FROM_EXCPN
0266 lr r9, [status32]
0267 bic r9, r9, STATUS_AE_MASK
0268 or r9, r9, STATUS_IE_MASK
0269 kflag r9
0270 .endm
0271
0272
0273 .macro GET_CURR_THR_INFO_FROM_SP reg
0274 bmskn \reg, sp, THREAD_SHIFT - 1
0275 .endm
0276
0277
0278 .macro GET_CPU_ID reg
0279 lr \reg, [identity]
0280 xbfu \reg, \reg, 0xE8
0281
0282 .endm
0283
0284 #endif