summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 @@
#define ECR_V_ITLB_MISS 0x21
#define ECR_V_DTLB_MISS 0x22
#define ECR_V_PROTV 0x23
+#define ECR_V_TRAP 0x25
/* Protection Violation Exception Cause Code Values */
#define ECR_C_PROTV_INST_FETCH 0x00
@@ -77,6 +78,9 @@
#define ECR_C_BIT_DTLB_LD_MISS 8
#define ECR_C_BIT_DTLB_ST_MISS 9
+/* Dummy ECR values for Interrupts */
+#define event_IRQ1 0x0031abcd
+#define event_IRQ2 0x0032abcd
/* Auxiliary registers */
#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 @@
#endif
/* Save Pre Intr/Exception User SP on kernel stack */
- st.a sp, [r9, -16] ; Make room for orig_r0, orig_r8, user_r25
+ st.a sp, [r9, -16] ; Make room for orig_r0, ECR, user_r25
/* CAUTION:
* SP should be set at the very end when we are done with everything
@@ -391,9 +391,10 @@
* Note that syscalls are implemented via TRAP which is also a exception
* from CPU's point of view
*-------------------------------------------------------------*/
-.macro SAVE_ALL_EXCEPTION marker
+.macro SAVE_ALL_SYS
- st \marker, [sp, 8] /* orig_r8 */
+ lr r9, [ecr]
+ st r9, [sp, 8] /* ECR */
st r0, [sp, 4] /* orig_r0, needed only for sys calls */
/* Restore r9 used to code the early prologue */
@@ -412,20 +413,6 @@
.endm
/*--------------------------------------------------------------
- * Save scratch regs for exceptions
- *-------------------------------------------------------------*/
-.macro SAVE_ALL_SYS
- SAVE_ALL_EXCEPTION orig_r8_IS_EXCPN
-.endm
-
-/*--------------------------------------------------------------
- * Save scratch regs for sys calls
- *-------------------------------------------------------------*/
-.macro SAVE_ALL_TRAP
- SAVE_ALL_EXCEPTION orig_r8_IS_SCALL
-.endm
-
-/*--------------------------------------------------------------
* Restore all registers used by system call or Exceptions
* SP should always be pointing to the next free stack element
* when entering this macro.
@@ -452,7 +439,7 @@
RESTORE_R12_TO_R0
ld sp, [sp] /* restore original sp */
- /* orig_r0, orig_r8, user_r25 skipped automatically */
+ /* orig_r0, ECR, user_r25 skipped automatically */
.endm
@@ -469,7 +456,7 @@
#endif
/* now we are ready to save the remaining context :) */
- st orig_r8_IS_IRQ1, [sp, 8] /* Event Type */
+ st event_IRQ1, [sp, 8] /* Dummy ECR */
st 0, [sp, 4] /* orig_r0 , N/A for IRQ */
SAVE_R0_TO_R12
@@ -494,7 +481,7 @@
ld r9, [@int2_saved_reg]
/* now we are ready to save the remaining context :) */
- st orig_r8_IS_IRQ2, [sp, 8] /* Event Type */
+ st event_IRQ2, [sp, 8] /* Dummy ECR */
st 0, [sp, 4] /* orig_r0 , N/A for IRQ */
SAVE_R0_TO_R12
@@ -535,7 +522,7 @@
RESTORE_R12_TO_R0
ld sp, [sp] /* restore original sp */
- /* orig_r0, orig_r8, user_r25 skipped automatically */
+ /* orig_r0, ECR, user_r25 skipped automatically */
.endm
.macro RESTORE_ALL_INT2
@@ -554,7 +541,7 @@
RESTORE_R12_TO_R0
ld sp, [sp] /* restore original sp */
- /* orig_r0, orig_r8, user_r25 skipped automatically */
+ /* orig_r0, ECR, user_r25 skipped automatically */
.endm
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 {
long sp; /* user/kernel sp depending on where we came from */
long orig_r0;
- /*to distinguish bet excp, syscall, irq */
+ /*
+ * To distinguish bet excp, syscall, irq
+ * For traps and exceptions, Exception Cause Register.
+ * ECR: <00> <VV> <CC> <PP>
+ * Last word used by Linux for extra state mgmt (syscall-restart)
+ * For interrupts, use artificial ECR values to note current prio-level
+ */
union {
+ struct {
#ifdef CONFIG_CPU_BIG_ENDIAN
- /* so that assembly code is same for LE/BE */
- unsigned long orig_r8:16, event:16;
+ unsigned long state:8, ecr_vec:8,
+ ecr_cause:8, ecr_param:8;
#else
- unsigned long event:16, orig_r8:16;
+ unsigned long ecr_param:8, ecr_cause:8,
+ ecr_vec:8, state:8;
#endif
- long orig_r8_word;
+ };
+ unsigned long event;
};
long user_r25;
@@ -94,11 +103,13 @@ struct callee_regs {
/* return 1 if PC in delay slot */
#define delay_mode(regs) ((regs->status32 & STATUS_DE_MASK) == STATUS_DE_MASK)
-#define in_syscall(regs) (regs->event & orig_r8_IS_SCALL)
-#define in_brkpt_trap(regs) (regs->event & orig_r8_IS_BRKPT)
+#define in_syscall(regs) ((regs->ecr_vec == ECR_V_TRAP) && !regs->ecr_param)
+#define in_brkpt_trap(regs) ((regs->ecr_vec == ECR_V_TRAP) && regs->ecr_param)
-#define syscall_wont_restart(regs) (regs->event |= orig_r8_IS_SCALL_RESTARTED)
-#define syscall_restartable(regs) !(regs->event & orig_r8_IS_SCALL_RESTARTED)
+#define STATE_SCALL_RESTARTED 0x01
+
+#define syscall_wont_restart(reg) (reg->state |= STATE_SCALL_RESTARTED)
+#define syscall_restartable(reg) !(reg->state & STATE_SCALL_RESTARTED)
#define current_pt_regs() \
({ \
@@ -115,11 +126,4 @@ static inline long regs_return_value(struct pt_regs *regs)
#endif /* !__ASSEMBLY__ */
-#define orig_r8_IS_SCALL 0x0001
-#define orig_r8_IS_SCALL_RESTARTED 0x0002
-#define orig_r8_IS_BRKPT 0x0004
-#define orig_r8_IS_EXCPN 0x0008
-#define orig_r8_IS_IRQ1 0x0010
-#define orig_r8_IS_IRQ2 0x0020
-
#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)
BLANK();
DEFINE(PT_status32, offsetof(struct pt_regs, status32));
- DEFINE(PT_orig_r8, offsetof(struct pt_regs, orig_r8_word));
+ DEFINE(PT_event, offsetof(struct pt_regs, event));
DEFINE(PT_sp, offsetof(struct pt_regs, sp));
DEFINE(PT_r0, offsetof(struct pt_regs, r0));
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
.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
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)
* with trap_s 4 (compiled) breakpoints, continuation needs to
* start after the breakpoint.
*/
- if (param == 3)
+ if (regs->ecr_param == 3)
instruction_pointer(regs) -= BREAK_INSTR_SIZE;
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);
* ------------------
* | SP |
* | orig_r0 |
- * | orig_r8 |
+ * | event/ECR |
* | user_r25 |
* ------------------ <===== END of PAGE
*/
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)
static void show_ecr_verbose(struct pt_regs *regs)
{
- unsigned int vec, cause_code, cause_reg;
+ unsigned int vec, cause_code;
unsigned long address;
- cause_reg = current->thread.cause_code;
- pr_info("\n[ECR ]: 0x%08x => ", cause_reg);
+ pr_info("\n[ECR ]: 0x%08lx => ", regs->event);
/* For Data fault, this is data address not instruction addr */
address = current->thread.fault_address;
- vec = cause_reg >> 16;
- cause_code = (cause_reg >> 8) & 0xFF;
+ vec = regs->ecr_vec;
+ cause_code = regs->ecr_cause;
/* For DTLB Miss or ProtV, display the memory involved too */
if (vec == ECR_V_DTLB_MISS) {
@@ -174,8 +173,7 @@ void show_regs(struct pt_regs *regs)
print_task_path_n_nm(tsk, buf);
show_regs_print_info(KERN_INFO);
- if (current->thread.cause_code)
- show_ecr_verbose(regs);
+ show_ecr_verbose(regs);
pr_info("[EFA ]: 0x%08lx\n[BLINK ]: %pS\n[ERET ]: %pS\n",
current->thread.fault_address,