blob: 9eada5b28be6cc1ab221311e0349a095ff5b436f [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/*--------------------------------------------------------------
Vineet Guptac3581032013-01-18 15:12:19 +0530169 * RESTORE_CALLEE_SAVED_USER:
170 * This is called after do_signal where tracer might have changed callee regs
171 * thus we need to restore the reg file.
172 * Special case handling is required for r25 in case it is used by kernel
173 * for caching task ptr. Ptrace would have modified on-kernel-stack value of
174 * r25, which needs to be shoved back into task->thread.user_r25 where from
175 * Low level exception/ISR return code will retrieve to populate with rest of
176 * callee reg-file.
177 *-------------------------------------------------------------*/
178.macro RESTORE_CALLEE_SAVED_USER
179
180 add sp, sp, 4 /* skip "callee_regs->stack_place_holder" */
181
182#ifdef CONFIG_ARC_CURR_IN_REG
183 ld.ab r12, [sp, 4]
184 st r12, [r25, TASK_THREAD + THREAD_USER_R25]
185#else
186 ld.ab r25, [sp, 4]
187#endif
188
189 ld.ab r24, [sp, 4]
190 ld.ab r23, [sp, 4]
191 ld.ab r22, [sp, 4]
192 ld.ab r21, [sp, 4]
193 ld.ab r20, [sp, 4]
194 ld.ab r19, [sp, 4]
195 ld.ab r18, [sp, 4]
196 ld.ab r17, [sp, 4]
197 ld.ab r16, [sp, 4]
198 ld.ab r15, [sp, 4]
199 ld.ab r14, [sp, 4]
200 ld.ab r13, [sp, 4]
201.endm
202
203/*--------------------------------------------------------------
Vineet Gupta9d42c842013-01-18 15:12:18 +0530204 * Super FAST Restore callee saved regs by simply re-adjusting SP
205 *-------------------------------------------------------------*/
206.macro DISCARD_CALLEE_SAVED_USER
207 add sp, sp, 14 * 4
208.endm
209
210/*--------------------------------------------------------------
211 * Restore User mode r25 saved in task_struct->thread.user_r25
212 *-------------------------------------------------------------*/
213.macro RESTORE_USER_R25
214 ld r25, [r25, TASK_THREAD + THREAD_USER_R25]
215.endm
216
217/*-------------------------------------------------------------
218 * given a tsk struct, get to the base of it's kernel mode stack
219 * tsk->thread_info is really a PAGE, whose bottom hoists stack
220 * which grows upwards towards thread_info
221 *------------------------------------------------------------*/
222
223.macro GET_TSK_STACK_BASE tsk, out
224
225 /* Get task->thread_info (this is essentially start of a PAGE) */
226 ld \out, [\tsk, TASK_THREAD_INFO]
227
228 /* Go to end of page where stack begins (grows upwards) */
229 add2 \out, \out, (THREAD_SIZE - 4)/4 /* one word GUTTER */
230
231.endm
232
233/*--------------------------------------------------------------
234 * Switch to Kernel Mode stack if SP points to User Mode stack
235 *
236 * Entry : r9 contains pre-IRQ/exception/trap status32
237 * Exit : SP is set to kernel mode stack pointer
238 * Clobbers: r9
239 *-------------------------------------------------------------*/
240
241.macro SWITCH_TO_KERNEL_STK
242
243 /* User Mode when this happened ? Yes: Proceed to switch stack */
244 bbit1 r9, STATUS_U_BIT, 88f
245
246 /* OK we were already in kernel mode when this event happened, thus can
247 * assume SP is kernel mode SP. _NO_ need to do any stack switching
248 */
249
250 /* Save Pre Intr/Exception KERNEL MODE SP on kernel stack
251 * safe-keeping not really needed, but it keeps the epilogue code
252 * (SP restore) simpler/uniform.
253 */
254 b.d 77f
255
256 st.a sp, [sp, -12] ; Make room for orig_r0 and orig_r8
257
25888: /*------Intr/Ecxp happened in user mode, "switch" stack ------ */
259
260 GET_CURR_TASK_ON_CPU r9
261
262 /* With current tsk in r9, get it's kernel mode stack base */
263 GET_TSK_STACK_BASE r9, r9
264
265#ifdef PT_REGS_CANARY
266 st 0xabcdabcd, [r9, 0]
267#endif
268
269 /* Save Pre Intr/Exception User SP on kernel stack */
270 st.a sp, [r9, -12] ; Make room for orig_r0 and orig_r8
271
272 /* CAUTION:
273 * SP should be set at the very end when we are done with everything
274 * In case of 2 levels of interrupt we depend on value of SP to assume
275 * that everything else is done (loading r25 etc)
276 */
277
278 /* set SP to point to kernel mode stack */
279 mov sp, r9
280
28177: /* ----- Stack Switched to kernel Mode, Now save REG FILE ----- */
282
283.endm
284
285/*------------------------------------------------------------
286 * "FAKE" a rtie to return from CPU Exception context
287 * This is to re-enable Exceptions within exception
288 * Look at EV_ProtV to see how this is actually used
289 *-------------------------------------------------------------*/
290
291.macro FAKE_RET_FROM_EXCPN reg
292
293 ld \reg, [sp, PT_status32]
294 bic \reg, \reg, (STATUS_U_MASK|STATUS_DE_MASK)
295 bset \reg, \reg, STATUS_L_BIT
296 sr \reg, [erstatus]
297 mov \reg, 55f
298 sr \reg, [eret]
299
300 rtie
30155:
302.endm
303
304/*
305 * @reg [OUT] &thread_info of "current"
306 */
307.macro GET_CURR_THR_INFO_FROM_SP reg
308 and \reg, sp, ~(THREAD_SIZE - 1)
309.endm
310
311/*
312 * @reg [OUT] thread_info->flags of "current"
313 */
314.macro GET_CURR_THR_INFO_FLAGS reg
315 GET_CURR_THR_INFO_FROM_SP \reg
316 ld \reg, [\reg, THREAD_INFO_FLAGS]
317.endm
318
319/*--------------------------------------------------------------
320 * For early Exception Prologue, a core reg is temporarily needed to
321 * code the rest of prolog (stack switching). This is done by stashing
322 * it to memory (non-SMP case) or SCRATCH0 Aux Reg (SMP).
323 *
324 * Before saving the full regfile - this reg is restored back, only
325 * to be saved again on kernel mode stack, as part of ptregs.
326 *-------------------------------------------------------------*/
327.macro EXCPN_PROLOG_FREEUP_REG reg
328 st \reg, [@ex_saved_reg1]
329.endm
330
331.macro EXCPN_PROLOG_RESTORE_REG reg
332 ld \reg, [@ex_saved_reg1]
333.endm
334
335/*--------------------------------------------------------------
336 * Save all registers used by Exceptions (TLB Miss, Prot-V, Mem err etc)
337 * Requires SP to be already switched to kernel mode Stack
338 * sp points to the next free element on the stack at exit of this macro.
339 * Registers are pushed / popped in the order defined in struct ptregs
340 * in asm/ptrace.h
341 * Note that syscalls are implemented via TRAP which is also a exception
342 * from CPU's point of view
343 *-------------------------------------------------------------*/
344.macro SAVE_ALL_EXCEPTION marker
345
Vineet Gupta5c39c0a2013-02-11 20:01:24 +0530346 st \marker, [sp, 8]
347 st r0, [sp, 4] /* orig_r0, needed only for sys calls */
348
Vineet Gupta9d42c842013-01-18 15:12:18 +0530349 /* Restore r9 used to code the early prologue */
350 EXCPN_PROLOG_RESTORE_REG r9
351
Vineet Gupta9d42c842013-01-18 15:12:18 +0530352 SAVE_CALLER_SAVED
353 st.a r26, [sp, -4] /* gp */
354 st.a fp, [sp, -4]
355 st.a blink, [sp, -4]
356 lr r9, [eret]
357 st.a r9, [sp, -4]
358 lr r9, [erstatus]
359 st.a r9, [sp, -4]
360 st.a lp_count, [sp, -4]
361 lr r9, [lp_end]
362 st.a r9, [sp, -4]
363 lr r9, [lp_start]
364 st.a r9, [sp, -4]
365 lr r9, [erbta]
366 st.a r9, [sp, -4]
367
368#ifdef PT_REGS_CANARY
369 mov r9, 0xdeadbeef
370 st r9, [sp, -4]
371#endif
372
373 /* move up by 1 word to "create" pt_regs->"stack_place_holder" */
374 sub sp, sp, 4
375.endm
376
377/*--------------------------------------------------------------
378 * Save scratch regs for exceptions
379 *-------------------------------------------------------------*/
380.macro SAVE_ALL_SYS
Vineet Gupta5c39c0a2013-02-11 20:01:24 +0530381 SAVE_ALL_EXCEPTION orig_r8_IS_EXCPN
Vineet Gupta9d42c842013-01-18 15:12:18 +0530382.endm
383
384/*--------------------------------------------------------------
385 * Save scratch regs for sys calls
386 *-------------------------------------------------------------*/
387.macro SAVE_ALL_TRAP
Vineet Gupta5c39c0a2013-02-11 20:01:24 +0530388 /*
389 * Setup pt_regs->orig_r8.
390 * Encode syscall number (r8) in upper short word of event type (r9)
391 * N.B. #1: This is already endian safe (see ptrace.h)
392 * #2: Only r9 can be used as scratch as it is already clobbered
393 * and it's contents are no longer needed by the latter part
394 * of exception prologue
395 */
396 lsl r9, r8, 16
397 or r9, r9, orig_r8_IS_SCALL
398
399 SAVE_ALL_EXCEPTION r9
Vineet Gupta9d42c842013-01-18 15:12:18 +0530400.endm
401
402/*--------------------------------------------------------------
403 * Restore all registers used by system call or Exceptions
404 * SP should always be pointing to the next free stack element
405 * when entering this macro.
406 *
407 * NOTE:
408 *
409 * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
410 * for memory load operations. If used in that way interrupts are deffered
411 * by hardware and that is not good.
412 *-------------------------------------------------------------*/
413.macro RESTORE_ALL_SYS
414
415 add sp, sp, 4 /* hop over unused "pt_regs->stack_place_holder" */
416
417 ld.ab r9, [sp, 4]
418 sr r9, [erbta]
419 ld.ab r9, [sp, 4]
420 sr r9, [lp_start]
421 ld.ab r9, [sp, 4]
422 sr r9, [lp_end]
423 ld.ab r9, [sp, 4]
424 mov lp_count, r9
425 ld.ab r9, [sp, 4]
426 sr r9, [erstatus]
427 ld.ab r9, [sp, 4]
428 sr r9, [eret]
429 ld.ab blink, [sp, 4]
430 ld.ab fp, [sp, 4]
431 ld.ab r26, [sp, 4] /* gp */
432 RESTORE_CALLER_SAVED
433
434 ld sp, [sp] /* restore original sp */
435 /* orig_r0 and orig_r8 skipped automatically */
436.endm
437
438
439/*--------------------------------------------------------------
440 * Save all registers used by interrupt handlers.
441 *-------------------------------------------------------------*/
442.macro SAVE_ALL_INT1
443
444 /* restore original r9 , saved in int1_saved_reg
445 * It will be saved on stack in macro: SAVE_CALLER_SAVED
446 */
447 ld r9, [@int1_saved_reg]
448
449 /* now we are ready to save the remaining context :) */
Vineet Gupta5c39c0a2013-02-11 20:01:24 +0530450 st orig_r8_IS_IRQ1, [sp, 8] /* Event Type */
Vineet Gupta9d42c842013-01-18 15:12:18 +0530451 st 0, [sp, 4] /* orig_r0 , N/A for IRQ */
452 SAVE_CALLER_SAVED
453 st.a r26, [sp, -4] /* gp */
454 st.a fp, [sp, -4]
455 st.a blink, [sp, -4]
456 st.a ilink1, [sp, -4]
457 lr r9, [status32_l1]
458 st.a r9, [sp, -4]
459 st.a lp_count, [sp, -4]
460 lr r9, [lp_end]
461 st.a r9, [sp, -4]
462 lr r9, [lp_start]
463 st.a r9, [sp, -4]
464 lr r9, [bta_l1]
465 st.a r9, [sp, -4]
466
467#ifdef PT_REGS_CANARY
468 mov r9, 0xdeadbee1
469 st r9, [sp, -4]
470#endif
471 /* move up by 1 word to "create" pt_regs->"stack_place_holder" */
472 sub sp, sp, 4
473.endm
474
475/*--------------------------------------------------------------
476 * Restore all registers used by interrupt handlers.
477 *
478 * NOTE:
479 *
480 * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
481 * for memory load operations. If used in that way interrupts are deffered
482 * by hardware and that is not good.
483 *-------------------------------------------------------------*/
484
485.macro RESTORE_ALL_INT1
486 add sp, sp, 4 /* hop over unused "pt_regs->stack_place_holder" */
487
488 ld.ab r9, [sp, 4] /* Actual reg file */
489 sr r9, [bta_l1]
490 ld.ab r9, [sp, 4]
491 sr r9, [lp_start]
492 ld.ab r9, [sp, 4]
493 sr r9, [lp_end]
494 ld.ab r9, [sp, 4]
495 mov lp_count, r9
496 ld.ab r9, [sp, 4]
497 sr r9, [status32_l1]
498 ld.ab r9, [sp, 4]
499 mov ilink1, r9
500 ld.ab blink, [sp, 4]
501 ld.ab fp, [sp, 4]
502 ld.ab r26, [sp, 4] /* gp */
503 RESTORE_CALLER_SAVED
504
505 ld sp, [sp] /* restore original sp */
506 /* orig_r0 and orig_r8 skipped automatically */
507.endm
508
509/* Get CPU-ID of this core */
510.macro GET_CPU_ID reg
511 lr \reg, [identity]
512 lsr \reg, \reg, 8
513 bmsk \reg, \reg, 7
514.endm
515
516.macro GET_CURR_TASK_ON_CPU reg
517 ld \reg, [@_current_task]
518.endm
519
520.macro SET_CURR_TASK_ON_CPU tsk, tmp
521 st \tsk, [@_current_task]
522.endm
523
524/* ------------------------------------------------------------------
525 * Get the ptr to some field of Current Task at @off in task struct
526 */
527
528.macro GET_CURR_TASK_FIELD_PTR off, reg
529 GET_CURR_TASK_ON_CPU \reg
530 add \reg, \reg, \off
531.endm
532
533#endif /* __ASSEMBLY__ */
534
535#endif /* __ASM_ARC_ENTRY_H */