1 /* SPDX-License-Identifier: GPL-2.0 */ 2 3 #ifndef __ASM_ARC_ENTRY_ARCV2_H 4 #define __ASM_ARC_ENTRY_ARCV2_H 5 6 #include <asm/asm-offsets.h> 7 #include <asm/dsp-impl.h> 8 #include <asm/irqflags-arcv2.h> 9 #include <asm/thread_info.h> /* For THREAD_SIZE */ 10 11 /* 12 * Interrupt/Exception stack layout (pt_regs) for ARCv2 13 * (End of struct aligned to end of page [unless nested]) 14 * 15 * INTERRUPT EXCEPTION 16 * 17 * manual --------------------- manual 18 * | orig_r0 | 19 * | event/ECR | 20 * | bta | 21 * | user_r25 | 22 * | gp | 23 * | fp | 24 * | sp | 25 * | r12 | 26 * | r30 | 27 * | r58 | 28 * | r59 | 29 * hw autosave --------------------- 30 * optional | r0 | 31 * | r1 | 32 * ~ ~ 33 * | r9 | 34 * | r10 | 35 * | r11 | 36 * | blink | 37 * | lpe | 38 * | lps | 39 * | lpc | 40 * | ei base | 41 * | ldi base | 42 * | jli base | 43 * --------------------- 44 * hw autosave | pc / eret | 45 * mandatory | stat32 / erstatus | 46 * --------------------- 47 */ 48 49 /*------------------------------------------------------------------------*/ 50 .macro INTERRUPT_PROLOGUE 51 52 ; (A) Before jumping to Interrupt Vector, hardware micro-ops did following: 53 ; 1. SP auto-switched to kernel mode stack 54 ; 2. STATUS32.Z flag set if in U mode at time of interrupt (U:1,K:0) 55 ; 3. Auto save: (mandatory) Push PC and STAT32 on stack 56 ; hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE 57 ; 4. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI 58 ; 59 ; (B) Manually saved some regs: r12,r25,r30, sp,fp,gp, ACCL pair 60 61 #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE 62 ; carve pt_regs on stack (case #3), PC/STAT32 already on stack 63 sub sp, sp, SZ_PT_REGS - 8 64 65 __SAVE_REGFILE_HARD 66 #else 67 ; carve pt_regs on stack (case #4), which grew partially already 68 sub sp, sp, PT_r0 69 #endif 70 71 __SAVE_REGFILE_SOFT 72 .endm 73 74 /*------------------------------------------------------------------------*/ 75 .macro EXCEPTION_PROLOGUE 76 77 ; (A) Before jumping to Exception Vector, hardware micro-ops did following: 78 ; 1. SP auto-switched to kernel mode stack 79 ; 2. STATUS32.Z flag set if in U mode at time of exception (U:1,K:0) 80 ; 81 ; (B) Manually save the complete reg file below 82 83 sub sp, sp, SZ_PT_REGS ; carve pt_regs 84 85 ; _HARD saves r10 clobbered by _SOFT as scratch hence comes first 86 87 __SAVE_REGFILE_HARD 88 __SAVE_REGFILE_SOFT 89 90 st r0, [sp] ; orig_r0 91 92 lr r10, [eret] 93 lr r11, [erstatus] 94 ST2 r10, r11, PT_ret 95 96 lr r10, [ecr] 97 lr r11, [erbta] 98 ST2 r10, r11, PT_event 99 100 ; OUTPUT: r10 has ECR expected by EV_Trap 101 .endm 102 103 /*------------------------------------------------------------------------ 104 * This macro saves the registers manually which would normally be autosaved 105 * by hardware on taken interrupts. It is used by 106 * - exception handlers (which don't have autosave) 107 * - interrupt autosave disabled due to CONFIG_ARC_IRQ_NO_AUTOSAVE 108 */ 109 .macro __SAVE_REGFILE_HARD 110 111 ST2 r0, r1, PT_r0 112 ST2 r2, r3, PT_r2 113 ST2 r4, r5, PT_r4 114 ST2 r6, r7, PT_r6 115 ST2 r8, r9, PT_r8 116 ST2 r10, r11, PT_r10 117 118 st blink, [sp, PT_blink] 119 120 lr r10, [lp_end] 121 lr r11, [lp_start] 122 ST2 r10, r11, PT_lpe 123 124 st lp_count, [sp, PT_lpc] 125 126 ; skip JLI, LDI, EI for now 127 .endm 128 129 /*------------------------------------------------------------------------ 130 * This macros saves a bunch of other registers which can't be autosaved for 131 * various reasons: 132 * - r12: the last caller saved scratch reg since hardware saves in pairs so r0-r11 133 * - r30: free reg, used by gcc as scratch 134 * - ACCL/ACCH pair when they exist 135 */ 136 .macro __SAVE_REGFILE_SOFT 137 138 ST2 gp, fp, PT_r26 ; gp (r26), fp (r27) 139 140 st r12, [sp, PT_sp + 4] 141 st r30, [sp, PT_sp + 8] 142 143 ; Saving pt_regs->sp correctly requires some extra work due to the way 144 ; Auto stack switch works 145 ; - U mode: retrieve it from AUX_USER_SP 146 ; - K mode: add the offset from current SP where H/w starts auto push 147 ; 148 ; 1. Utilize the fact that Z bit is set if Intr taken in U mode 149 ; 2. Upon entry SP is always saved (for any inspection, unwinding etc), 150 ; but on return, restored only if U mode 151 152 lr r10, [AUX_USER_SP] ; U mode SP 153 154 ; ISA requires ADD.nz to have same dest and src reg operands 155 mov.nz r10, sp 156 add.nz r10, r10, SZ_PT_REGS ; K mode SP 157 158 st r10, [sp, PT_sp] ; SP (pt_regs->sp) 159 160 #ifdef CONFIG_ARC_CURR_IN_REG 161 st r25, [sp, PT_user_r25] 162 GET_CURR_TASK_ON_CPU r25 163 #endif 164 165 #ifdef CONFIG_ARC_HAS_ACCL_REGS 166 ST2 r58, r59, PT_r58 167 #endif 168 169 /* clobbers r10, r11 registers pair */ 170 DSP_SAVE_REGFILE_IRQ 171 .endm 172 173 /*------------------------------------------------------------------------*/ 174 .macro __RESTORE_REGFILE_SOFT 175 176 LD2 gp, fp, PT_r26 ; gp (r26), fp (r27) 177 178 ld r12, [sp, PT_r12] 179 ld r30, [sp, PT_r30] 180 181 ; Restore SP (into AUX_USER_SP) only if returning to U mode 182 ; - for K mode, it will be implicitly restored as stack is unwound 183 ; - Z flag set on K is inverse of what hardware does on interrupt entry 184 ; but that doesn't really matter 185 bz 1f 186 187 ld r10, [sp, PT_sp] ; SP (pt_regs->sp) 188 sr r10, [AUX_USER_SP] 189 1: 190 191 #ifdef CONFIG_ARC_CURR_IN_REG 192 ld r25, [sp, PT_user_r25] 193 #endif 194 195 /* clobbers r10, r11 registers pair */ 196 DSP_RESTORE_REGFILE_IRQ 197 198 #ifdef CONFIG_ARC_HAS_ACCL_REGS 199 LD2 r58, r59, PT_r58 200 #endif 201 .endm 202 203 /*------------------------------------------------------------------------*/ 204 .macro __RESTORE_REGFILE_HARD 205 206 ld blink, [sp, PT_blink] 207 208 LD2 r10, r11, PT_lpe 209 sr r10, [lp_end] 210 sr r11, [lp_start] 211 212 ld r10, [sp, PT_lpc] ; lp_count can't be target of LD 213 mov lp_count, r10 214 215 LD2 r0, r1, PT_r0 216 LD2 r2, r3, PT_r2 217 LD2 r4, r5, PT_r4 218 LD2 r6, r7, PT_r6 219 LD2 r8, r9, PT_r8 220 LD2 r10, r11, PT_r10 221 .endm 222 223 224 /*------------------------------------------------------------------------*/ 225 .macro INTERRUPT_EPILOGUE 226 227 ; INPUT: r0 has STAT32 of calling context 228 ; INPUT: Z flag set if returning to K mode 229 230 ; _SOFT clobbers r10 restored by _HARD hence the order 231 232 __RESTORE_REGFILE_SOFT 233 234 #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE 235 __RESTORE_REGFILE_HARD 236 237 ; SP points to PC/STAT32: hw restores them despite NO_AUTOSAVE 238 add sp, sp, SZ_PT_REGS - 8 239 #else 240 add sp, sp, PT_r0 241 #endif 242 243 .endm 244 245 /*------------------------------------------------------------------------*/ 246 .macro EXCEPTION_EPILOGUE 247 248 ; INPUT: r0 has STAT32 of calling context 249 250 btst r0, STATUS_U_BIT ; Z flag set if K, used in restoring SP 251 252 ld r10, [sp, PT_event + 4] 253 sr r10, [erbta] 254 255 LD2 r10, r11, PT_ret 256 sr r10, [eret] 257 sr r11, [erstatus] 258 259 __RESTORE_REGFILE_SOFT 260 __RESTORE_REGFILE_HARD 261 262 add sp, sp, SZ_PT_REGS 263 .endm 264 265 .macro FAKE_RET_FROM_EXCPN 266 lr r9, [status32] 267 bic r9, r9, STATUS_AE_MASK 268 or r9, r9, STATUS_IE_MASK 269 kflag r9 270 .endm 271 272 /* Get thread_info of "current" tsk */ 273 .macro GET_CURR_THR_INFO_FROM_SP reg 274 bmskn \reg, sp, THREAD_SHIFT - 1 275 .endm 276 277 /* Get CPU-ID of this core */ 278 .macro GET_CPU_ID reg 279 lr \reg, [identity] 280 xbfu \reg, \reg, 0xE8 /* 00111 01000 */ 281 /* M = 8-1 N = 8 */ 282 .endm 283 284 #endif 285