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