xref: /openbmc/linux/arch/arc/include/asm/entry-arcv2.h (revision f220d3eb)
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