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