aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arc')
-rw-r--r--arch/arc/include/asm/entry.h495
-rw-r--r--arch/arc/kernel/entry.S571
2 files changed, 1066 insertions, 0 deletions
diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h
new file mode 100644
index 000000000000..63705b12d911
--- /dev/null
+++ b/arch/arc/include/asm/entry.h
@@ -0,0 +1,495 @@
1/*
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 */
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
new file mode 100644
index 000000000000..a4acc9ee1311
--- /dev/null
+++ b/arch/arc/kernel/entry.S
@@ -0,0 +1,571 @@
1/*
2 * Low Level Interrupts/Traps/Exceptions(non-TLB) Handling for ARC
3 *
4 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * vineetg: Nov 2010:
11 * -Vector table jumps (@8 bytes) converted into branches (@4 bytes)
12 * -To maintain the slot size of 8 bytes/vector, added nop, which is
13 * not executed at runtime.
14 *
15 * vineetg: Nov 2009 (Everything needed for TIF_RESTORE_SIGMASK)
16 * -do_signal()invoked upon TIF_RESTORE_SIGMASK as well
17 * -Wrappers for sys_{,rt_}sigsuspend() nolonger needed as they don't
18 * need ptregs anymore
19 *
20 * Vineetg: Oct 2009
21 * -In a rare scenario, Process gets a Priv-V exception and gets scheduled
22 * out. Since we don't do FAKE RTIE for Priv-V, CPU excpetion state remains
23 * active (AE bit enabled). This causes a double fault for a subseq valid
24 * exception. Thus FAKE RTIE needed in low level Priv-Violation handler.
25 * Instr Error could also cause similar scenario, so same there as well.
26 *
27 * Vineetg: Aug 28th 2008: Bug #94984
28 * -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
29 * Normally CPU does this automatically, however when doing FAKE rtie,
30 * we need to explicitly do this. The problem in macros
31 * FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit
32 * was being "CLEARED" rather then "SET". Since it is Loop INHIBIT Bit,
33 * setting it and not clearing it clears ZOL context
34 *
35 * Vineetg: Dec 22, 2007
36 * Minor Surgery of Low Level ISR to make it SMP safe
37 * - MMU_SCRATCH0 Reg used for freeing up r9 in Level 1 ISR
38 * - _current_task is made an array of NR_CPUS
39 * - Access of _current_task wrapped inside a macro so that if hardware
40 * team agrees for a dedicated reg, no other code is touched
41 *
42 * Amit Bhor, Rahul Trivedi, Kanika Nema, Sameer Dhavale : Codito Tech 2004
43 */
44
45/*------------------------------------------------------------------
46 * Function ABI
47 *------------------------------------------------------------------
48 *
49 * Arguments r0 - r7
50 * Caller Saved Registers r0 - r12
51 * Callee Saved Registers r13- r25
52 * Global Pointer (gp) r26
53 * Frame Pointer (fp) r27
54 * Stack Pointer (sp) r28
55 * Interrupt link register (ilink1) r29
56 * Interrupt link register (ilink2) r30
57 * Branch link register (blink) r31
58 *------------------------------------------------------------------
59 */
60
61 .cpu A7
62
63;############################ Vector Table #################################
64
65.macro VECTOR lbl
66#if 1 /* Just in case, build breaks */
67 j \lbl
68#else
69 b \lbl
70 nop
71#endif
72.endm
73
74 .section .vector, "ax",@progbits
75 .align 4
76
77/* Each entry in the vector table must occupy 2 words. Since it is a jump
78 * across sections (.vector to .text) we are gauranteed that 'j somewhere'
79 * will use the 'j limm' form of the intrsuction as long as somewhere is in
80 * a section other than .vector.
81 */
82
83; ********* Critical System Events **********************
84VECTOR res_service ; 0x0, Restart Vector (0x0)
85VECTOR mem_service ; 0x8, Mem exception (0x1)
86VECTOR instr_service ; 0x10, Instrn Error (0x2)
87
88; ******************** Device ISRs **********************
89VECTOR handle_interrupt_level1
90
91VECTOR handle_interrupt_level1
92
93VECTOR handle_interrupt_level1
94
95VECTOR handle_interrupt_level1
96
97.rept 25
98VECTOR handle_interrupt_level1 ; Other devices
99.endr
100
101/* FOR ARC600: timer = 0x3, uart = 0x8, emac = 0x10 */
102
103; ******************** Exceptions **********************
104VECTOR EV_MachineCheck ; 0x100, Fatal Machine check (0x20)
105VECTOR EV_TLBMissI ; 0x108, Intruction TLB miss (0x21)
106VECTOR EV_TLBMissD ; 0x110, Data TLB miss (0x22)
107VECTOR EV_TLBProtV ; 0x118, Protection Violation (0x23)
108 ; or Misaligned Access
109VECTOR EV_PrivilegeV ; 0x120, Privilege Violation (0x24)
110VECTOR EV_Trap ; 0x128, Trap exception (0x25)
111VECTOR EV_Extension ; 0x130, Extn Intruction Excp (0x26)
112
113.rept 24
114VECTOR reserved ; Reserved Exceptions
115.endr
116
117#include <linux/linkage.h> /* ARC_{EXTRY,EXIT} */
118#include <asm/entry.h> /* SAVE_ALL_{INT1,INT2,TRAP...} */
119#include <asm/errno.h>
120#include <asm/arcregs.h>
121#include <asm/irqflags.h>
122
123;##################### Scratch Mem for IRQ stack switching #############
124
125 .section .data ; NOT .global
126 .align 32
127 .type int1_saved_reg, @object
128 .size int1_saved_reg, 4
129int1_saved_reg:
130 .zero 4
131
132; ---------------------------------------------
133 .section .text, "ax",@progbits
134
135res_service: ; processor restart
136 flag 0x1 ; not implemented
137 nop
138 nop
139
140reserved: ; processor restart
141 rtie ; jump to processor initializations
142
143;##################### Interrupt Handling ##############################
144
145; ---------------------------------------------
146; Level 1 ISR
147; ---------------------------------------------
148ARC_ENTRY handle_interrupt_level1
149
150 /* free up r9 as scratchpad */
151 st r9, [@int1_saved_reg]
152
153 ;Which mode (user/kernel) was the system in when intr occured
154 lr r9, [status32_l1]
155
156 SWITCH_TO_KERNEL_STK
157 SAVE_ALL_INT1
158
159 lr r0, [icause1]
160 and r0, r0, 0x1f
161
162 bl.d @arch_do_IRQ
163 mov r1, sp
164
165 mov r8,0x1
166 sr r8, [AUX_IRQ_LV12] ; clear bit in Sticky Status Reg
167
168 b ret_from_exception
169ARC_EXIT handle_interrupt_level1
170
171;################### Non TLB Exception Handling #############################
172
173; ---------------------------------------------
174; Instruction Error Exception Handler
175; ---------------------------------------------
176
177ARC_ENTRY instr_service
178
179 EXCPN_PROLOG_FREEUP_REG r9
180
181 lr r9, [erstatus]
182
183 SWITCH_TO_KERNEL_STK
184 SAVE_ALL_SYS
185
186 lr r0, [ecr]
187 lr r1, [efa]
188
189 mov r2, sp
190
191 FAKE_RET_FROM_EXCPN r9
192
193 bl do_insterror_or_kprobe
194 b ret_from_exception
195ARC_EXIT instr_service
196
197; ---------------------------------------------
198; Memory Error Exception Handler
199; ---------------------------------------------
200
201ARC_ENTRY mem_service
202
203 EXCPN_PROLOG_FREEUP_REG r9
204
205 lr r9, [erstatus]
206
207 SWITCH_TO_KERNEL_STK
208 SAVE_ALL_SYS
209
210 lr r0, [ecr]
211 lr r1, [efa]
212 mov r2, sp
213 bl do_memory_error
214 b ret_from_exception
215ARC_EXIT mem_service
216
217; ---------------------------------------------
218; Machine Check Exception Handler
219; ---------------------------------------------
220
221ARC_ENTRY EV_MachineCheck
222
223 EXCPN_PROLOG_FREEUP_REG r9
224 lr r9, [erstatus]
225
226 SWITCH_TO_KERNEL_STK
227 SAVE_ALL_SYS
228
229 lr r0, [ecr]
230 lr r1, [efa]
231 mov r2, sp
232
233 brne r0, 0x200100, 1f
234 bl do_tlb_overlap_fault
235 b ret_from_exception
236
2371:
238 ; DEAD END: can't do much, display Regs and HALT
239 SAVE_CALLEE_SAVED_USER
240
241 GET_CURR_TASK_FIELD_PTR TASK_THREAD, r10
242 st sp, [r10, THREAD_CALLEE_REG]
243
244 j do_machine_check_fault
245
246ARC_EXIT EV_MachineCheck
247
248; ---------------------------------------------
249; Protection Violation Exception Handler
250; ---------------------------------------------
251
252ARC_ENTRY EV_TLBProtV
253
254 EXCPN_PROLOG_FREEUP_REG r9
255
256 ;Which mode (user/kernel) was the system in when Exception occured
257 lr r9, [erstatus]
258
259 SWITCH_TO_KERNEL_STK
260 SAVE_ALL_SYS
261
262 ;---------(3) Save some more regs-----------------
263 ; vineetg: Mar 6th: Random Seg Fault issue #1
264 ; ecr and efa were not saved in case an Intr sneaks in
265 ; after fake rtie
266 ;
267 lr r3, [ecr]
268 lr r4, [efa]
269
270 ; --------(4) Return from CPU Exception Mode ---------
271 ; Fake a rtie, but rtie to next label
272 ; That way, subsequently, do_page_fault ( ) executes in pure kernel
273 ; mode with further Exceptions enabled
274
275 FAKE_RET_FROM_EXCPN r9
276
277 ;------ (5) Type of Protection Violation? ----------
278 ;
279 ; ProtV Hardware Exception is triggered for Access Faults of 2 types
280 ; -Access Violaton (WRITE to READ ONLY Page) - for linux COW
281 ; -Unaligned Access (READ/WRITE on odd boundary)
282 ;
283 cmp r3, 0x230400 ; Misaligned data access ?
284 beq 4f
285
286 ;========= (6a) Access Violation Processing ========
287 cmp r3, 0x230100
288 mov r1, 0x0 ; if LD exception ? write = 0
289 mov.ne r1, 0x1 ; else write = 1
290
291 mov r2, r4 ; faulting address
292 mov r0, sp ; pt_regs
293 bl do_page_fault
294 b ret_from_exception
295
296 ;========== (6b) Non aligned access ============
2974:
298 mov r0, r3 ; cause code
299 mov r1, r4 ; faulting address
300 mov r2, sp ; pt_regs
301
302 bl do_misaligned_access
303 b ret_from_exception
304
305ARC_EXIT EV_TLBProtV
306
307; ---------------------------------------------
308; Privilege Violation Exception Handler
309; ---------------------------------------------
310ARC_ENTRY EV_PrivilegeV
311
312 EXCPN_PROLOG_FREEUP_REG r9
313
314 lr r9, [erstatus]
315
316 SWITCH_TO_KERNEL_STK
317 SAVE_ALL_SYS
318
319 lr r0, [ecr]
320 lr r1, [efa]
321 mov r2, sp
322
323 FAKE_RET_FROM_EXCPN r9
324
325 bl do_privilege_fault
326 b ret_from_exception
327ARC_EXIT EV_PrivilegeV
328
329; ---------------------------------------------
330; Extension Instruction Exception Handler
331; ---------------------------------------------
332ARC_ENTRY EV_Extension
333
334 EXCPN_PROLOG_FREEUP_REG r9
335 lr r9, [erstatus]
336
337 SWITCH_TO_KERNEL_STK
338 SAVE_ALL_SYS
339
340 lr r0, [ecr]
341 lr r1, [efa]
342 mov r2, sp
343 bl do_extension_fault
344 b ret_from_exception
345ARC_EXIT EV_Extension
346
347;################### Break Point TRAP ##########################
348
349 ; ======= (5b) Trap is due to Break-Point =========
350
351trap_with_param:
352
353 ;make sure orig_r8 is a positive value
354 st NR_syscalls + 2, [sp, PT_orig_r8]
355
356 mov r0, r12
357 lr r1, [efa]
358 mov r2, sp
359
360 ; Now that we have read EFA, its safe to do "fake" rtie
361 ; and get out of CPU exception mode
362 FAKE_RET_FROM_EXCPN r11
363
364 ; Save callee regs in case gdb wants to have a look
365 ; SP will grow up by size of CALLEE Reg-File
366 ; NOTE: clobbers r12
367 SAVE_CALLEE_SAVED_USER
368
369 ; save location of saved Callee Regs @ thread_struct->pc
370 GET_CURR_TASK_FIELD_PTR TASK_THREAD, r10
371 st sp, [r10, THREAD_CALLEE_REG]
372
373 ; Call the trap handler
374 bl do_non_swi_trap
375
376 ; unwind stack to discard Callee saved Regs
377 DISCARD_CALLEE_SAVED_USER
378
379 b ret_from_exception
380
381;##################### Trap Handling ##############################
382;
383; EV_Trap caused by TRAP_S and TRAP0 instructions.
384;------------------------------------------------------------------
385; (1) System Calls
386; :parameters in r0-r7.
387; :r8 has the system call number
388; (2) Break Points
389;------------------------------------------------------------------
390
391ARC_ENTRY EV_Trap
392
393 ; Need at least 1 reg to code the early exception prolog
394 EXCPN_PROLOG_FREEUP_REG r9
395
396 ;Which mode (user/kernel) was the system in when intr occured
397 lr r9, [erstatus]
398
399 SWITCH_TO_KERNEL_STK
400 SAVE_ALL_TRAP
401
402 ;------- (4) What caused the Trap --------------
403 lr r12, [ecr]
404 and.f 0, r12, ECR_PARAM_MASK
405 bnz trap_with_param
406
407 ; ======= (5a) Trap is due to System Call ========
408
409 ; Before doing anything, return from CPU Exception Mode
410 FAKE_RET_FROM_EXCPN r11
411
412 ;============ This is normal System Call case ==========
413 ; Sys-call num shd not exceed the total system calls avail
414 cmp r8, NR_syscalls
415 mov.hi r0, -ENOSYS
416 bhi ret_from_system_call
417
418 ; Offset into the syscall_table and call handler
419 ld.as r9,[sys_call_table, r8]
420 jl [r9] ; Entry into Sys Call Handler
421
422 ; fall through to ret_from_system_call
423ARC_EXIT EV_Trap
424
425ARC_ENTRY ret_from_system_call
426
427 st r0, [sp, PT_r0] ; sys call return value in pt_regs
428
429 ; fall through yet again to ret_from_exception
430
431;############# Return from Intr/Excp/Trap (Linux Specifics) ##############
432;
433; If ret to user mode do we need to handle signals, schedule() et al.
434
435ARC_ENTRY ret_from_exception
436
437 ; Pre-{IRQ,Trap,Exception} K/U mode from pt_regs->status32
438 ld r8, [sp, PT_status32] ; returning to User/Kernel Mode
439
440#ifdef CONFIG_PREEMPT
441 bbit0 r8, STATUS_U_BIT, resume_kernel_mode
442#else
443 bbit0 r8, STATUS_U_BIT, restore_regs
444#endif
445
446 ; Before returning to User mode check-for-and-complete any pending work
447 ; such as rescheduling/signal-delivery etc.
448resume_user_mode_begin:
449
450 ; Disable IRQs to ensures that chk for pending work itself is atomic
451 ; (and we don't end up missing a NEED_RESCHED/SIGPENDING due to an
452 ; interim IRQ).
453 IRQ_DISABLE r10
454
455 ; Fast Path return to user mode if no pending work
456 GET_CURR_THR_INFO_FLAGS r9
457 and.f 0, r9, _TIF_WORK_MASK
458 bz restore_regs
459
460 ; --- (Slow Path #1) task preemption ---
461 bbit0 r9, TIF_NEED_RESCHED, .Lchk_pend_signals
462 mov blink, resume_user_mode_begin ; tail-call to U mode ret chks
463 b @schedule ; BTST+Bnz causes relo error in link
464
465.Lchk_pend_signals:
466 IRQ_ENABLE r10
467
468 ; --- (Slow Path #2) pending signal ---
469 mov r0, sp ; pt_regs for arg to do_signal()/do_notify_resume()
470
471 bbit0 r9, TIF_SIGPENDING, .Lchk_notify_resume
472
473 ; save CALLEE Regs.
474 ; (i) If this signal causes coredump - full regfile needed
475 ; (ii) If signal is SIGTRAP/SIGSTOP, task is being traced thus
476 ; tracer might call PEEKUSR(CALLEE reg)
477 ;
478 ; NOTE: SP will grow up by size of CALLEE Reg-File
479 SAVE_CALLEE_SAVED_USER ; clobbers r12
480
481 ; save location of saved Callee Regs @ thread_struct->callee
482 GET_CURR_TASK_FIELD_PTR TASK_THREAD, r10
483 st sp, [r10, THREAD_CALLEE_REG]
484
485 bl @do_signal
486
487 ; unwind SP for cheap discard of Callee saved Regs
488 DISCARD_CALLEE_SAVED_USER
489
490 b resume_user_mode_begin ; loop back to start of U mode ret
491
492 ; --- (Slow Path #3) notify_resume ---
493.Lchk_notify_resume:
494 btst r9, TIF_NOTIFY_RESUME
495 blnz @do_notify_resume
496 b resume_user_mode_begin ; unconditionally back to U mode ret chks
497 ; for single exit point from this block
498
499#ifdef CONFIG_PREEMPT
500
501resume_kernel_mode:
502
503 ; Can't preempt if preemption disabled
504 GET_CURR_THR_INFO_FROM_SP r10
505 ld r8, [r10, THREAD_INFO_PREEMPT_COUNT]
506 brne r8, 0, restore_regs
507
508 ; check if this task's NEED_RESCHED flag set
509 ld r9, [r10, THREAD_INFO_FLAGS]
510 bbit0 r9, TIF_NEED_RESCHED, restore_regs
511
512 IRQ_DISABLE r9
513
514 ; Invoke PREEMPTION
515 bl preempt_schedule_irq
516
517 ; preempt_schedule_irq() always returns with IRQ disabled
518#endif
519
520 ; fall through
521
522;############# Return from Intr/Excp/Trap (ARC Specifics) ##############
523;
524; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap)
525; IRQ shd definitely not happen between now and rtie
526
527restore_regs :
528
529 ; Disable Interrupts while restoring reg-file back
530 ; XXX can this be optimised out
531 IRQ_DISABLE_SAVE r9, r10 ;@r10 has prisitine (pre-disable) copy
532
533 ; Restore REG File. In case multiple Events outstanding,
534 ; use the same priorty as rtie: EXCPN, L2 IRQ, L1 IRQ, None
535 ; Note that we use realtime STATUS32 (not pt_regs->status32) to
536 ; decide that.
537
538 ; if Returning from Exception
539 bbit0 r10, STATUS_AE_BIT, not_exception
540 RESTORE_ALL_SYS
541 rtie
542
543 ; Not Exception so maybe Interrupts (Level 1 or 2)
544
545not_exception:
546
547 bbit0 r10, STATUS_A1_BIT, not_level1_interrupt
548
549 ;return from level 1
550
551 RESTORE_ALL_INT1
552debug_marker_l1:
553 rtie
554
555not_level1_interrupt:
556
557 ;this case is for syscalls or Exceptions (with fake rtie)
558
559 RESTORE_ALL_SYS
560debug_marker_syscall:
561 rtie
562
563ARC_EXIT ret_from_exception
564
565ARC_ENTRY ret_from_fork
566 ; when the forked child comes here from the __switch_to function
567 ; r0 has the last task pointer.
568 ; put last task in scheduler queue
569 bl @schedule_tail
570 b @ret_from_exception
571ARC_EXIT ret_from_fork