diff options
Diffstat (limited to 'arch/arc')
-rw-r--r-- | arch/arc/include/asm/arcregs.h | 4 | ||||
-rw-r--r-- | arch/arc/include/asm/entry.h | 31 | ||||
-rw-r--r-- | arch/arc/include/asm/ptrace.h | 36 | ||||
-rw-r--r-- | arch/arc/kernel/asm-offsets.c | 2 | ||||
-rw-r--r-- | arch/arc/kernel/entry.S | 21 | ||||
-rw-r--r-- | arch/arc/kernel/kgdb.c | 2 | ||||
-rw-r--r-- | arch/arc/kernel/process.c | 2 | ||||
-rw-r--r-- | arch/arc/kernel/troubleshoot.c | 12 |
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: | |||
495 | trap_with_param: | 495 | trap_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 | ||
118 | static void show_ecr_verbose(struct pt_regs *regs) | 118 | static 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, |