diff options
Diffstat (limited to 'arch/arc/kernel/entry.S')
| -rw-r--r-- | arch/arc/kernel/entry.S | 96 | 
1 files changed, 52 insertions, 44 deletions
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index b908dde8a33..83a046a7cd0 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -141,7 +141,7 @@ VECTOR   EV_Extension            ; 0x130, Extn Intruction Excp  (0x26)  VECTOR   reserved                ; Reserved Exceptions  .endr -#include <linux/linkage.h>   /* ARC_{EXTRY,EXIT} */ +#include <linux/linkage.h>   /* {EXTRY,EXIT} */  #include <asm/entry.h>       /* SAVE_ALL_{INT1,INT2,SYS...} */  #include <asm/errno.h>  #include <asm/arcregs.h> @@ -156,7 +156,7 @@ ARCFP_DATA int1_saved_reg  int1_saved_reg:  	.zero 4 -/* Each Interrupt level needs it's own scratch */ +/* Each Interrupt level needs its own scratch */  #ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS  ARCFP_DATA int2_saved_reg @@ -184,7 +184,7 @@ reserved:		; processor restart  ; ---------------------------------------------  ;  Level 2 ISR: Can interrupt a Level 1 ISR  ; --------------------------------------------- -ARC_ENTRY handle_interrupt_level2 +ENTRY(handle_interrupt_level2)  	; TODO-vineetg for SMP this wont work  	; free up r9 as scratchpad @@ -225,14 +225,14 @@ ARC_ENTRY handle_interrupt_level2  	b   ret_from_exception -ARC_EXIT handle_interrupt_level2 +END(handle_interrupt_level2)  #endif  ; ---------------------------------------------  ;  Level 1 ISR  ; --------------------------------------------- -ARC_ENTRY handle_interrupt_level1 +ENTRY(handle_interrupt_level1)  	/* free up r9 as scratchpad */  #ifdef CONFIG_SMP @@ -250,6 +250,14 @@ ARC_ENTRY handle_interrupt_level1  	lr  r0, [icause1]  	and r0, r0, 0x1f +#ifdef CONFIG_TRACE_IRQFLAGS +	; icause1 needs to be read early, before calling tracing, which +	; can clobber scratch regs, hence use of stack to stash it +	push r0 +	TRACE_ASM_IRQ_DISABLE +	pop  r0 +#endif +  	bl.d  @arch_do_IRQ  	mov r1, sp @@ -257,7 +265,7 @@ ARC_ENTRY handle_interrupt_level1  	sr r8, [AUX_IRQ_LV12]       ; clear bit in Sticky Status Reg  	b   ret_from_exception -ARC_EXIT handle_interrupt_level1 +END(handle_interrupt_level1)  ;################### Non TLB Exception Handling ############################# @@ -265,7 +273,7 @@ ARC_EXIT handle_interrupt_level1  ; Instruction Error Exception Handler  ; --------------------------------------------- -ARC_ENTRY instr_service +ENTRY(instr_service)  	EXCEPTION_PROLOGUE @@ -276,13 +284,13 @@ ARC_ENTRY instr_service  	bl  do_insterror_or_kprobe  	b   ret_from_exception -ARC_EXIT instr_service +END(instr_service)  ; ---------------------------------------------  ; Memory Error Exception Handler  ; --------------------------------------------- -ARC_ENTRY mem_service +ENTRY(mem_service)  	EXCEPTION_PROLOGUE @@ -293,13 +301,13 @@ ARC_ENTRY mem_service  	bl  do_memory_error  	b   ret_from_exception -ARC_EXIT mem_service +END(mem_service)  ; ---------------------------------------------  ; Machine Check Exception Handler  ; --------------------------------------------- -ARC_ENTRY EV_MachineCheck +ENTRY(EV_MachineCheck)  	EXCEPTION_PROLOGUE @@ -323,13 +331,13 @@ ARC_ENTRY EV_MachineCheck  	j  do_machine_check_fault -ARC_EXIT EV_MachineCheck +END(EV_MachineCheck)  ; ---------------------------------------------  ; Protection Violation Exception Handler  ; --------------------------------------------- -ARC_ENTRY EV_TLBProtV +ENTRY(EV_TLBProtV)  	EXCEPTION_PROLOGUE @@ -337,9 +345,9 @@ ARC_ENTRY EV_TLBProtV  	;  vineetg: Mar 6th: Random Seg Fault issue #1  	;  ecr and efa were not saved in case an Intr sneaks in  	;  after fake rtie -	; +  	lr  r2, [ecr] -	lr  r1, [efa]	; Faulting Data address +	lr  r0, [efa]	; Faulting Data address  	; --------(4) Return from CPU Exception Mode ---------  	;  Fake a rtie, but rtie to next label @@ -348,6 +356,8 @@ ARC_ENTRY EV_TLBProtV  	FAKE_RET_FROM_EXCPN r9 +	mov   r1, sp +  	;------ (5) Type of Protection Violation? ----------  	;  	; ProtV Hardware Exception is triggered for Access Faults of 2 types @@ -358,16 +368,12 @@ ARC_ENTRY EV_TLBProtV  	bbit1 r2, ECR_C_BIT_PROTV_MISALIG_DATA, 4f  	;========= (6a) Access Violation Processing ======== -	mov r0, sp              ; pt_regs  	bl  do_page_fault  	b   ret_from_exception  	;========== (6b) Non aligned access ============  4: -	mov r0, r1 -	mov r1, sp              ; pt_regs -#ifdef  CONFIG_ARC_MISALIGN_ACCESS  	SAVE_CALLEE_SAVED_USER  	mov r2, sp              ; callee_regs @@ -376,18 +382,15 @@ ARC_ENTRY EV_TLBProtV  	; TBD: optimize - do this only if a callee reg was involved  	; either a dst of emulated LD/ST or src with address-writeback  	RESTORE_CALLEE_SAVED_USER -#else -	bl  do_misaligned_error -#endif  	b   ret_from_exception -ARC_EXIT EV_TLBProtV +END(EV_TLBProtV)  ; ---------------------------------------------  ; Privilege Violation Exception Handler  ; --------------------------------------------- -ARC_ENTRY EV_PrivilegeV +ENTRY(EV_PrivilegeV)  	EXCEPTION_PROLOGUE @@ -398,12 +401,12 @@ ARC_ENTRY EV_PrivilegeV  	bl  do_privilege_fault  	b   ret_from_exception -ARC_EXIT EV_PrivilegeV +END(EV_PrivilegeV)  ; ---------------------------------------------  ; Extension Instruction Exception Handler  ; --------------------------------------------- -ARC_ENTRY EV_Extension +ENTRY(EV_Extension)  	EXCEPTION_PROLOGUE @@ -414,7 +417,7 @@ ARC_ENTRY EV_Extension  	bl  do_extension_fault  	b   ret_from_exception -ARC_EXIT EV_Extension +END(EV_Extension)  ;######################### System Call Tracing ######################### @@ -470,7 +473,7 @@ trap_with_param:  	lr  r0, [efa]  	mov r1, sp -	; Now that we have read EFA, its safe to do "fake" rtie +	; Now that we have read EFA, it is safe to do "fake" rtie  	;   and get out of CPU exception mode  	FAKE_RET_FROM_EXCPN r11 @@ -501,7 +504,7 @@ trap_with_param:  ;   (2) Break Points  ;------------------------------------------------------------------ -ARC_ENTRY EV_Trap +ENTRY(EV_Trap)  	EXCEPTION_PROLOGUE @@ -531,9 +534,9 @@ ARC_ENTRY EV_Trap  	jl      [r9]        ; Entry into Sys Call Handler  	; fall through to ret_from_system_call -ARC_EXIT EV_Trap +END(EV_Trap) -ARC_ENTRY ret_from_system_call +ENTRY(ret_from_system_call)  	st  r0, [sp, PT_r0]     ; sys call return value in pt_regs @@ -543,7 +546,7 @@ ARC_ENTRY ret_from_system_call  ;  ; If ret to user mode do we need to handle signals, schedule() et al. -ARC_ENTRY ret_from_exception +ENTRY(ret_from_exception)  	; Pre-{IRQ,Trap,Exception} K/U mode from pt_regs->status32  	ld  r8, [sp, PT_status32]   ; returning to User/Kernel Mode @@ -575,6 +578,7 @@ resume_user_mode_begin:  	; --- (Slow Path #2) pending signal  ---  	mov r0, sp	; pt_regs for arg to do_signal()/do_notify_resume() +	GET_CURR_THR_INFO_FLAGS   r9  	bbit0  r9, TIF_SIGPENDING, .Lchk_notify_resume  	; Normal Trap/IRQ entry only saves Scratch (caller-saved) regs @@ -610,11 +614,13 @@ resume_user_mode_begin:  resume_kernel_mode: -#ifdef CONFIG_PREEMPT - -	; This is a must for preempt_schedule_irq() +	; Disable Interrupts from this point on +	; CONFIG_PREEMPT: This is a must for preempt_schedule_irq() +	; !CONFIG_PREEMPT: To ensure restore_regs is intr safe  	IRQ_DISABLE	r9 +#ifdef CONFIG_PREEMPT +  	; Can't preempt if preemption disabled  	GET_CURR_THR_INFO_FROM_SP   r10  	ld  r8, [r10, THREAD_INFO_PREEMPT_COUNT] @@ -640,6 +646,8 @@ resume_kernel_mode:  restore_regs : +	TRACE_ASM_IRQ_ENABLE +  	lr	r10, [status32]  	; Restore REG File. In case multiple Events outstanding, @@ -670,9 +678,9 @@ not_exception:  	brne r9, event_IRQ2, 149f  	;------------------------------------------------------------------ -	; if L2 IRQ interrupted a L1 ISR,  we'd disbaled preemption earlier -	; so that sched doesnt move to new task, causing L1 to be delayed -	; undeterministically. Now that we've achieved that, lets reset +	; if L2 IRQ interrupted an L1 ISR,  we'd disabled preemption earlier +	; so that sched doesn't move to new task, causing L1 to be delayed +	; undeterministically. Now that we've achieved that, let's reset  	; things to what they were, before returning from L2 context  	;---------------------------------------------------------------- @@ -720,15 +728,15 @@ not_level1_interrupt:  debug_marker_syscall:  	rtie -ARC_EXIT ret_from_exception +END(ret_from_exception) -ARC_ENTRY ret_from_fork +ENTRY(ret_from_fork)  	; when the forked child comes here from the __switch_to function  	; r0 has the last task pointer.  	; put last task in scheduler queue  	bl   @schedule_tail -	; If kernel thread, jump to it's entry-point +	; If kernel thread, jump to its entry-point  	ld   r9, [sp, PT_status32]  	brne r9, 0, 1f @@ -739,11 +747,11 @@ ARC_ENTRY ret_from_fork  	; special case of kernel_thread entry point returning back due to  	; kernel_execve() - pretend return from syscall to ret to userland  	b    ret_from_exception -ARC_EXIT ret_from_fork +END(ret_from_fork)  ;################### Special Sys Call Wrappers ########################## -ARC_ENTRY sys_clone_wrapper +ENTRY(sys_clone_wrapper)  	SAVE_CALLEE_SAVED_USER  	bl  @sys_clone  	DISCARD_CALLEE_SAVED_USER @@ -753,7 +761,7 @@ ARC_ENTRY sys_clone_wrapper  	bnz  tracesys_exit  	b ret_from_system_call -ARC_EXIT sys_clone_wrapper +END(sys_clone_wrapper)  #ifdef CONFIG_ARC_DW2_UNWIND  ; Workaround for bug 94179 (STAR ):  | 
