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