summary refs log tree commit diff
path: root/arch/arc/kernel/entry.S
diff options
context:
space:
mode:
authorVineet Gupta <vgupta@synopsys.com>2013-06-11 18:56:54 +0530
committerVineet Gupta <vgupta@synopsys.com>2013-06-26 14:04:48 +0530
commit502a0c775c7f0a01065e0d078e06c0440b86a11a (patch)
treedf280c7ba4533c0d6fddcd3985f4da3cd6a68dd8 /arch/arc/kernel/entry.S
parent352c1d95e3220d0ea33cefac5c1f0deb2c4470c6 (diff)
downloadlinux-502a0c775c7f0a01065e0d078e06c0440b86a11a.tar.gz
ARC: pt_regs update #5: Use real ECR for pt_regs->event vs. synth values
pt_regs->event was set with artificial values to identify the low level
system event (syscall trap / breakpoint trap / exceptions / interrupts)

With r8 saving out of the way, the full word can be used to save real
ECR (Exception Cause Register) which helps idenify the event naturally,
including additional info such as cause code, param.
Only for Interrupts, where ECR is not applicable, do we resort to
synthetic non ECR values.

SAVE_ALL_TRAP/EXCEPTIONS can now be merged as they both use ECR with
different runtime values.

The ptrace helpers now use the sub-fields of ECR to distinguish the
events (e.g. vector 0x25 is trap, param 0 is syscall...)

The following benefits will follow:

(1) This centralizes the location of where ECR is saved and will allow
    the cleanup of task->thread.cause_code ECR placeholder which is set
    in non-uniform way. Then ARC VM code can safely rely on it being
    there for purpose of finer grained VM_EXEC dcache flush (based on
    exec fault: I-TLB Miss)

(2) Further, ECR being passed around from low level handlers as arg can
    be eliminated as it is part of standard reg-file in pt_regs

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch/arc/kernel/entry.S')
-rw-r--r--arch/arc/kernel/entry.S21
1 files changed, 12 insertions, 9 deletions
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index fd5f9160bbd2..fb0fe3265637 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -142,7 +142,7 @@ VECTOR   reserved                ; Reserved Exceptions
 .endr
 
 #include <linux/linkage.h>   /* ARC_{EXTRY,EXIT} */
-#include <asm/entry.h>       /* SAVE_ALL_{INT1,INT2,TRAP...} */
+#include <asm/entry.h>       /* SAVE_ALL_{INT1,INT2,SYS...} */
 #include <asm/errno.h>
 #include <asm/arcregs.h>
 #include <asm/irqflags.h>
@@ -495,8 +495,6 @@ tracesys_exit:
 trap_with_param:
 
 	; stop_pc info by gdb needs this info
-	stw orig_r8_IS_BRKPT, [sp, PT_orig_r8]
-
 	mov r0, r12
 	lr  r1, [efa]
 	mov r2, sp
@@ -541,7 +539,7 @@ ARC_ENTRY EV_Trap
 	lr  r9, [erstatus]
 
 	SWITCH_TO_KERNEL_STK
-	SAVE_ALL_TRAP
+	SAVE_ALL_SYS
 
 	;------- (4) What caused the Trap --------------
 	lr     r12, [ecr]
@@ -696,28 +694,33 @@ not_exception:
 
 #ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
 
+	; Level 2 interrupt return Path - from hardware standpoint
 	bbit0  r10, STATUS_A2_BIT, not_level2_interrupt
 
 	;------------------------------------------------------------------
+	; However the context returning might not have taken L2 intr itself
+	; e.g. Task'A' user-code -> L2 intr -> schedule -> 'B' user-code ret
+	; Special considerations needed for the context which took L2 intr
+
+	ld   r9, [sp, PT_event]        ; Ensure this is L2 intr context
+	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
 	; things to what they were, before returning from L2 context
 	;----------------------------------------------------------------
 
-	ldw  r9, [sp, PT_orig_r8]      ; get orig_r8 to make sure it is
-	brne r9, orig_r8_IS_IRQ2, 149f ; infact a L2 ISR ret path
-
 	ld r9, [sp, PT_status32]       ; get statu32_l2 (saved in pt_regs)
 	bbit0 r9, STATUS_A1_BIT, 149f  ; L1 not active when L2 IRQ, so normal
 
-	; A1 is set in status32_l2
 	; decrement thread_info->preempt_count (re-enable preemption)
 	GET_CURR_THR_INFO_FROM_SP   r10
 	ld      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
 
 	; paranoid check, given A1 was active when A2 happened, preempt count
-	; must not be 0 beccause we would have incremented it.
+	; must not be 0 because we would have incremented it.
 	; If this does happen we simply HALT as it means a BUG !!!
 	cmp     r9, 0
 	bnz     2f