summaryrefslogtreecommitdiffstats
path: root/arch/arc
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
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')
-rw-r--r--arch/arc/include/asm/arcregs.h4
-rw-r--r--arch/arc/include/asm/entry.h31
-rw-r--r--arch/arc/include/asm/ptrace.h36
-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
8 files changed, 53 insertions, 57 deletions
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index 122e9af46824..355cb470c2a4 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -60,6 +60,7 @@
60#define ECR_V_ITLB_MISS 0x21 60#define ECR_V_ITLB_MISS 0x21
61#define ECR_V_DTLB_MISS 0x22 61#define ECR_V_DTLB_MISS 0x22
62#define ECR_V_PROTV 0x23 62#define ECR_V_PROTV 0x23
63#define ECR_V_TRAP 0x25
63 64
64/* Protection Violation Exception Cause Code Values */ 65/* Protection Violation Exception Cause Code Values */
65#define ECR_C_PROTV_INST_FETCH 0x00 66#define ECR_C_PROTV_INST_FETCH 0x00
@@ -77,6 +78,9 @@
77#define ECR_C_BIT_DTLB_LD_MISS 8 78#define ECR_C_BIT_DTLB_LD_MISS 8
78#define ECR_C_BIT_DTLB_ST_MISS 9 79#define ECR_C_BIT_DTLB_ST_MISS 9
79 80
81/* Dummy ECR values for Interrupts */
82#define event_IRQ1 0x0031abcd
83#define event_IRQ2 0x0032abcd
80 84
81/* Auxiliary registers */ 85/* Auxiliary registers */
82#define AUX_IDENTITY 4 86#define AUX_IDENTITY 4
diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h
index de01bc842a9a..8943c028d4bb 100644
--- a/arch/arc/include/asm/entry.h
+++ b/arch/arc/include/asm/entry.h
@@ -309,7 +309,7 @@
309#endif 309#endif
310 310
311 /* Save Pre Intr/Exception User SP on kernel stack */ 311 /* Save Pre Intr/Exception User SP on kernel stack */
312 st.a sp, [r9, -16] ; Make room for orig_r0, orig_r8, user_r25 312 st.a sp, [r9, -16] ; Make room for orig_r0, ECR, user_r25
313 313
314 /* CAUTION: 314 /* CAUTION:
315 * SP should be set at the very end when we are done with everything 315 * SP should be set at the very end when we are done with everything
@@ -391,9 +391,10 @@
391 * Note that syscalls are implemented via TRAP which is also a exception 391 * Note that syscalls are implemented via TRAP which is also a exception
392 * from CPU's point of view 392 * from CPU's point of view
393 *-------------------------------------------------------------*/ 393 *-------------------------------------------------------------*/
394.macro SAVE_ALL_EXCEPTION marker 394.macro SAVE_ALL_SYS
395 395
396 st \marker, [sp, 8] /* orig_r8 */ 396 lr r9, [ecr]
397 st r9, [sp, 8] /* ECR */
397 st r0, [sp, 4] /* orig_r0, needed only for sys calls */ 398 st r0, [sp, 4] /* orig_r0, needed only for sys calls */
398 399
399 /* Restore r9 used to code the early prologue */ 400 /* Restore r9 used to code the early prologue */
@@ -412,20 +413,6 @@
412.endm 413.endm
413 414
414/*-------------------------------------------------------------- 415/*--------------------------------------------------------------
415 * Save scratch regs for exceptions
416 *-------------------------------------------------------------*/
417.macro SAVE_ALL_SYS
418 SAVE_ALL_EXCEPTION orig_r8_IS_EXCPN
419.endm
420
421/*--------------------------------------------------------------
422 * Save scratch regs for sys calls
423 *-------------------------------------------------------------*/
424.macro SAVE_ALL_TRAP
425 SAVE_ALL_EXCEPTION orig_r8_IS_SCALL
426.endm
427
428/*--------------------------------------------------------------
429 * Restore all registers used by system call or Exceptions 416 * Restore all registers used by system call or Exceptions
430 * SP should always be pointing to the next free stack element 417 * SP should always be pointing to the next free stack element
431 * when entering this macro. 418 * when entering this macro.
@@ -452,7 +439,7 @@
452 RESTORE_R12_TO_R0 439 RESTORE_R12_TO_R0
453 440
454 ld sp, [sp] /* restore original sp */ 441 ld sp, [sp] /* restore original sp */
455 /* orig_r0, orig_r8, user_r25 skipped automatically */ 442 /* orig_r0, ECR, user_r25 skipped automatically */
456.endm 443.endm
457 444
458 445
@@ -469,7 +456,7 @@
469#endif 456#endif
470 457
471 /* now we are ready to save the remaining context :) */ 458 /* now we are ready to save the remaining context :) */
472 st orig_r8_IS_IRQ1, [sp, 8] /* Event Type */ 459 st event_IRQ1, [sp, 8] /* Dummy ECR */
473 st 0, [sp, 4] /* orig_r0 , N/A for IRQ */ 460 st 0, [sp, 4] /* orig_r0 , N/A for IRQ */
474 461
475 SAVE_R0_TO_R12 462 SAVE_R0_TO_R12
@@ -494,7 +481,7 @@
494 ld r9, [@int2_saved_reg] 481 ld r9, [@int2_saved_reg]
495 482
496 /* now we are ready to save the remaining context :) */ 483 /* now we are ready to save the remaining context :) */
497 st orig_r8_IS_IRQ2, [sp, 8] /* Event Type */ 484 st event_IRQ2, [sp, 8] /* Dummy ECR */
498 st 0, [sp, 4] /* orig_r0 , N/A for IRQ */ 485 st 0, [sp, 4] /* orig_r0 , N/A for IRQ */
499 486
500 SAVE_R0_TO_R12 487 SAVE_R0_TO_R12
@@ -535,7 +522,7 @@
535 RESTORE_R12_TO_R0 522 RESTORE_R12_TO_R0
536 523
537 ld sp, [sp] /* restore original sp */ 524 ld sp, [sp] /* restore original sp */
538 /* orig_r0, orig_r8, user_r25 skipped automatically */ 525 /* orig_r0, ECR, user_r25 skipped automatically */
539.endm 526.endm
540 527
541.macro RESTORE_ALL_INT2 528.macro RESTORE_ALL_INT2
@@ -554,7 +541,7 @@
554 RESTORE_R12_TO_R0 541 RESTORE_R12_TO_R0
555 542
556 ld sp, [sp] /* restore original sp */ 543 ld sp, [sp] /* restore original sp */
557 /* orig_r0, orig_r8, user_r25 skipped automatically */ 544 /* orig_r0, ECR, user_r25 skipped automatically */
558.endm 545.endm
559 546
560 547
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index 7b2de6f7025a..c9938e7a7dbd 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -44,15 +44,24 @@ struct pt_regs {
44 long sp; /* user/kernel sp depending on where we came from */ 44 long sp; /* user/kernel sp depending on where we came from */
45 long orig_r0; 45 long orig_r0;
46 46
47 /*to distinguish bet excp, syscall, irq */ 47 /*
48 * To distinguish bet excp, syscall, irq
49 * For traps and exceptions, Exception Cause Register.
50 * ECR: <00> <VV> <CC> <PP>
51 * Last word used by Linux for extra state mgmt (syscall-restart)
52 * For interrupts, use artificial ECR values to note current prio-level
53 */
48 union { 54 union {
55 struct {
49#ifdef CONFIG_CPU_BIG_ENDIAN 56#ifdef CONFIG_CPU_BIG_ENDIAN
50 /* so that assembly code is same for LE/BE */ 57 unsigned long state:8, ecr_vec:8,
51 unsigned long orig_r8:16, event:16; 58 ecr_cause:8, ecr_param:8;
52#else 59#else
53 unsigned long event:16, orig_r8:16; 60 unsigned long ecr_param:8, ecr_cause:8,
61 ecr_vec:8, state:8;
54#endif 62#endif
55 long orig_r8_word; 63 };
64 unsigned long event;
56 }; 65 };
57 66
58 long user_r25; 67 long user_r25;
@@ -94,11 +103,13 @@ struct callee_regs {
94/* return 1 if PC in delay slot */ 103/* return 1 if PC in delay slot */
95#define delay_mode(regs) ((regs->status32 & STATUS_DE_MASK) == STATUS_DE_MASK) 104#define delay_mode(regs) ((regs->status32 & STATUS_DE_MASK) == STATUS_DE_MASK)
96 105
97#define in_syscall(regs) (regs->event & orig_r8_IS_SCALL) 106#define in_syscall(regs) ((regs->ecr_vec == ECR_V_TRAP) && !regs->ecr_param)
98#define in_brkpt_trap(regs) (regs->event & orig_r8_IS_BRKPT) 107#define in_brkpt_trap(regs) ((regs->ecr_vec == ECR_V_TRAP) && regs->ecr_param)
99 108
100#define syscall_wont_restart(regs) (regs->event |= orig_r8_IS_SCALL_RESTARTED) 109#define STATE_SCALL_RESTARTED 0x01
101#define syscall_restartable(regs) !(regs->event & orig_r8_IS_SCALL_RESTARTED) 110
111#define syscall_wont_restart(reg) (reg->state |= STATE_SCALL_RESTARTED)
112#define syscall_restartable(reg) !(reg->state & STATE_SCALL_RESTARTED)
102 113
103#define current_pt_regs() \ 114#define current_pt_regs() \
104({ \ 115({ \
@@ -115,11 +126,4 @@ static inline long regs_return_value(struct pt_regs *regs)
115 126
116#endif /* !__ASSEMBLY__ */ 127#endif /* !__ASSEMBLY__ */
117 128
118#define orig_r8_IS_SCALL 0x0001
119#define orig_r8_IS_SCALL_RESTARTED 0x0002
120#define orig_r8_IS_BRKPT 0x0004
121#define orig_r8_IS_EXCPN 0x0008
122#define orig_r8_IS_IRQ1 0x0010
123#define orig_r8_IS_IRQ2 0x0020
124
125#endif /* __ASM_PTRACE_H */ 129#endif /* __ASM_PTRACE_H */
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,