aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arc/kernel
diff options
context:
space:
mode:
authorVineet Gupta <vgupta@synopsys.com>2013-06-11 09:26:54 -0400
committerVineet Gupta <vgupta@synopsys.com>2013-06-26 04:34:48 -0400
commit502a0c775c7f0a01065e0d078e06c0440b86a11a (patch)
treedf280c7ba4533c0d6fddcd3985f4da3cd6a68dd8 /arch/arc/kernel
parent352c1d95e3220d0ea33cefac5c1f0deb2c4470c6 (diff)
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')
-rw-r--r--arch/arc/kernel/asm-offsets.c2
-rw-r--r--arch/arc/kernel/entry.S21
-rw-r--r--arch/arc/kernel/kgdb.c2
-rw-r--r--arch/arc/kernel/process.c2
-rw-r--r--arch/arc/kernel/troubleshoot.c12
5 files changed, 20 insertions, 19 deletions
diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c
index 75f05b83d77d..6c3aa0edb9b5 100644
--- a/arch/arc/kernel/asm-offsets.c
+++ b/arch/arc/kernel/asm-offsets.c
@@ -46,7 +46,7 @@ int main(void)
46 BLANK(); 46 BLANK();
47 47
48 DEFINE(PT_status32, offsetof(struct pt_regs, status32)); 48 DEFINE(PT_status32, offsetof(struct pt_regs, status32));
49 DEFINE(PT_orig_r8, offsetof(struct pt_regs, orig_r8_word)); 49 DEFINE(PT_event, offsetof(struct pt_regs, event));
50 DEFINE(PT_sp, offsetof(struct pt_regs, sp)); 50 DEFINE(PT_sp, offsetof(struct pt_regs, sp));
51 DEFINE(PT_r0, offsetof(struct pt_regs, r0)); 51 DEFINE(PT_r0, offsetof(struct pt_regs, r0));
52 DEFINE(PT_r1, offsetof(struct pt_regs, r1)); 52 DEFINE(PT_r1, offsetof(struct pt_regs, r1));
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
142.endr 142.endr
143 143
144#include <linux/linkage.h> /* ARC_{EXTRY,EXIT} */ 144#include <linux/linkage.h> /* ARC_{EXTRY,EXIT} */
145#include <asm/entry.h> /* SAVE_ALL_{INT1,INT2,TRAP...} */ 145#include <asm/entry.h> /* SAVE_ALL_{INT1,INT2,SYS...} */
146#include <asm/errno.h> 146#include <asm/errno.h>
147#include <asm/arcregs.h> 147#include <asm/arcregs.h>
148#include <asm/irqflags.h> 148#include <asm/irqflags.h>
@@ -495,8 +495,6 @@ tracesys_exit:
495trap_with_param: 495trap_with_param:
496 496
497 ; stop_pc info by gdb needs this info 497 ; stop_pc info by gdb needs this info
498 stw orig_r8_IS_BRKPT, [sp, PT_orig_r8]
499
500 mov r0, r12 498 mov r0, r12
501 lr r1, [efa] 499 lr r1, [efa]
502 mov r2, sp 500 mov r2, sp
@@ -541,7 +539,7 @@ ARC_ENTRY EV_Trap
541 lr r9, [erstatus] 539 lr r9, [erstatus]
542 540
543 SWITCH_TO_KERNEL_STK 541 SWITCH_TO_KERNEL_STK
544 SAVE_ALL_TRAP 542 SAVE_ALL_SYS
545 543
546 ;------- (4) What caused the Trap -------------- 544 ;------- (4) What caused the Trap --------------
547 lr r12, [ecr] 545 lr r12, [ecr]
@@ -696,28 +694,33 @@ not_exception:
696 694
697#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS 695#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
698 696
697 ; Level 2 interrupt return Path - from hardware standpoint
699 bbit0 r10, STATUS_A2_BIT, not_level2_interrupt 698 bbit0 r10, STATUS_A2_BIT, not_level2_interrupt
700 699
701 ;------------------------------------------------------------------ 700 ;------------------------------------------------------------------
701 ; However the context returning might not have taken L2 intr itself
702 ; e.g. Task'A' user-code -> L2 intr -> schedule -> 'B' user-code ret
703 ; Special considerations needed for the context which took L2 intr
704
705 ld r9, [sp, PT_event] ; Ensure this is L2 intr context
706 brne r9, event_IRQ2, 149f
707
708 ;------------------------------------------------------------------
702 ; if L2 IRQ interrupted a L1 ISR, we'd disbaled preemption earlier 709 ; if L2 IRQ interrupted a L1 ISR, we'd disbaled preemption earlier
703 ; so that sched doesnt move to new task, causing L1 to be delayed 710 ; so that sched doesnt move to new task, causing L1 to be delayed
704 ; undeterministically. Now that we've achieved that, lets reset 711 ; undeterministically. Now that we've achieved that, lets reset
705 ; things to what they were, before returning from L2 context 712 ; things to what they were, before returning from L2 context
706 ;---------------------------------------------------------------- 713 ;----------------------------------------------------------------
707 714
708 ldw r9, [sp, PT_orig_r8] ; get orig_r8 to make sure it is
709 brne r9, orig_r8_IS_IRQ2, 149f ; infact a L2 ISR ret path
710
711 ld r9, [sp, PT_status32] ; get statu32_l2 (saved in pt_regs) 715 ld r9, [sp, PT_status32] ; get statu32_l2 (saved in pt_regs)
712 bbit0 r9, STATUS_A1_BIT, 149f ; L1 not active when L2 IRQ, so normal 716 bbit0 r9, STATUS_A1_BIT, 149f ; L1 not active when L2 IRQ, so normal
713 717
714 ; A1 is set in status32_l2
715 ; decrement thread_info->preempt_count (re-enable preemption) 718 ; decrement thread_info->preempt_count (re-enable preemption)
716 GET_CURR_THR_INFO_FROM_SP r10 719 GET_CURR_THR_INFO_FROM_SP r10
717 ld r9, [r10, THREAD_INFO_PREEMPT_COUNT] 720 ld r9, [r10, THREAD_INFO_PREEMPT_COUNT]
718 721
719 ; paranoid check, given A1 was active when A2 happened, preempt count 722 ; paranoid check, given A1 was active when A2 happened, preempt count
720 ; must not be 0 beccause we would have incremented it. 723 ; must not be 0 because we would have incremented it.
721 ; If this does happen we simply HALT as it means a BUG !!! 724 ; If this does happen we simply HALT as it means a BUG !!!
722 cmp r9, 0 725 cmp r9, 0
723 bnz 2f 726 bnz 2f
diff --git a/arch/arc/kernel/kgdb.c b/arch/arc/kernel/kgdb.c
index 52bdc83c1495..84f1bb8208b4 100644
--- a/arch/arc/kernel/kgdb.c
+++ b/arch/arc/kernel/kgdb.c
@@ -181,7 +181,7 @@ void kgdb_trap(struct pt_regs *regs, int param)
181 * with trap_s 4 (compiled) breakpoints, continuation needs to 181 * with trap_s 4 (compiled) breakpoints, continuation needs to
182 * start after the breakpoint. 182 * start after the breakpoint.
183 */ 183 */
184 if (param == 3) 184 if (regs->ecr_param == 3)
185 instruction_pointer(regs) -= BREAK_INSTR_SIZE; 185 instruction_pointer(regs) -= BREAK_INSTR_SIZE;
186 186
187 kgdb_handle_exception(1, SIGTRAP, 0, regs); 187 kgdb_handle_exception(1, SIGTRAP, 0, regs);
diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c
index a3cc6a577039..07a3a968fe49 100644
--- a/arch/arc/kernel/process.c
+++ b/arch/arc/kernel/process.c
@@ -76,7 +76,7 @@ asmlinkage void ret_from_fork(void);
76 * ------------------ 76 * ------------------
77 * | SP | 77 * | SP |
78 * | orig_r0 | 78 * | orig_r0 |
79 * | orig_r8 | 79 * | event/ECR |
80 * | user_r25 | 80 * | user_r25 |
81 * ------------------ <===== END of PAGE 81 * ------------------ <===== END of PAGE
82 */ 82 */
diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c
index 31a5d8905e1a..977464126be9 100644
--- a/arch/arc/kernel/troubleshoot.c
+++ b/arch/arc/kernel/troubleshoot.c
@@ -117,17 +117,16 @@ static void show_faulting_vma(unsigned long address, char *buf)
117 117
118static void show_ecr_verbose(struct pt_regs *regs) 118static void show_ecr_verbose(struct pt_regs *regs)
119{ 119{
120 unsigned int vec, cause_code, cause_reg; 120 unsigned int vec, cause_code;
121 unsigned long address; 121 unsigned long address;
122 122
123 cause_reg = current->thread.cause_code; 123 pr_info("\n[ECR ]: 0x%08lx => ", regs->event);
124 pr_info("\n[ECR ]: 0x%08x => ", cause_reg);
125 124
126 /* For Data fault, this is data address not instruction addr */ 125 /* For Data fault, this is data address not instruction addr */
127 address = current->thread.fault_address; 126 address = current->thread.fault_address;
128 127
129 vec = cause_reg >> 16; 128 vec = regs->ecr_vec;
130 cause_code = (cause_reg >> 8) & 0xFF; 129 cause_code = regs->ecr_cause;
131 130
132 /* For DTLB Miss or ProtV, display the memory involved too */ 131 /* For DTLB Miss or ProtV, display the memory involved too */
133 if (vec == ECR_V_DTLB_MISS) { 132 if (vec == ECR_V_DTLB_MISS) {
@@ -174,8 +173,7 @@ void show_regs(struct pt_regs *regs)
174 print_task_path_n_nm(tsk, buf); 173 print_task_path_n_nm(tsk, buf);
175 show_regs_print_info(KERN_INFO); 174 show_regs_print_info(KERN_INFO);
176 175
177 if (current->thread.cause_code) 176 show_ecr_verbose(regs);
178 show_ecr_verbose(regs);
179 177
180 pr_info("[EFA ]: 0x%08lx\n[BLINK ]: %pS\n[ERET ]: %pS\n", 178 pr_info("[EFA ]: 0x%08lx\n[BLINK ]: %pS\n[ERET ]: %pS\n",
181 current->thread.fault_address, 179 current->thread.fault_address,