xref: /linux/arch/arc/kernel/entry.S (revision abe11ddea1d759f9995a9a4636c28c9b40856ca8)
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	; stop_pc info by gdb needs this info
354	st  orig_r8_IS_BRKPT, [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	; Normal Trap/IRQ entry only saves Scratch (caller-saved) regs
474	; in pt_reg since the "C" ABI (kernel code) will automatically
475	; save/restore callee-saved regs.
476	;
477	; However, here we need to explicitly save callee regs because
478	; (i)  If this signal causes coredump - full regfile needed
479	; (ii) If signal is SIGTRAP/SIGSTOP, task is being traced thus
480	;      tracer might call PEEKUSR(CALLEE reg)
481	;
482	; NOTE: SP will grow up by size of CALLEE Reg-File
483	SAVE_CALLEE_SAVED_USER		; clobbers r12
484
485	; save location of saved Callee Regs @ thread_struct->callee
486	GET_CURR_TASK_FIELD_PTR   TASK_THREAD, r10
487	st  sp, [r10, THREAD_CALLEE_REG]
488
489	bl  @do_signal
490
491	; Ideally we want to discard the Callee reg above, however if this was
492	; a tracing signal, tracer could have done a POKEUSR(CALLEE reg)
493	RESTORE_CALLEE_SAVED_USER
494
495	b      resume_user_mode_begin	; loop back to start of U mode ret
496
497	; --- (Slow Path #3) notify_resume ---
498.Lchk_notify_resume:
499	btst   r9, TIF_NOTIFY_RESUME
500	blnz   @do_notify_resume
501	b      resume_user_mode_begin	; unconditionally back to U mode ret chks
502					; for single exit point from this block
503
504#ifdef CONFIG_PREEMPT
505
506resume_kernel_mode:
507
508	; Can't preempt if preemption disabled
509	GET_CURR_THR_INFO_FROM_SP   r10
510	ld  r8, [r10, THREAD_INFO_PREEMPT_COUNT]
511	brne  r8, 0, restore_regs
512
513	; check if this task's NEED_RESCHED flag set
514	ld  r9, [r10, THREAD_INFO_FLAGS]
515	bbit0  r9, TIF_NEED_RESCHED, restore_regs
516
517	IRQ_DISABLE	r9
518
519	; Invoke PREEMPTION
520	bl      preempt_schedule_irq
521
522	; preempt_schedule_irq() always returns with IRQ disabled
523#endif
524
525	; fall through
526
527;############# Return from Intr/Excp/Trap (ARC Specifics) ##############
528;
529; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap)
530; IRQ shd definitely not happen between now and rtie
531
532restore_regs :
533
534	; Disable Interrupts while restoring reg-file back
535	; XXX can this be optimised out
536	IRQ_DISABLE_SAVE    r9, r10	;@r10 has prisitine (pre-disable) copy
537
538	; Restore REG File. In case multiple Events outstanding,
539	; use the same priorty as rtie: EXCPN, L2 IRQ, L1 IRQ, None
540	; Note that we use realtime STATUS32 (not pt_regs->status32) to
541	; decide that.
542
543	; if Returning from Exception
544	bbit0  r10, STATUS_AE_BIT, not_exception
545	RESTORE_ALL_SYS
546	rtie
547
548	; Not Exception so maybe Interrupts (Level 1 or 2)
549
550not_exception:
551
552	bbit0  r10, STATUS_A1_BIT, not_level1_interrupt
553
554	;return from level 1
555
556	RESTORE_ALL_INT1
557debug_marker_l1:
558	rtie
559
560not_level1_interrupt:
561
562	;this case is for syscalls or Exceptions (with fake rtie)
563
564	RESTORE_ALL_SYS
565debug_marker_syscall:
566	rtie
567
568ARC_EXIT ret_from_exception
569
570ARC_ENTRY ret_from_fork
571	; when the forked child comes here from the __switch_to function
572	; r0 has the last task pointer.
573	; put last task in scheduler queue
574	bl   @schedule_tail
575
576	; If kernel thread, jump to it's entry-point
577	ld   r9, [sp, PT_status32]
578	brne r9, 0, 1f
579
580	jl.d [r14]
581	mov  r0, r13		; arg to payload
582
5831:
584	; special case of kernel_thread entry point returning back due to
585	; kernel_execve() - pretend return from syscall to ret to userland
586	b    ret_from_exception
587ARC_EXIT ret_from_fork
588
589;################### Special Sys Call Wrappers ##########################
590
591; TBD: call do_fork directly from here
592ARC_ENTRY sys_fork_wrapper
593	SAVE_CALLEE_SAVED_USER
594	bl  @sys_fork
595	DISCARD_CALLEE_SAVED_USER
596
597	b ret_from_system_call
598ARC_EXIT sys_fork_wrapper
599
600ARC_ENTRY sys_vfork_wrapper
601	SAVE_CALLEE_SAVED_USER
602	bl  @sys_vfork
603	DISCARD_CALLEE_SAVED_USER
604
605	b ret_from_system_call
606ARC_EXIT sys_vfork_wrapper
607
608ARC_ENTRY sys_clone_wrapper
609	SAVE_CALLEE_SAVED_USER
610	bl  @sys_clone
611	DISCARD_CALLEE_SAVED_USER
612
613	b ret_from_system_call
614ARC_EXIT sys_clone_wrapper
615