xref: /linux/arch/arc/include/asm/entry-compact.h (revision 8e07e0e3964ca4e23ce7b68e2096fe660a888942)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
4  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
5  *
6  * Vineetg: March 2009 (Supporting 2 levels of Interrupts)
7  *  Stack switching code can no longer reliably rely on the fact that
8  *  if we are NOT in user mode, stack is switched to kernel mode.
9  *  e.g. L2 IRQ interrupted a L1 ISR which had not yet completed
10  *  it's prologue including stack switching from user mode
11  *
12  * Vineetg: Aug 28th 2008: Bug #94984
13  *  -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
14  *   Normally CPU does this automatically, however when doing FAKE rtie,
15  *   we also need to explicitly do this. The problem in macros
16  *   FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit
17  *   was being "CLEARED" rather then "SET". Actually "SET" clears ZOL context
18  *
19  * Vineetg: May 5th 2008
20  *  -Modified CALLEE_REG save/restore macros to handle the fact that
21  *      r25 contains the kernel current task ptr
22  *  - Defined Stack Switching Macro to be reused in all intr/excp hdlrs
23  *  - Shaved off 11 instructions from RESTORE_ALL_INT1 by using the
24  *      address Write back load ld.ab instead of separate ld/add instn
25  *
26  * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
27  */
28 
29 #ifndef __ASM_ARC_ENTRY_COMPACT_H
30 #define __ASM_ARC_ENTRY_COMPACT_H
31 
32 #include <asm/asm-offsets.h>
33 #include <asm/irqflags-compact.h>
34 #include <asm/thread_info.h>	/* For THREAD_SIZE */
35 
36 /* Note on the LD/ST addr modes with addr reg wback
37  *
38  * LD.a same as LD.aw
39  *
40  * LD.a    reg1, [reg2, x]  => Pre Incr
41  *      Eff Addr for load = [reg2 + x]
42  *
43  * LD.ab   reg1, [reg2, x]  => Post Incr
44  *      Eff Addr for load = [reg2]
45  */
46 
47 .macro PUSHAX aux
48 	lr	r9, [\aux]
49 	push	r9
50 .endm
51 
52 .macro POPAX aux
53 	pop	r9
54 	sr	r9, [\aux]
55 .endm
56 
57 .macro  SAVE_R0_TO_R12
58 	push	r0
59 	push	r1
60 	push	r2
61 	push	r3
62 	push	r4
63 	push	r5
64 	push	r6
65 	push	r7
66 	push	r8
67 	push	r9
68 	push	r10
69 	push	r11
70 	push	r12
71 .endm
72 
73 .macro RESTORE_R12_TO_R0
74 	pop	r12
75 	pop	r11
76 	pop	r10
77 	pop	r9
78 	pop	r8
79 	pop	r7
80 	pop	r6
81 	pop	r5
82 	pop	r4
83 	pop	r3
84 	pop	r2
85 	pop	r1
86 	pop	r0
87 .endm
88 
89 .macro SAVE_ABI_CALLEE_REGS
90 	push	r13
91 	push	r14
92 	push	r15
93 	push	r16
94 	push	r17
95 	push	r18
96 	push	r19
97 	push	r20
98 	push	r21
99 	push	r22
100 	push	r23
101 	push	r24
102 	push	r25
103 .endm
104 
105 .macro RESTORE_ABI_CALLEE_REGS
106 	pop	r25
107 	pop	r24
108 	pop	r23
109 	pop	r22
110 	pop	r21
111 	pop	r20
112 	pop	r19
113 	pop	r18
114 	pop	r17
115 	pop	r16
116 	pop	r15
117 	pop	r14
118 	pop	r13
119 .endm
120 
121 /*--------------------------------------------------------------
122  * Switch to Kernel Mode stack if SP points to User Mode stack
123  *
124  * Entry   : r9 contains pre-IRQ/exception/trap status32
125  * Exit    : SP set to K mode stack
126  *           SP at the time of entry (K/U) saved @ pt_regs->sp
127  * Clobbers: r9
128  *-------------------------------------------------------------*/
129 
130 .macro SWITCH_TO_KERNEL_STK
131 
132 	/* User Mode when this happened ? Yes: Proceed to switch stack */
133 	bbit1   r9, STATUS_U_BIT, 88f
134 
135 	/* OK we were already in kernel mode when this event happened, thus can
136 	 * assume SP is kernel mode SP. _NO_ need to do any stack switching
137 	 */
138 
139 #ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
140 	/* However....
141 	 * If Level 2 Interrupts enabled, we may end up with a corner case:
142 	 * 1. User Task executing
143 	 * 2. L1 IRQ taken, ISR starts (CPU auto-switched to KERNEL mode)
144 	 * 3. But before it could switch SP from USER to KERNEL stack
145 	 *      a L2 IRQ "Interrupts" L1
146 	 * Thay way although L2 IRQ happened in Kernel mode, stack is still
147 	 * not switched.
148 	 * To handle this, we may need to switch stack even if in kernel mode
149 	 * provided SP has values in range of USER mode stack ( < 0x7000_0000 )
150 	 */
151 	brlo sp, VMALLOC_START, 88f
152 
153 	/* TODO: vineetg:
154 	 * We need to be a bit more cautious here. What if a kernel bug in
155 	 * L1 ISR, caused SP to go whaco (some small value which looks like
156 	 * USER stk) and then we take L2 ISR.
157 	 * Above brlo alone would treat it as a valid L1-L2 scenario
158 	 * instead of shouting around
159 	 * The only feasible way is to make sure this L2 happened in
160 	 * L1 prelogue ONLY i.e. ilink2 is less than a pre-set marker in
161 	 * L1 ISR before it switches stack
162 	 */
163 
164 #endif
165 
166     /*------Intr/Ecxp happened in kernel mode, SP already setup ------ */
167 	/* save it nevertheless @ pt_regs->sp for uniformity */
168 
169 	b.d	66f
170 	st	sp, [sp, PT_sp - SZ_PT_REGS]
171 
172 88: /*------Intr/Ecxp happened in user mode, "switch" stack ------ */
173 
174 	GET_CURR_TASK_ON_CPU   r9
175 
176 	/* With current tsk in r9, get it's kernel mode stack base */
177 	GET_TSK_STACK_BASE  r9, r9
178 
179 	/* save U mode SP @ pt_regs->sp */
180 	st	sp, [r9, PT_sp - SZ_PT_REGS]
181 
182 	/* final SP switch */
183 	mov	sp, r9
184 66:
185 .endm
186 
187 /*------------------------------------------------------------
188  * "FAKE" a rtie to return from CPU Exception context
189  * This is to re-enable Exceptions within exception
190  * Look at EV_ProtV to see how this is actually used
191  *-------------------------------------------------------------*/
192 
193 .macro FAKE_RET_FROM_EXCPN
194 
195 	lr	r9, [status32]
196 	bclr	r9, r9, STATUS_AE_BIT
197 	or	r9, r9, (STATUS_E1_MASK|STATUS_E2_MASK)
198 	sr	r9, [erstatus]
199 	mov	r9, 55f
200 	sr	r9, [eret]
201 	rtie
202 55:
203 .endm
204 
205 /*--------------------------------------------------------------
206  * For early Exception/ISR Prologue, a core reg is temporarily needed to
207  * code the rest of prolog (stack switching). This is done by stashing
208  * it to memory (non-SMP case) or SCRATCH0 Aux Reg (SMP).
209  *
210  * Before saving the full regfile - this reg is restored back, only
211  * to be saved again on kernel mode stack, as part of pt_regs.
212  *-------------------------------------------------------------*/
213 .macro PROLOG_FREEUP_REG	reg, mem
214 	st  \reg, [\mem]
215 .endm
216 
217 .macro PROLOG_RESTORE_REG	reg, mem
218 	ld  \reg, [\mem]
219 .endm
220 
221 /*--------------------------------------------------------------
222  * Exception Entry prologue
223  * -Switches stack to K mode (if not already)
224  * -Saves the register file
225  *
226  * After this it is safe to call the "C" handlers
227  *-------------------------------------------------------------*/
228 .macro EXCEPTION_PROLOGUE_KEEP_AE
229 
230 	/* Need at least 1 reg to code the early exception prologue */
231 	PROLOG_FREEUP_REG r9, @ex_saved_reg1
232 
233 	/* U/K mode at time of exception (stack not switched if already K) */
234 	lr  r9, [erstatus]
235 
236 	/* ARC700 doesn't provide auto-stack switching */
237 	SWITCH_TO_KERNEL_STK
238 
239 	st.a	r0, [sp, -8]    /* orig_r0 needed for syscall (skip ECR slot) */
240 	sub	sp, sp, 4	/* skip pt_regs->sp, already saved above */
241 
242 	/* Restore r9 used to code the early prologue */
243 	PROLOG_RESTORE_REG  r9, @ex_saved_reg1
244 
245 	/* now we are ready to save the regfile */
246 	SAVE_R0_TO_R12
247 	PUSH	gp
248 	PUSH	fp
249 	PUSH	blink
250 	PUSHAX	eret
251 	PUSHAX	erstatus
252 	PUSH	lp_count
253 	PUSHAX	lp_end
254 	PUSHAX	lp_start
255 	PUSHAX	erbta
256 
257 	lr	r10, [ecr]
258 	st      r10, [sp, PT_event]
259 
260 #ifdef CONFIG_ARC_CURR_IN_REG
261 	/* gp already saved on stack: now load with "current" */
262 	GET_CURR_TASK_ON_CPU   gp
263 #endif
264 	; OUTPUT: r10 has ECR expected by EV_Trap
265 .endm
266 
267 .macro EXCEPTION_PROLOGUE
268 
269 	EXCEPTION_PROLOGUE_KEEP_AE	; return ECR in r10
270 
271 	lr  r0, [efa]
272 	mov r1, sp
273 
274 	FAKE_RET_FROM_EXCPN		; clobbers r9
275 .endm
276 
277 /*--------------------------------------------------------------
278  * Restore all registers used by system call or Exceptions
279  * SP should always be pointing to the next free stack element
280  * when entering this macro.
281  *
282  * NOTE:
283  *
284  * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
285  * for memory load operations. If used in that way interrupts are deffered
286  * by hardware and that is not good.
287  *-------------------------------------------------------------*/
288 .macro EXCEPTION_EPILOGUE
289 
290 	POPAX	erbta
291 	POPAX	lp_start
292 	POPAX	lp_end
293 
294 	POP	r9
295 	mov	lp_count, r9	;LD to lp_count is not allowed
296 
297 	POPAX	erstatus
298 	POPAX	eret
299 	POP	blink
300 	POP	fp
301 	POP	gp
302 	RESTORE_R12_TO_R0
303 
304 	ld  sp, [sp] /* restore original sp */
305 	/* orig_r0, ECR skipped automatically */
306 .endm
307 
308 /* Dummy ECR values for Interrupts */
309 #define event_IRQ1		0x0031abcd
310 #define event_IRQ2		0x0032abcd
311 
312 .macro INTERRUPT_PROLOGUE  LVL
313 
314 	/* free up r9 as scratchpad */
315 	PROLOG_FREEUP_REG r9, @int\LVL\()_saved_reg
316 
317 	/* Which mode (user/kernel) was the system in when intr occurred */
318 	lr  r9, [status32_l\LVL\()]
319 
320 	SWITCH_TO_KERNEL_STK
321 
322 
323 	st.a	0x003\LVL\()abcd, [sp, -4]	/* Dummy ECR */
324 	sub	sp, sp, 8	    /* skip orig_r0 (not needed)
325 				       skip pt_regs->sp, already saved above */
326 
327 	/* Restore r9 used to code the early prologue */
328 	PROLOG_RESTORE_REG  r9, @int\LVL\()_saved_reg
329 
330 	SAVE_R0_TO_R12
331 	PUSH	gp
332 	PUSH	fp
333 	PUSH	blink
334 	PUSH	ilink\LVL\()
335 	PUSHAX	status32_l\LVL\()
336 	PUSH	lp_count
337 	PUSHAX	lp_end
338 	PUSHAX	lp_start
339 	PUSHAX	bta_l\LVL\()
340 
341 #ifdef CONFIG_ARC_CURR_IN_REG
342 	/* gp already saved on stack: now load with "current" */
343 	GET_CURR_TASK_ON_CPU   gp
344 #endif
345 .endm
346 
347 /*--------------------------------------------------------------
348  * Restore all registers used by interrupt handlers.
349  *
350  * NOTE:
351  *
352  * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
353  * for memory load operations. If used in that way interrupts are deffered
354  * by hardware and that is not good.
355  *-------------------------------------------------------------*/
356 .macro INTERRUPT_EPILOGUE  LVL
357 
358 	POPAX	bta_l\LVL\()
359 	POPAX	lp_start
360 	POPAX	lp_end
361 
362 	POP	r9
363 	mov	lp_count, r9	;LD to lp_count is not allowed
364 
365 	POPAX	status32_l\LVL\()
366 	POP	ilink\LVL\()
367 	POP	blink
368 	POP	fp
369 	POP	gp
370 	RESTORE_R12_TO_R0
371 
372 	ld  sp, [sp] /* restore original sp; orig_r0, ECR skipped implicitly */
373 .endm
374 
375 /* Get thread_info of "current" tsk */
376 .macro GET_CURR_THR_INFO_FROM_SP  reg
377 	bic \reg, sp, (THREAD_SIZE - 1)
378 .endm
379 
380 /* Get CPU-ID of this core */
381 .macro  GET_CPU_ID  reg
382 	lr  \reg, [identity]
383 	lsr \reg, \reg, 8
384 	bmsk \reg, \reg, 7
385 .endm
386 
387 #endif  /* __ASM_ARC_ENTRY_COMPACT_H */
388