xref: /linux/arch/arc/include/asm/entry.h (revision 820970a5aa3c98be26e1df64da4b93294d20d4e7)
1 /*
2  * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
3  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  */
9 
10 #ifndef __ASM_ARC_ENTRY_H
11 #define __ASM_ARC_ENTRY_H
12 
13 #include <asm/unistd.h>		/* For NR_syscalls defination */
14 #include <asm/arcregs.h>
15 #include <asm/ptrace.h>
16 #include <asm/processor.h>	/* For VMALLOC_START */
17 #include <asm/mmu.h>
18 
19 #include <asm/entry-compact.h>	/* ISA specific bits */
20 
21 /* Note on the LD/ST addr modes with addr reg wback
22  *
23  * LD.a same as LD.aw
24  *
25  * LD.a    reg1, [reg2, x]  => Pre Incr
26  *      Eff Addr for load = [reg2 + x]
27  *
28  * LD.ab   reg1, [reg2, x]  => Post Incr
29  *      Eff Addr for load = [reg2]
30  */
31 
32 .macro PUSH reg
33 	st.a	\reg, [sp, -4]
34 .endm
35 
36 .macro PUSHAX aux
37 	lr	r9, [\aux]
38 	PUSH	r9
39 .endm
40 
41 .macro POP reg
42 	ld.ab	\reg, [sp, 4]
43 .endm
44 
45 .macro POPAX aux
46 	POP	r9
47 	sr	r9, [\aux]
48 .endm
49 
50 /*--------------------------------------------------------------
51  * Helpers to save/restore Scratch Regs:
52  * used by Interrupt/Exception Prologue/Epilogue
53  *-------------------------------------------------------------*/
54 .macro  SAVE_R0_TO_R12
55 	PUSH	r0
56 	PUSH	r1
57 	PUSH	r2
58 	PUSH	r3
59 	PUSH	r4
60 	PUSH	r5
61 	PUSH	r6
62 	PUSH	r7
63 	PUSH	r8
64 	PUSH	r9
65 	PUSH	r10
66 	PUSH	r11
67 	PUSH	r12
68 .endm
69 
70 .macro RESTORE_R12_TO_R0
71 	POP	r12
72 	POP	r11
73 	POP	r10
74 	POP	r9
75 	POP	r8
76 	POP	r7
77 	POP	r6
78 	POP	r5
79 	POP	r4
80 	POP	r3
81 	POP	r2
82 	POP	r1
83 	POP	r0
84 
85 #ifdef CONFIG_ARC_CURR_IN_REG
86 	ld	r25, [sp, 12]
87 #endif
88 .endm
89 
90 /*--------------------------------------------------------------
91  * Helpers to save/restore callee-saved regs:
92  * used by several macros below
93  *-------------------------------------------------------------*/
94 .macro SAVE_R13_TO_R24
95 	PUSH	r13
96 	PUSH	r14
97 	PUSH	r15
98 	PUSH	r16
99 	PUSH	r17
100 	PUSH	r18
101 	PUSH	r19
102 	PUSH	r20
103 	PUSH	r21
104 	PUSH	r22
105 	PUSH	r23
106 	PUSH	r24
107 .endm
108 
109 .macro RESTORE_R24_TO_R13
110 	POP	r24
111 	POP	r23
112 	POP	r22
113 	POP	r21
114 	POP	r20
115 	POP	r19
116 	POP	r18
117 	POP	r17
118 	POP	r16
119 	POP	r15
120 	POP	r14
121 	POP	r13
122 .endm
123 
124 #define OFF_USER_R25_FROM_R24	(SZ_CALLEE_REGS + SZ_PT_REGS - 8)/4
125 
126 /*--------------------------------------------------------------
127  * Collect User Mode callee regs as struct callee_regs - needed by
128  * fork/do_signal/unaligned-access-emulation.
129  * (By default only scratch regs are saved on entry to kernel)
130  *
131  * Special handling for r25 if used for caching Task Pointer.
132  * It would have been saved in task->thread.user_r25 already, but to keep
133  * the interface same it is copied into regular r25 placeholder in
134  * struct callee_regs.
135  *-------------------------------------------------------------*/
136 .macro SAVE_CALLEE_SAVED_USER
137 
138 	SAVE_R13_TO_R24
139 
140 #ifdef CONFIG_ARC_CURR_IN_REG
141 	; Retrieve orig r25 and save it on stack
142 	ld.as   r12, [sp, OFF_USER_R25_FROM_R24]
143 	st.a    r12, [sp, -4]
144 #else
145 	PUSH	r25
146 #endif
147 
148 .endm
149 
150 /*--------------------------------------------------------------
151  * Save kernel Mode callee regs at the time of Contect Switch.
152  *
153  * Special handling for r25 if used for caching Task Pointer.
154  * Kernel simply skips saving it since it will be loaded with
155  * incoming task pointer anyways
156  *-------------------------------------------------------------*/
157 .macro SAVE_CALLEE_SAVED_KERNEL
158 
159 	SAVE_R13_TO_R24
160 
161 #ifdef CONFIG_ARC_CURR_IN_REG
162 	sub     sp, sp, 4
163 #else
164 	PUSH	r25
165 #endif
166 .endm
167 
168 /*--------------------------------------------------------------
169  * Opposite of SAVE_CALLEE_SAVED_KERNEL
170  *-------------------------------------------------------------*/
171 .macro RESTORE_CALLEE_SAVED_KERNEL
172 
173 #ifdef CONFIG_ARC_CURR_IN_REG
174 	add     sp, sp, 4  /* skip usual r25 placeholder */
175 #else
176 	POP	r25
177 #endif
178 	RESTORE_R24_TO_R13
179 .endm
180 
181 /*--------------------------------------------------------------
182  * Opposite of SAVE_CALLEE_SAVED_USER
183  *
184  * ptrace tracer or unaligned-access fixup might have changed a user mode
185  * callee reg which is saved back to usual r25 storage location
186  *-------------------------------------------------------------*/
187 .macro RESTORE_CALLEE_SAVED_USER
188 
189 #ifdef CONFIG_ARC_CURR_IN_REG
190 	ld.ab   r12, [sp, 4]
191 	st.as   r12, [sp, OFF_USER_R25_FROM_R24]
192 #else
193 	POP	r25
194 #endif
195 	RESTORE_R24_TO_R13
196 .endm
197 
198 /*--------------------------------------------------------------
199  * Super FAST Restore callee saved regs by simply re-adjusting SP
200  *-------------------------------------------------------------*/
201 .macro DISCARD_CALLEE_SAVED_USER
202 	add     sp, sp, SZ_CALLEE_REGS
203 .endm
204 
205 /*-------------------------------------------------------------
206  * given a tsk struct, get to the base of it's kernel mode stack
207  * tsk->thread_info is really a PAGE, whose bottom hoists stack
208  * which grows upwards towards thread_info
209  *------------------------------------------------------------*/
210 
211 .macro GET_TSK_STACK_BASE tsk, out
212 
213 	/* Get task->thread_info (this is essentially start of a PAGE) */
214 	ld  \out, [\tsk, TASK_THREAD_INFO]
215 
216 	/* Go to end of page where stack begins (grows upwards) */
217 	add2 \out, \out, (THREAD_SIZE)/4
218 
219 .endm
220 
221 /*
222  * @reg [OUT] thread_info->flags of "current"
223  */
224 .macro GET_CURR_THR_INFO_FLAGS  reg
225 	GET_CURR_THR_INFO_FROM_SP  \reg
226 	ld  \reg, [\reg, THREAD_INFO_FLAGS]
227 .endm
228 
229 #ifdef CONFIG_SMP
230 
231 /*-------------------------------------------------
232  * Retrieve the current running task on this CPU
233  * 1. Determine curr CPU id.
234  * 2. Use it to index into _current_task[ ]
235  */
236 .macro  GET_CURR_TASK_ON_CPU   reg
237 	GET_CPU_ID  \reg
238 	ld.as  \reg, [@_current_task, \reg]
239 .endm
240 
241 /*-------------------------------------------------
242  * Save a new task as the "current" task on this CPU
243  * 1. Determine curr CPU id.
244  * 2. Use it to index into _current_task[ ]
245  *
246  * Coded differently than GET_CURR_TASK_ON_CPU (which uses LD.AS)
247  * because ST r0, [r1, offset] can ONLY have s9 @offset
248  * while   LD can take s9 (4 byte insn) or LIMM (8 byte insn)
249  */
250 
251 .macro  SET_CURR_TASK_ON_CPU    tsk, tmp
252 	GET_CPU_ID  \tmp
253 	add2 \tmp, @_current_task, \tmp
254 	st   \tsk, [\tmp]
255 #ifdef CONFIG_ARC_CURR_IN_REG
256 	mov r25, \tsk
257 #endif
258 
259 .endm
260 
261 
262 #else   /* Uniprocessor implementation of macros */
263 
264 .macro  GET_CURR_TASK_ON_CPU    reg
265 	ld  \reg, [@_current_task]
266 .endm
267 
268 .macro  SET_CURR_TASK_ON_CPU    tsk, tmp
269 	st  \tsk, [@_current_task]
270 #ifdef CONFIG_ARC_CURR_IN_REG
271 	mov r25, \tsk
272 #endif
273 .endm
274 
275 #endif /* SMP / UNI */
276 
277 /* ------------------------------------------------------------------
278  * Get the ptr to some field of Current Task at @off in task struct
279  *  -Uses r25 for Current task ptr if that is enabled
280  */
281 
282 #ifdef CONFIG_ARC_CURR_IN_REG
283 
284 .macro GET_CURR_TASK_FIELD_PTR  off,  reg
285 	add \reg, r25, \off
286 .endm
287 
288 #else
289 
290 .macro GET_CURR_TASK_FIELD_PTR  off,  reg
291 	GET_CURR_TASK_ON_CPU  \reg
292 	add \reg, \reg, \off
293 .endm
294 
295 #endif	/* CONFIG_ARC_CURR_IN_REG */
296 
297 #endif  /* __ASM_ARC_ENTRY_H */
298