xref: /linux/arch/arc/include/asm/entry.h (revision 9d42c84f9182da615e7ec0964ce585f23c822349)
1*9d42c84fSVineet Gupta /*
2*9d42c84fSVineet Gupta  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
3*9d42c84fSVineet Gupta  *
4*9d42c84fSVineet Gupta  * This program is free software; you can redistribute it and/or modify
5*9d42c84fSVineet Gupta  * it under the terms of the GNU General Public License version 2 as
6*9d42c84fSVineet Gupta  * published by the Free Software Foundation.
7*9d42c84fSVineet Gupta  *
8*9d42c84fSVineet Gupta  * Vineetg: Aug 28th 2008: Bug #94984
9*9d42c84fSVineet Gupta  *  -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
10*9d42c84fSVineet Gupta  *   Normally CPU does this automatically, however when doing FAKE rtie,
11*9d42c84fSVineet Gupta  *   we also need to explicitly do this. The problem in macros
12*9d42c84fSVineet Gupta  *   FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit
13*9d42c84fSVineet Gupta  *   was being "CLEARED" rather then "SET". Actually "SET" clears ZOL context
14*9d42c84fSVineet Gupta  *
15*9d42c84fSVineet Gupta  * Vineetg: May 5th 2008
16*9d42c84fSVineet Gupta  *  - Defined Stack Switching Macro to be reused in all intr/excp hdlrs
17*9d42c84fSVineet Gupta  *  - Shaved off 11 instructions from RESTORE_ALL_INT1 by using the
18*9d42c84fSVineet Gupta  *      address Write back load ld.ab instead of seperate ld/add instn
19*9d42c84fSVineet Gupta  *
20*9d42c84fSVineet Gupta  * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
21*9d42c84fSVineet Gupta  */
22*9d42c84fSVineet Gupta 
23*9d42c84fSVineet Gupta #ifndef __ASM_ARC_ENTRY_H
24*9d42c84fSVineet Gupta #define __ASM_ARC_ENTRY_H
25*9d42c84fSVineet Gupta 
26*9d42c84fSVineet Gupta #ifdef __ASSEMBLY__
27*9d42c84fSVineet Gupta #include <asm/unistd.h>		/* For NR_syscalls defination */
28*9d42c84fSVineet Gupta #include <asm/asm-offsets.h>
29*9d42c84fSVineet Gupta #include <asm/arcregs.h>
30*9d42c84fSVineet Gupta #include <asm/ptrace.h>
31*9d42c84fSVineet Gupta #include <asm/thread_info.h>	/* For THREAD_SIZE */
32*9d42c84fSVineet Gupta 
33*9d42c84fSVineet Gupta /* Note on the LD/ST addr modes with addr reg wback
34*9d42c84fSVineet Gupta  *
35*9d42c84fSVineet Gupta  * LD.a same as LD.aw
36*9d42c84fSVineet Gupta  *
37*9d42c84fSVineet Gupta  * LD.a    reg1, [reg2, x]  => Pre Incr
38*9d42c84fSVineet Gupta  *      Eff Addr for load = [reg2 + x]
39*9d42c84fSVineet Gupta  *
40*9d42c84fSVineet Gupta  * LD.ab   reg1, [reg2, x]  => Post Incr
41*9d42c84fSVineet Gupta  *      Eff Addr for load = [reg2]
42*9d42c84fSVineet Gupta  */
43*9d42c84fSVineet Gupta 
44*9d42c84fSVineet Gupta /*--------------------------------------------------------------
45*9d42c84fSVineet Gupta  * Save caller saved registers (scratch registers) ( r0 - r12 )
46*9d42c84fSVineet Gupta  * Registers are pushed / popped in the order defined in struct ptregs
47*9d42c84fSVineet Gupta  * in asm/ptrace.h
48*9d42c84fSVineet Gupta  *-------------------------------------------------------------*/
49*9d42c84fSVineet Gupta .macro  SAVE_CALLER_SAVED
50*9d42c84fSVineet Gupta 	st.a    r0, [sp, -4]
51*9d42c84fSVineet Gupta 	st.a    r1, [sp, -4]
52*9d42c84fSVineet Gupta 	st.a    r2, [sp, -4]
53*9d42c84fSVineet Gupta 	st.a    r3, [sp, -4]
54*9d42c84fSVineet Gupta 	st.a    r4, [sp, -4]
55*9d42c84fSVineet Gupta 	st.a    r5, [sp, -4]
56*9d42c84fSVineet Gupta 	st.a    r6, [sp, -4]
57*9d42c84fSVineet Gupta 	st.a    r7, [sp, -4]
58*9d42c84fSVineet Gupta 	st.a    r8, [sp, -4]
59*9d42c84fSVineet Gupta 	st.a    r9, [sp, -4]
60*9d42c84fSVineet Gupta 	st.a    r10, [sp, -4]
61*9d42c84fSVineet Gupta 	st.a    r11, [sp, -4]
62*9d42c84fSVineet Gupta 	st.a    r12, [sp, -4]
63*9d42c84fSVineet Gupta .endm
64*9d42c84fSVineet Gupta 
65*9d42c84fSVineet Gupta /*--------------------------------------------------------------
66*9d42c84fSVineet Gupta  * Restore caller saved registers (scratch registers)
67*9d42c84fSVineet Gupta  *-------------------------------------------------------------*/
68*9d42c84fSVineet Gupta .macro RESTORE_CALLER_SAVED
69*9d42c84fSVineet Gupta 	ld.ab   r12, [sp, 4]
70*9d42c84fSVineet Gupta 	ld.ab   r11, [sp, 4]
71*9d42c84fSVineet Gupta 	ld.ab   r10, [sp, 4]
72*9d42c84fSVineet Gupta 	ld.ab   r9, [sp, 4]
73*9d42c84fSVineet Gupta 	ld.ab   r8, [sp, 4]
74*9d42c84fSVineet Gupta 	ld.ab   r7, [sp, 4]
75*9d42c84fSVineet Gupta 	ld.ab   r6, [sp, 4]
76*9d42c84fSVineet Gupta 	ld.ab   r5, [sp, 4]
77*9d42c84fSVineet Gupta 	ld.ab   r4, [sp, 4]
78*9d42c84fSVineet Gupta 	ld.ab   r3, [sp, 4]
79*9d42c84fSVineet Gupta 	ld.ab   r2, [sp, 4]
80*9d42c84fSVineet Gupta 	ld.ab   r1, [sp, 4]
81*9d42c84fSVineet Gupta 	ld.ab   r0, [sp, 4]
82*9d42c84fSVineet Gupta .endm
83*9d42c84fSVineet Gupta 
84*9d42c84fSVineet Gupta 
85*9d42c84fSVineet Gupta /*--------------------------------------------------------------
86*9d42c84fSVineet Gupta  * Save callee saved registers (non scratch registers) ( r13 - r25 )
87*9d42c84fSVineet Gupta  *  on kernel stack.
88*9d42c84fSVineet Gupta  * User mode callee regs need to be saved in case of
89*9d42c84fSVineet Gupta  *    -fork and friends for replicating from parent to child
90*9d42c84fSVineet Gupta  *    -before going into do_signal( ) for ptrace/core-dump
91*9d42c84fSVineet Gupta  * Special case handling is required for r25 in case it is used by kernel
92*9d42c84fSVineet Gupta  *  for caching task ptr. Low level exception/ISR save user mode r25
93*9d42c84fSVineet Gupta  *  into task->thread.user_r25. So it needs to be retrieved from there and
94*9d42c84fSVineet Gupta  *  saved into kernel stack with rest of callee reg-file
95*9d42c84fSVineet Gupta  *-------------------------------------------------------------*/
96*9d42c84fSVineet Gupta .macro SAVE_CALLEE_SAVED_USER
97*9d42c84fSVineet Gupta 	st.a    r13, [sp, -4]
98*9d42c84fSVineet Gupta 	st.a    r14, [sp, -4]
99*9d42c84fSVineet Gupta 	st.a    r15, [sp, -4]
100*9d42c84fSVineet Gupta 	st.a    r16, [sp, -4]
101*9d42c84fSVineet Gupta 	st.a    r17, [sp, -4]
102*9d42c84fSVineet Gupta 	st.a    r18, [sp, -4]
103*9d42c84fSVineet Gupta 	st.a    r19, [sp, -4]
104*9d42c84fSVineet Gupta 	st.a    r20, [sp, -4]
105*9d42c84fSVineet Gupta 	st.a    r21, [sp, -4]
106*9d42c84fSVineet Gupta 	st.a    r22, [sp, -4]
107*9d42c84fSVineet Gupta 	st.a    r23, [sp, -4]
108*9d42c84fSVineet Gupta 	st.a    r24, [sp, -4]
109*9d42c84fSVineet Gupta 	st.a    r25, [sp, -4]
110*9d42c84fSVineet Gupta 
111*9d42c84fSVineet Gupta 	/* move up by 1 word to "create" callee_regs->"stack_place_holder" */
112*9d42c84fSVineet Gupta 	sub sp, sp, 4
113*9d42c84fSVineet Gupta .endm
114*9d42c84fSVineet Gupta 
115*9d42c84fSVineet Gupta /*--------------------------------------------------------------
116*9d42c84fSVineet Gupta  * Save callee saved registers (non scratch registers) ( r13 - r25 )
117*9d42c84fSVineet Gupta  * kernel mode callee regs needed to be saved in case of context switch
118*9d42c84fSVineet Gupta  * If r25 is used for caching task pointer then that need not be saved
119*9d42c84fSVineet Gupta  * as it can be re-created from current task global
120*9d42c84fSVineet Gupta  *-------------------------------------------------------------*/
121*9d42c84fSVineet Gupta .macro SAVE_CALLEE_SAVED_KERNEL
122*9d42c84fSVineet Gupta 	st.a    r13, [sp, -4]
123*9d42c84fSVineet Gupta 	st.a    r14, [sp, -4]
124*9d42c84fSVineet Gupta 	st.a    r15, [sp, -4]
125*9d42c84fSVineet Gupta 	st.a    r16, [sp, -4]
126*9d42c84fSVineet Gupta 	st.a    r17, [sp, -4]
127*9d42c84fSVineet Gupta 	st.a    r18, [sp, -4]
128*9d42c84fSVineet Gupta 	st.a    r19, [sp, -4]
129*9d42c84fSVineet Gupta 	st.a    r20, [sp, -4]
130*9d42c84fSVineet Gupta 	st.a    r21, [sp, -4]
131*9d42c84fSVineet Gupta 	st.a    r22, [sp, -4]
132*9d42c84fSVineet Gupta 	st.a    r23, [sp, -4]
133*9d42c84fSVineet Gupta 	st.a    r24, [sp, -4]
134*9d42c84fSVineet Gupta 	st.a    r25, [sp, -4]
135*9d42c84fSVineet Gupta 	sub     sp, sp, 4
136*9d42c84fSVineet Gupta .endm
137*9d42c84fSVineet Gupta 
138*9d42c84fSVineet Gupta /*--------------------------------------------------------------
139*9d42c84fSVineet Gupta  * RESTORE_CALLEE_SAVED_KERNEL:
140*9d42c84fSVineet Gupta  * Loads callee (non scratch) Reg File by popping from Kernel mode stack.
141*9d42c84fSVineet Gupta  *  This is reverse of SAVE_CALLEE_SAVED,
142*9d42c84fSVineet Gupta  *
143*9d42c84fSVineet Gupta  * NOTE:
144*9d42c84fSVineet Gupta  * Ideally this shd only be called in switch_to for loading
145*9d42c84fSVineet Gupta  *  switched-IN task's CALLEE Reg File.
146*9d42c84fSVineet Gupta  *  For all other cases RESTORE_CALLEE_SAVED_FAST must be used
147*9d42c84fSVineet Gupta  *  which simply pops the stack w/o touching regs.
148*9d42c84fSVineet Gupta  *-------------------------------------------------------------*/
149*9d42c84fSVineet Gupta .macro RESTORE_CALLEE_SAVED_KERNEL
150*9d42c84fSVineet Gupta 
151*9d42c84fSVineet Gupta 	add     sp, sp, 4   /* skip "callee_regs->stack_place_holder" */
152*9d42c84fSVineet Gupta 	ld.ab   r25, [sp, 4]
153*9d42c84fSVineet Gupta 	ld.ab   r24, [sp, 4]
154*9d42c84fSVineet Gupta 	ld.ab   r23, [sp, 4]
155*9d42c84fSVineet Gupta 	ld.ab   r22, [sp, 4]
156*9d42c84fSVineet Gupta 	ld.ab   r21, [sp, 4]
157*9d42c84fSVineet Gupta 	ld.ab   r20, [sp, 4]
158*9d42c84fSVineet Gupta 	ld.ab   r19, [sp, 4]
159*9d42c84fSVineet Gupta 	ld.ab   r18, [sp, 4]
160*9d42c84fSVineet Gupta 	ld.ab   r17, [sp, 4]
161*9d42c84fSVineet Gupta 	ld.ab   r16, [sp, 4]
162*9d42c84fSVineet Gupta 	ld.ab   r15, [sp, 4]
163*9d42c84fSVineet Gupta 	ld.ab   r14, [sp, 4]
164*9d42c84fSVineet Gupta 	ld.ab   r13, [sp, 4]
165*9d42c84fSVineet Gupta 
166*9d42c84fSVineet Gupta .endm
167*9d42c84fSVineet Gupta 
168*9d42c84fSVineet Gupta /*--------------------------------------------------------------
169*9d42c84fSVineet Gupta  * Super FAST Restore callee saved regs by simply re-adjusting SP
170*9d42c84fSVineet Gupta  *-------------------------------------------------------------*/
171*9d42c84fSVineet Gupta .macro DISCARD_CALLEE_SAVED_USER
172*9d42c84fSVineet Gupta 	add     sp, sp, 14 * 4
173*9d42c84fSVineet Gupta .endm
174*9d42c84fSVineet Gupta 
175*9d42c84fSVineet Gupta /*--------------------------------------------------------------
176*9d42c84fSVineet Gupta  * Restore User mode r25 saved in task_struct->thread.user_r25
177*9d42c84fSVineet Gupta  *-------------------------------------------------------------*/
178*9d42c84fSVineet Gupta .macro RESTORE_USER_R25
179*9d42c84fSVineet Gupta 	ld  r25, [r25, TASK_THREAD + THREAD_USER_R25]
180*9d42c84fSVineet Gupta .endm
181*9d42c84fSVineet Gupta 
182*9d42c84fSVineet Gupta /*-------------------------------------------------------------
183*9d42c84fSVineet Gupta  * given a tsk struct, get to the base of it's kernel mode stack
184*9d42c84fSVineet Gupta  * tsk->thread_info is really a PAGE, whose bottom hoists stack
185*9d42c84fSVineet Gupta  * which grows upwards towards thread_info
186*9d42c84fSVineet Gupta  *------------------------------------------------------------*/
187*9d42c84fSVineet Gupta 
188*9d42c84fSVineet Gupta .macro GET_TSK_STACK_BASE tsk, out
189*9d42c84fSVineet Gupta 
190*9d42c84fSVineet Gupta 	/* Get task->thread_info (this is essentially start of a PAGE) */
191*9d42c84fSVineet Gupta 	ld  \out, [\tsk, TASK_THREAD_INFO]
192*9d42c84fSVineet Gupta 
193*9d42c84fSVineet Gupta 	/* Go to end of page where stack begins (grows upwards) */
194*9d42c84fSVineet Gupta 	add2 \out, \out, (THREAD_SIZE - 4)/4   /* one word GUTTER */
195*9d42c84fSVineet Gupta 
196*9d42c84fSVineet Gupta .endm
197*9d42c84fSVineet Gupta 
198*9d42c84fSVineet Gupta /*--------------------------------------------------------------
199*9d42c84fSVineet Gupta  * Switch to Kernel Mode stack if SP points to User Mode stack
200*9d42c84fSVineet Gupta  *
201*9d42c84fSVineet Gupta  * Entry   : r9 contains pre-IRQ/exception/trap status32
202*9d42c84fSVineet Gupta  * Exit    : SP is set to kernel mode stack pointer
203*9d42c84fSVineet Gupta  * Clobbers: r9
204*9d42c84fSVineet Gupta  *-------------------------------------------------------------*/
205*9d42c84fSVineet Gupta 
206*9d42c84fSVineet Gupta .macro SWITCH_TO_KERNEL_STK
207*9d42c84fSVineet Gupta 
208*9d42c84fSVineet Gupta 	/* User Mode when this happened ? Yes: Proceed to switch stack */
209*9d42c84fSVineet Gupta 	bbit1   r9, STATUS_U_BIT, 88f
210*9d42c84fSVineet Gupta 
211*9d42c84fSVineet Gupta 	/* OK we were already in kernel mode when this event happened, thus can
212*9d42c84fSVineet Gupta 	 * assume SP is kernel mode SP. _NO_ need to do any stack switching
213*9d42c84fSVineet Gupta 	 */
214*9d42c84fSVineet Gupta 
215*9d42c84fSVineet Gupta 	/* Save Pre Intr/Exception KERNEL MODE SP on kernel stack
216*9d42c84fSVineet Gupta 	 * safe-keeping not really needed, but it keeps the epilogue code
217*9d42c84fSVineet Gupta 	 * (SP restore) simpler/uniform.
218*9d42c84fSVineet Gupta 	 */
219*9d42c84fSVineet Gupta 	b.d	77f
220*9d42c84fSVineet Gupta 
221*9d42c84fSVineet Gupta 	st.a	sp, [sp, -12]	; Make room for orig_r0 and orig_r8
222*9d42c84fSVineet Gupta 
223*9d42c84fSVineet Gupta 88: /*------Intr/Ecxp happened in user mode, "switch" stack ------ */
224*9d42c84fSVineet Gupta 
225*9d42c84fSVineet Gupta 	GET_CURR_TASK_ON_CPU   r9
226*9d42c84fSVineet Gupta 
227*9d42c84fSVineet Gupta 	/* With current tsk in r9, get it's kernel mode stack base */
228*9d42c84fSVineet Gupta 	GET_TSK_STACK_BASE  r9, r9
229*9d42c84fSVineet Gupta 
230*9d42c84fSVineet Gupta #ifdef PT_REGS_CANARY
231*9d42c84fSVineet Gupta 	st	0xabcdabcd, [r9, 0]
232*9d42c84fSVineet Gupta #endif
233*9d42c84fSVineet Gupta 
234*9d42c84fSVineet Gupta 	/* Save Pre Intr/Exception User SP on kernel stack */
235*9d42c84fSVineet Gupta 	st.a    sp, [r9, -12]	; Make room for orig_r0 and orig_r8
236*9d42c84fSVineet Gupta 
237*9d42c84fSVineet Gupta 	/* CAUTION:
238*9d42c84fSVineet Gupta 	 * SP should be set at the very end when we are done with everything
239*9d42c84fSVineet Gupta 	 * In case of 2 levels of interrupt we depend on value of SP to assume
240*9d42c84fSVineet Gupta 	 * that everything else is done (loading r25 etc)
241*9d42c84fSVineet Gupta 	 */
242*9d42c84fSVineet Gupta 
243*9d42c84fSVineet Gupta 	/* set SP to point to kernel mode stack */
244*9d42c84fSVineet Gupta 	mov sp, r9
245*9d42c84fSVineet Gupta 
246*9d42c84fSVineet Gupta 77: /* ----- Stack Switched to kernel Mode, Now save REG FILE ----- */
247*9d42c84fSVineet Gupta 
248*9d42c84fSVineet Gupta .endm
249*9d42c84fSVineet Gupta 
250*9d42c84fSVineet Gupta /*------------------------------------------------------------
251*9d42c84fSVineet Gupta  * "FAKE" a rtie to return from CPU Exception context
252*9d42c84fSVineet Gupta  * This is to re-enable Exceptions within exception
253*9d42c84fSVineet Gupta  * Look at EV_ProtV to see how this is actually used
254*9d42c84fSVineet Gupta  *-------------------------------------------------------------*/
255*9d42c84fSVineet Gupta 
256*9d42c84fSVineet Gupta .macro FAKE_RET_FROM_EXCPN  reg
257*9d42c84fSVineet Gupta 
258*9d42c84fSVineet Gupta 	ld  \reg, [sp, PT_status32]
259*9d42c84fSVineet Gupta 	bic  \reg, \reg, (STATUS_U_MASK|STATUS_DE_MASK)
260*9d42c84fSVineet Gupta 	bset \reg, \reg, STATUS_L_BIT
261*9d42c84fSVineet Gupta 	sr  \reg, [erstatus]
262*9d42c84fSVineet Gupta 	mov \reg, 55f
263*9d42c84fSVineet Gupta 	sr  \reg, [eret]
264*9d42c84fSVineet Gupta 
265*9d42c84fSVineet Gupta 	rtie
266*9d42c84fSVineet Gupta 55:
267*9d42c84fSVineet Gupta .endm
268*9d42c84fSVineet Gupta 
269*9d42c84fSVineet Gupta /*
270*9d42c84fSVineet Gupta  * @reg [OUT] &thread_info of "current"
271*9d42c84fSVineet Gupta  */
272*9d42c84fSVineet Gupta .macro GET_CURR_THR_INFO_FROM_SP  reg
273*9d42c84fSVineet Gupta 	and \reg, sp, ~(THREAD_SIZE - 1)
274*9d42c84fSVineet Gupta .endm
275*9d42c84fSVineet Gupta 
276*9d42c84fSVineet Gupta /*
277*9d42c84fSVineet Gupta  * @reg [OUT] thread_info->flags of "current"
278*9d42c84fSVineet Gupta  */
279*9d42c84fSVineet Gupta .macro GET_CURR_THR_INFO_FLAGS  reg
280*9d42c84fSVineet Gupta 	GET_CURR_THR_INFO_FROM_SP  \reg
281*9d42c84fSVineet Gupta 	ld  \reg, [\reg, THREAD_INFO_FLAGS]
282*9d42c84fSVineet Gupta .endm
283*9d42c84fSVineet Gupta 
284*9d42c84fSVineet Gupta /*--------------------------------------------------------------
285*9d42c84fSVineet Gupta  * For early Exception Prologue, a core reg is temporarily needed to
286*9d42c84fSVineet Gupta  * code the rest of prolog (stack switching). This is done by stashing
287*9d42c84fSVineet Gupta  * it to memory (non-SMP case) or SCRATCH0 Aux Reg (SMP).
288*9d42c84fSVineet Gupta  *
289*9d42c84fSVineet Gupta  * Before saving the full regfile - this reg is restored back, only
290*9d42c84fSVineet Gupta  * to be saved again on kernel mode stack, as part of ptregs.
291*9d42c84fSVineet Gupta  *-------------------------------------------------------------*/
292*9d42c84fSVineet Gupta .macro EXCPN_PROLOG_FREEUP_REG	reg
293*9d42c84fSVineet Gupta 	st  \reg, [@ex_saved_reg1]
294*9d42c84fSVineet Gupta .endm
295*9d42c84fSVineet Gupta 
296*9d42c84fSVineet Gupta .macro EXCPN_PROLOG_RESTORE_REG	reg
297*9d42c84fSVineet Gupta 	ld  \reg, [@ex_saved_reg1]
298*9d42c84fSVineet Gupta .endm
299*9d42c84fSVineet Gupta 
300*9d42c84fSVineet Gupta /*--------------------------------------------------------------
301*9d42c84fSVineet Gupta  * Save all registers used by Exceptions (TLB Miss, Prot-V, Mem err etc)
302*9d42c84fSVineet Gupta  * Requires SP to be already switched to kernel mode Stack
303*9d42c84fSVineet Gupta  * sp points to the next free element on the stack at exit of this macro.
304*9d42c84fSVineet Gupta  * Registers are pushed / popped in the order defined in struct ptregs
305*9d42c84fSVineet Gupta  * in asm/ptrace.h
306*9d42c84fSVineet Gupta  * Note that syscalls are implemented via TRAP which is also a exception
307*9d42c84fSVineet Gupta  * from CPU's point of view
308*9d42c84fSVineet Gupta  *-------------------------------------------------------------*/
309*9d42c84fSVineet Gupta .macro SAVE_ALL_EXCEPTION   marker
310*9d42c84fSVineet Gupta 
311*9d42c84fSVineet Gupta 	/* Restore r9 used to code the early prologue */
312*9d42c84fSVineet Gupta 	EXCPN_PROLOG_RESTORE_REG  r9
313*9d42c84fSVineet Gupta 
314*9d42c84fSVineet Gupta 	/* Save the complete regfile now */
315*9d42c84fSVineet Gupta 
316*9d42c84fSVineet Gupta 	/* orig_r8 marker:
317*9d42c84fSVineet Gupta 	 * syscalls   -> 1 to NR_SYSCALLS
318*9d42c84fSVineet Gupta 	 * Exceptions -> NR_SYSCALLS + 1
319*9d42c84fSVineet Gupta 	 * Break-point-> NR_SYSCALLS + 2
320*9d42c84fSVineet Gupta 	 */
321*9d42c84fSVineet Gupta 	st      \marker, [sp, 8]
322*9d42c84fSVineet Gupta 	st      r0, [sp, 4]    /* orig_r0, needed only for sys calls */
323*9d42c84fSVineet Gupta 	SAVE_CALLER_SAVED
324*9d42c84fSVineet Gupta 	st.a    r26, [sp, -4]   /* gp */
325*9d42c84fSVineet Gupta 	st.a    fp, [sp, -4]
326*9d42c84fSVineet Gupta 	st.a    blink, [sp, -4]
327*9d42c84fSVineet Gupta 	lr	r9, [eret]
328*9d42c84fSVineet Gupta 	st.a    r9, [sp, -4]
329*9d42c84fSVineet Gupta 	lr	r9, [erstatus]
330*9d42c84fSVineet Gupta 	st.a    r9, [sp, -4]
331*9d42c84fSVineet Gupta 	st.a    lp_count, [sp, -4]
332*9d42c84fSVineet Gupta 	lr	r9, [lp_end]
333*9d42c84fSVineet Gupta 	st.a    r9, [sp, -4]
334*9d42c84fSVineet Gupta 	lr	r9, [lp_start]
335*9d42c84fSVineet Gupta 	st.a    r9, [sp, -4]
336*9d42c84fSVineet Gupta 	lr	r9, [erbta]
337*9d42c84fSVineet Gupta 	st.a    r9, [sp, -4]
338*9d42c84fSVineet Gupta 
339*9d42c84fSVineet Gupta #ifdef PT_REGS_CANARY
340*9d42c84fSVineet Gupta 	mov   r9, 0xdeadbeef
341*9d42c84fSVineet Gupta 	st    r9, [sp, -4]
342*9d42c84fSVineet Gupta #endif
343*9d42c84fSVineet Gupta 
344*9d42c84fSVineet Gupta 	/* move up by 1 word to "create" pt_regs->"stack_place_holder" */
345*9d42c84fSVineet Gupta 	sub sp, sp, 4
346*9d42c84fSVineet Gupta .endm
347*9d42c84fSVineet Gupta 
348*9d42c84fSVineet Gupta /*--------------------------------------------------------------
349*9d42c84fSVineet Gupta  * Save scratch regs for exceptions
350*9d42c84fSVineet Gupta  *-------------------------------------------------------------*/
351*9d42c84fSVineet Gupta .macro SAVE_ALL_SYS
352*9d42c84fSVineet Gupta 	SAVE_ALL_EXCEPTION  (NR_syscalls + 1)
353*9d42c84fSVineet Gupta .endm
354*9d42c84fSVineet Gupta 
355*9d42c84fSVineet Gupta /*--------------------------------------------------------------
356*9d42c84fSVineet Gupta  * Save scratch regs for sys calls
357*9d42c84fSVineet Gupta  *-------------------------------------------------------------*/
358*9d42c84fSVineet Gupta .macro SAVE_ALL_TRAP
359*9d42c84fSVineet Gupta 	SAVE_ALL_EXCEPTION  r8
360*9d42c84fSVineet Gupta .endm
361*9d42c84fSVineet Gupta 
362*9d42c84fSVineet Gupta /*--------------------------------------------------------------
363*9d42c84fSVineet Gupta  * Restore all registers used by system call or Exceptions
364*9d42c84fSVineet Gupta  * SP should always be pointing to the next free stack element
365*9d42c84fSVineet Gupta  * when entering this macro.
366*9d42c84fSVineet Gupta  *
367*9d42c84fSVineet Gupta  * NOTE:
368*9d42c84fSVineet Gupta  *
369*9d42c84fSVineet Gupta  * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
370*9d42c84fSVineet Gupta  * for memory load operations. If used in that way interrupts are deffered
371*9d42c84fSVineet Gupta  * by hardware and that is not good.
372*9d42c84fSVineet Gupta  *-------------------------------------------------------------*/
373*9d42c84fSVineet Gupta .macro RESTORE_ALL_SYS
374*9d42c84fSVineet Gupta 
375*9d42c84fSVineet Gupta 	add sp, sp, 4       /* hop over unused "pt_regs->stack_place_holder" */
376*9d42c84fSVineet Gupta 
377*9d42c84fSVineet Gupta 	ld.ab   r9, [sp, 4]
378*9d42c84fSVineet Gupta 	sr	r9, [erbta]
379*9d42c84fSVineet Gupta 	ld.ab   r9, [sp, 4]
380*9d42c84fSVineet Gupta 	sr	r9, [lp_start]
381*9d42c84fSVineet Gupta 	ld.ab   r9, [sp, 4]
382*9d42c84fSVineet Gupta 	sr	r9, [lp_end]
383*9d42c84fSVineet Gupta 	ld.ab   r9, [sp, 4]
384*9d42c84fSVineet Gupta 	mov	lp_count, r9
385*9d42c84fSVineet Gupta 	ld.ab   r9, [sp, 4]
386*9d42c84fSVineet Gupta 	sr	r9, [erstatus]
387*9d42c84fSVineet Gupta 	ld.ab   r9, [sp, 4]
388*9d42c84fSVineet Gupta 	sr	r9, [eret]
389*9d42c84fSVineet Gupta 	ld.ab   blink, [sp, 4]
390*9d42c84fSVineet Gupta 	ld.ab   fp, [sp, 4]
391*9d42c84fSVineet Gupta 	ld.ab   r26, [sp, 4]    /* gp */
392*9d42c84fSVineet Gupta 	RESTORE_CALLER_SAVED
393*9d42c84fSVineet Gupta 
394*9d42c84fSVineet Gupta 	ld  sp, [sp] /* restore original sp */
395*9d42c84fSVineet Gupta 	/* orig_r0 and orig_r8 skipped automatically */
396*9d42c84fSVineet Gupta .endm
397*9d42c84fSVineet Gupta 
398*9d42c84fSVineet Gupta 
399*9d42c84fSVineet Gupta /*--------------------------------------------------------------
400*9d42c84fSVineet Gupta  * Save all registers used by interrupt handlers.
401*9d42c84fSVineet Gupta  *-------------------------------------------------------------*/
402*9d42c84fSVineet Gupta .macro SAVE_ALL_INT1
403*9d42c84fSVineet Gupta 
404*9d42c84fSVineet Gupta 	/* restore original r9 , saved in int1_saved_reg
405*9d42c84fSVineet Gupta 	* It will be saved on stack in macro: SAVE_CALLER_SAVED
406*9d42c84fSVineet Gupta 	*/
407*9d42c84fSVineet Gupta 	ld  r9, [@int1_saved_reg]
408*9d42c84fSVineet Gupta 
409*9d42c84fSVineet Gupta 	/* now we are ready to save the remaining context :) */
410*9d42c84fSVineet Gupta 	st     -1, [sp, 8]    /* orig_r8, -1 for interuppt level one */
411*9d42c84fSVineet Gupta 	st      0, [sp, 4]    /* orig_r0 , N/A for IRQ */
412*9d42c84fSVineet Gupta 	SAVE_CALLER_SAVED
413*9d42c84fSVineet Gupta 	st.a    r26, [sp, -4]   /* gp */
414*9d42c84fSVineet Gupta 	st.a    fp, [sp, -4]
415*9d42c84fSVineet Gupta 	st.a    blink, [sp, -4]
416*9d42c84fSVineet Gupta 	st.a    ilink1, [sp, -4]
417*9d42c84fSVineet Gupta 	lr	r9, [status32_l1]
418*9d42c84fSVineet Gupta 	st.a    r9, [sp, -4]
419*9d42c84fSVineet Gupta 	st.a    lp_count, [sp, -4]
420*9d42c84fSVineet Gupta 	lr	r9, [lp_end]
421*9d42c84fSVineet Gupta 	st.a    r9, [sp, -4]
422*9d42c84fSVineet Gupta 	lr	r9, [lp_start]
423*9d42c84fSVineet Gupta 	st.a    r9, [sp, -4]
424*9d42c84fSVineet Gupta 	lr	r9, [bta_l1]
425*9d42c84fSVineet Gupta 	st.a    r9, [sp, -4]
426*9d42c84fSVineet Gupta 
427*9d42c84fSVineet Gupta #ifdef PT_REGS_CANARY
428*9d42c84fSVineet Gupta 	mov   r9, 0xdeadbee1
429*9d42c84fSVineet Gupta 	st    r9, [sp, -4]
430*9d42c84fSVineet Gupta #endif
431*9d42c84fSVineet Gupta 	/* move up by 1 word to "create" pt_regs->"stack_place_holder" */
432*9d42c84fSVineet Gupta 	sub sp, sp, 4
433*9d42c84fSVineet Gupta .endm
434*9d42c84fSVineet Gupta 
435*9d42c84fSVineet Gupta /*--------------------------------------------------------------
436*9d42c84fSVineet Gupta  * Restore all registers used by interrupt handlers.
437*9d42c84fSVineet Gupta  *
438*9d42c84fSVineet Gupta  * NOTE:
439*9d42c84fSVineet Gupta  *
440*9d42c84fSVineet Gupta  * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
441*9d42c84fSVineet Gupta  * for memory load operations. If used in that way interrupts are deffered
442*9d42c84fSVineet Gupta  * by hardware and that is not good.
443*9d42c84fSVineet Gupta  *-------------------------------------------------------------*/
444*9d42c84fSVineet Gupta 
445*9d42c84fSVineet Gupta .macro RESTORE_ALL_INT1
446*9d42c84fSVineet Gupta 	add sp, sp, 4       /* hop over unused "pt_regs->stack_place_holder" */
447*9d42c84fSVineet Gupta 
448*9d42c84fSVineet Gupta 	ld.ab   r9, [sp, 4] /* Actual reg file */
449*9d42c84fSVineet Gupta 	sr	r9, [bta_l1]
450*9d42c84fSVineet Gupta 	ld.ab   r9, [sp, 4]
451*9d42c84fSVineet Gupta 	sr	r9, [lp_start]
452*9d42c84fSVineet Gupta 	ld.ab   r9, [sp, 4]
453*9d42c84fSVineet Gupta 	sr	r9, [lp_end]
454*9d42c84fSVineet Gupta 	ld.ab   r9, [sp, 4]
455*9d42c84fSVineet Gupta 	mov	lp_count, r9
456*9d42c84fSVineet Gupta 	ld.ab   r9, [sp, 4]
457*9d42c84fSVineet Gupta 	sr	r9, [status32_l1]
458*9d42c84fSVineet Gupta 	ld.ab   r9, [sp, 4]
459*9d42c84fSVineet Gupta 	mov	ilink1, r9
460*9d42c84fSVineet Gupta 	ld.ab   blink, [sp, 4]
461*9d42c84fSVineet Gupta 	ld.ab   fp, [sp, 4]
462*9d42c84fSVineet Gupta 	ld.ab   r26, [sp, 4]    /* gp */
463*9d42c84fSVineet Gupta 	RESTORE_CALLER_SAVED
464*9d42c84fSVineet Gupta 
465*9d42c84fSVineet Gupta 	ld  sp, [sp] /* restore original sp */
466*9d42c84fSVineet Gupta 	/* orig_r0 and orig_r8 skipped automatically */
467*9d42c84fSVineet Gupta .endm
468*9d42c84fSVineet Gupta 
469*9d42c84fSVineet Gupta /* Get CPU-ID of this core */
470*9d42c84fSVineet Gupta .macro  GET_CPU_ID  reg
471*9d42c84fSVineet Gupta 	lr  \reg, [identity]
472*9d42c84fSVineet Gupta 	lsr \reg, \reg, 8
473*9d42c84fSVineet Gupta 	bmsk \reg, \reg, 7
474*9d42c84fSVineet Gupta .endm
475*9d42c84fSVineet Gupta 
476*9d42c84fSVineet Gupta .macro  GET_CURR_TASK_ON_CPU    reg
477*9d42c84fSVineet Gupta 	ld  \reg, [@_current_task]
478*9d42c84fSVineet Gupta .endm
479*9d42c84fSVineet Gupta 
480*9d42c84fSVineet Gupta .macro  SET_CURR_TASK_ON_CPU    tsk, tmp
481*9d42c84fSVineet Gupta 	st  \tsk, [@_current_task]
482*9d42c84fSVineet Gupta .endm
483*9d42c84fSVineet Gupta 
484*9d42c84fSVineet Gupta /* ------------------------------------------------------------------
485*9d42c84fSVineet Gupta  * Get the ptr to some field of Current Task at @off in task struct
486*9d42c84fSVineet Gupta  */
487*9d42c84fSVineet Gupta 
488*9d42c84fSVineet Gupta .macro GET_CURR_TASK_FIELD_PTR  off,  reg
489*9d42c84fSVineet Gupta 	GET_CURR_TASK_ON_CPU  \reg
490*9d42c84fSVineet Gupta 	add \reg, \reg, \off
491*9d42c84fSVineet Gupta .endm
492*9d42c84fSVineet Gupta 
493*9d42c84fSVineet Gupta #endif  /* __ASSEMBLY__ */
494*9d42c84fSVineet Gupta 
495*9d42c84fSVineet Gupta #endif  /* __ASM_ARC_ENTRY_H */
496