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 .macro INTERRUPT_PROLOGUE called_from 12 13 ; Before jumping to Interrupt Vector, hardware micro-ops did following: 14 ; 1. SP auto-switched to kernel mode stack 15 ; 2. STATUS32.Z flag set to U mode at time of interrupt (U:1, K:0) 16 ; 3. Auto saved: r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI, PC, STAT32 17 ; 18 ; Now manually save: r12, sp, fp, gp, r25 19 20 #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE 21 .ifnc \called_from, exception 22 st.as r9, [sp, -10] ; save r9 in it's final stack slot 23 sub sp, sp, 12 ; skip JLI, LDI, EI 24 25 PUSH lp_count 26 PUSHAX lp_start 27 PUSHAX lp_end 28 PUSH blink 29 30 PUSH r11 31 PUSH r10 32 33 sub sp, sp, 4 ; skip r9 34 35 PUSH r8 36 PUSH r7 37 PUSH r6 38 PUSH r5 39 PUSH r4 40 PUSH r3 41 PUSH r2 42 PUSH r1 43 PUSH r0 44 .endif 45 #endif 46 47 #ifdef CONFIG_ARC_HAS_ACCL_REGS 48 PUSH r59 49 PUSH r58 50 #endif 51 52 PUSH r30 53 PUSH r12 54 55 ; Saving pt_regs->sp correctly requires some extra work due to the way 56 ; Auto stack switch works 57 ; - U mode: retrieve it from AUX_USER_SP 58 ; - K mode: add the offset from current SP where H/w starts auto push 59 ; 60 ; Utilize the fact that Z bit is set if Intr taken in U mode 61 mov.nz r9, sp 62 add.nz r9, r9, SZ_PT_REGS - PT_sp - 4 63 bnz 1f 64 65 lr r9, [AUX_USER_SP] 66 1: 67 PUSH r9 ; SP 68 69 PUSH fp 70 PUSH gp 71 72 #ifdef CONFIG_ARC_CURR_IN_REG 73 PUSH r25 ; user_r25 74 GET_CURR_TASK_ON_CPU r25 75 #else 76 sub sp, sp, 4 77 #endif 78 79 .ifnc \called_from, exception 80 sub sp, sp, 12 ; BTA/ECR/orig_r0 placeholder per pt_regs 81 .endif 82 83 .endm 84 85 /*------------------------------------------------------------------------*/ 86 .macro INTERRUPT_EPILOGUE called_from 87 88 .ifnc \called_from, exception 89 add sp, sp, 12 ; skip BTA/ECR/orig_r0 placeholderss 90 .endif 91 92 #ifdef CONFIG_ARC_CURR_IN_REG 93 POP r25 94 #else 95 add sp, sp, 4 96 #endif 97 98 POP gp 99 POP fp 100 101 ; Don't touch AUX_USER_SP if returning to K mode (Z bit set) 102 ; (Z bit set on K mode is inverse of INTERRUPT_PROLOGUE) 103 add.z sp, sp, 4 104 bz 1f 105 106 POPAX AUX_USER_SP 107 1: 108 POP r12 109 POP r30 110 111 #ifdef CONFIG_ARC_HAS_ACCL_REGS 112 POP r58 113 POP r59 114 #endif 115 116 #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE 117 .ifnc \called_from, exception 118 POP r0 119 POP r1 120 POP r2 121 POP r3 122 POP r4 123 POP r5 124 POP r6 125 POP r7 126 POP r8 127 POP r9 128 POP r10 129 POP r11 130 131 POP blink 132 POPAX lp_end 133 POPAX lp_start 134 135 POP r9 136 mov lp_count, r9 137 138 add sp, sp, 12 ; skip JLI, LDI, EI 139 ld.as r9, [sp, -10] ; reload r9 which got clobbered 140 .endif 141 #endif 142 143 .endm 144 145 /*------------------------------------------------------------------------*/ 146 .macro EXCEPTION_PROLOGUE 147 148 ; Before jumping to Exception Vector, hardware micro-ops did following: 149 ; 1. SP auto-switched to kernel mode stack 150 ; 2. STATUS32.Z flag set to U mode at time of interrupt (U:1,K:0) 151 ; 152 ; Now manually save the complete reg file 153 154 PUSH r9 ; freeup a register: slot of erstatus 155 156 PUSHAX eret 157 sub sp, sp, 12 ; skip JLI, LDI, EI 158 PUSH lp_count 159 PUSHAX lp_start 160 PUSHAX lp_end 161 PUSH blink 162 163 PUSH r11 164 PUSH r10 165 166 ld.as r9, [sp, 10] ; load stashed r9 (status32 stack slot) 167 lr r10, [erstatus] 168 st.as r10, [sp, 10] ; save status32 at it's right stack slot 169 170 PUSH r9 171 PUSH r8 172 PUSH r7 173 PUSH r6 174 PUSH r5 175 PUSH r4 176 PUSH r3 177 PUSH r2 178 PUSH r1 179 PUSH r0 180 181 ; -- for interrupts, regs above are auto-saved by h/w in that order -- 182 ; Now do what ISR prologue does (manually save r12, sp, fp, gp, r25) 183 ; 184 ; Set Z flag if this was from U mode (expected by INTERRUPT_PROLOGUE) 185 ; Although H/w exception micro-ops do set Z flag for U mode (just like 186 ; for interrupts), it could get clobbered in case we soft land here from 187 ; a TLB Miss exception handler (tlbex.S) 188 189 and r10, r10, STATUS_U_MASK 190 xor.f 0, r10, STATUS_U_MASK 191 192 INTERRUPT_PROLOGUE exception 193 194 PUSHAX erbta 195 PUSHAX ecr ; r9 contains ECR, expected by EV_Trap 196 197 PUSH r0 ; orig_r0 198 .endm 199 200 /*------------------------------------------------------------------------*/ 201 .macro EXCEPTION_EPILOGUE 202 203 ; Assumes r0 has PT_status32 204 btst r0, STATUS_U_BIT ; Z flag set if K, used in INTERRUPT_EPILOGUE 205 206 add sp, sp, 8 ; orig_r0/ECR don't need restoring 207 POPAX erbta 208 209 INTERRUPT_EPILOGUE exception 210 211 POP r0 212 POP r1 213 POP r2 214 POP r3 215 POP r4 216 POP r5 217 POP r6 218 POP r7 219 POP r8 220 POP r9 221 POP r10 222 POP r11 223 224 POP blink 225 POPAX lp_end 226 POPAX lp_start 227 228 POP r9 229 mov lp_count, r9 230 231 add sp, sp, 12 ; skip JLI, LDI, EI 232 POPAX eret 233 POPAX erstatus 234 235 ld.as r9, [sp, -12] ; reload r9 which got clobbered 236 .endm 237 238 .macro FAKE_RET_FROM_EXCPN 239 lr r9, [status32] 240 bic r9, r9, (STATUS_U_MASK|STATUS_DE_MASK|STATUS_AE_MASK) 241 or r9, r9, STATUS_IE_MASK 242 kflag r9 243 .endm 244 245 /* Get thread_info of "current" tsk */ 246 .macro GET_CURR_THR_INFO_FROM_SP reg 247 bmskn \reg, sp, THREAD_SHIFT - 1 248 .endm 249 250 /* Get CPU-ID of this core */ 251 .macro GET_CPU_ID reg 252 lr \reg, [identity] 253 xbfu \reg, \reg, 0xE8 /* 00111 01000 */ 254 /* M = 8-1 N = 8 */ 255 .endm 256 257 #endif 258