From 283237a04fd332bddc2ac298e6ad7d23a1fc4b99 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Tue, 28 May 2013 09:34:45 +0530 Subject: ARC: pt_regs update #1: Align pt_regs end with end of kernel stack page Historically, pt_regs would end at offset of 1 word from end of stack page. ----------------- -> START of page (task->stack) | | | thread_info | ----------------- | | ^ ~ ~ | ~ ~ | | | | | | <---- pt_regs used to END here ----------------- | 1 word GUTTER | ----------------- -> End of page (START of kernel stack) This required special "one-off" considerations in low level code. The root cause is very likely assumption of "empty" SP by the original ARC kernel hackers, despite ARC700 always been "full" SP. So finally RIP one word gutter ! Signed-off-by: Vineet Gupta --- arch/arc/include/asm/processor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arc/include/asm/processor.h') diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h index 5f26b2c1cba..81efbcae383 100644 --- a/arch/arc/include/asm/processor.h +++ b/arch/arc/include/asm/processor.h @@ -50,7 +50,7 @@ struct task_struct; unsigned long thread_saved_pc(struct task_struct *t); #define task_pt_regs(p) \ - ((struct pt_regs *)(THREAD_SIZE - 4 + (void *)task_stack_page(p)) - 1) + ((struct pt_regs *)(THREAD_SIZE + (void *)task_stack_page(p)) - 1) /* Free all resources held by a thread. */ #define release_thread(thread) do { } while (0) -- cgit v1.2.3-70-g09d2 From 16f9afe651e8197fb7ce6df0990d8e2ad779e1af Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Mon, 27 May 2013 21:43:41 +0530 Subject: ARC: pt_regs update #3: Remove unused gutter at start of callee_regs This is trickier than prev two: * context switching code saves kernel mode callee regs in the format of struct callee_regs thus needs adjustment. This also reduces the height of topmost kernel stack frame by 1 word. * Since kernel stack unwinder is sensitive to height of topmost kernel stack frame, that needs a word of adjustment too. ptrace needs a bit of updating since pt_regs now diverges from user_regs_struct. Signed-off-by: Vineet Gupta --- arch/arc/include/asm/entry.h | 14 +++----------- arch/arc/include/asm/processor.h | 11 ++++++++--- arch/arc/include/asm/ptrace.h | 1 - arch/arc/include/uapi/asm/ptrace.h | 2 +- arch/arc/kernel/asm-offsets.c | 1 + arch/arc/kernel/ctx_sw.c | 14 +++++--------- arch/arc/kernel/process.c | 4 +--- arch/arc/kernel/ptrace.c | 6 ++++-- arch/arc/kernel/stacktrace.c | 2 +- 9 files changed, 24 insertions(+), 31 deletions(-) (limited to 'arch/arc/include/asm/processor.h') diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h index 5ff7b8dd3d5..820202af21a 100644 --- a/arch/arc/include/asm/entry.h +++ b/arch/arc/include/asm/entry.h @@ -124,8 +124,6 @@ st.a r25, [sp, -4] #endif - /* move up by 1 word to "create" callee_regs->"stack_place_holder" */ - sub sp, sp, 4 .endm /*-------------------------------------------------------------- @@ -148,10 +146,9 @@ st.a r23, [sp, -4] st.a r24, [sp, -4] #ifdef CONFIG_ARC_CURR_IN_REG - sub sp, sp, 8 + sub sp, sp, 4 #else st.a r25, [sp, -4] - sub sp, sp, 4 #endif .endm @@ -168,14 +165,11 @@ *-------------------------------------------------------------*/ .macro RESTORE_CALLEE_SAVED_KERNEL - #ifdef CONFIG_ARC_CURR_IN_REG - add sp, sp, 8 /* skip callee_reg gutter and user r25 placeholder */ + add sp, sp, 4 /* skip usual r25 placeholder */ #else - add sp, sp, 4 /* skip "callee_regs->stack_place_holder" */ ld.ab r25, [sp, 4] #endif - ld.ab r24, [sp, 4] ld.ab r23, [sp, 4] ld.ab r22, [sp, 4] @@ -203,8 +197,6 @@ *-------------------------------------------------------------*/ .macro RESTORE_CALLEE_SAVED_USER - add sp, sp, 4 /* skip "callee_regs->stack_place_holder" */ - #ifdef CONFIG_ARC_CURR_IN_REG ld.ab r12, [sp, 4] st r12, [r25, TASK_THREAD + THREAD_USER_R25] @@ -230,7 +222,7 @@ * Super FAST Restore callee saved regs by simply re-adjusting SP *-------------------------------------------------------------*/ .macro DISCARD_CALLEE_SAVED_USER - add sp, sp, 14 * 4 + add sp, sp, SZ_CALLEE_REGS .endm /*-------------------------------------------------------------- diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h index 81efbcae383..8c77e623c4e 100644 --- a/arch/arc/include/asm/processor.h +++ b/arch/arc/include/asm/processor.h @@ -19,6 +19,7 @@ #ifndef __ASSEMBLY__ #include /* for STATUS_E1_MASK et all */ +#include /* Arch specific stuff which needs to be saved per task. * However these items are not so important so as to earn a place in @@ -75,11 +76,15 @@ unsigned long thread_saved_pc(struct task_struct *t); /* * Where abouts of Task's sp, fp, blink when it was last seen in kernel mode. - * These can't be derived from pt_regs as that would give correp user-mode val + * Look in process.c for details of kernel stack layout */ #define KSTK_ESP(tsk) (tsk->thread.ksp) -#define KSTK_BLINK(tsk) (*((unsigned int *)((KSTK_ESP(tsk)) + (13+1+1)*4))) -#define KSTK_FP(tsk) (*((unsigned int *)((KSTK_ESP(tsk)) + (13+1)*4))) + +#define KSTK_REG(tsk, off) (*((unsigned int *)(KSTK_ESP(tsk) + \ + sizeof(struct callee_regs) + off))) + +#define KSTK_BLINK(tsk) KSTK_REG(tsk, 4) +#define KSTK_FP(tsk) KSTK_REG(tsk, 0) /* * Do necessary setup to start up a newly executed thread. diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index 7491bb7428b..47801ba135b 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h @@ -59,7 +59,6 @@ struct pt_regs { /* Callee saved registers - need to be saved only when you are scheduled out */ struct callee_regs { - long res; /* Again this is not needed */ long r25; long r24; long r23; diff --git a/arch/arc/include/uapi/asm/ptrace.h b/arch/arc/include/uapi/asm/ptrace.h index e0e8403f181..4599109f68f 100644 --- a/arch/arc/include/uapi/asm/ptrace.h +++ b/arch/arc/include/uapi/asm/ptrace.h @@ -38,8 +38,8 @@ struct user_regs_struct { long r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r1, r0; long sp; } scratch; + long pad2; struct { - long pad; long r25, r24, r23, r22, r21, r20; long r19, r18, r17, r16, r15, r14, r13; } callee; diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c index 7dcda702524..fdcd76532b7 100644 --- a/arch/arc/kernel/asm-offsets.c +++ b/arch/arc/kernel/asm-offsets.c @@ -60,5 +60,6 @@ int main(void) DEFINE(PT_r6, offsetof(struct pt_regs, r6)); DEFINE(PT_r7, offsetof(struct pt_regs, r7)); + DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs)); return 0; } diff --git a/arch/arc/kernel/ctx_sw.c b/arch/arc/kernel/ctx_sw.c index 60844dac613..34410eb1a30 100644 --- a/arch/arc/kernel/ctx_sw.c +++ b/arch/arc/kernel/ctx_sw.c @@ -23,10 +23,6 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) unsigned int tmp; unsigned int prev = (unsigned int)prev_task; unsigned int next = (unsigned int)next_task; - int num_words_to_skip = 1; -#ifdef CONFIG_ARC_CURR_IN_REG - num_words_to_skip++; -#endif __asm__ __volatile__( /* FP/BLINK save generated by gcc (standard function prologue */ @@ -44,8 +40,9 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) "st.a r24, [sp, -4] \n\t" #ifndef CONFIG_ARC_CURR_IN_REG "st.a r25, [sp, -4] \n\t" +#else + "sub sp, sp, 4 \n\t" /* usual r25 placeholder */ #endif - "sub sp, sp, %4 \n\t" /* create gutter at top */ /* set ksp of outgoing task in tsk->thread.ksp */ "st.as sp, [%3, %1] \n\t" @@ -76,10 +73,10 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) /* start loading it's CALLEE reg file */ - "add sp, sp, %4 \n\t" /* skip gutter at top */ - #ifndef CONFIG_ARC_CURR_IN_REG "ld.ab r25, [sp, 4] \n\t" +#else + "add sp, sp, 4 \n\t" #endif "ld.ab r24, [sp, 4] \n\t" "ld.ab r23, [sp, 4] \n\t" @@ -100,8 +97,7 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) /* FP/BLINK restore generated by gcc (standard func epilogue */ : "=r"(tmp) - : "n"((TASK_THREAD + THREAD_KSP) / 4), "r"(next), "r"(prev), - "n"(num_words_to_skip * 4) + : "n"((TASK_THREAD + THREAD_KSP) / 4), "r"(next), "r"(prev) : "blink" ); diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c index 949bfd5d62a..db868db8294 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -55,10 +55,8 @@ asmlinkage void ret_from_fork(void); * | ... | * | unused | * | | - * ------------------ <==== top of Stack (thread.ksp) - * | UNUSED 1 word| * ------------------ - * | r25 | + * | r25 | <==== top of Stack (thread.ksp) * ~ ~ * | --to-- | (CALLEE Regs of user mode) * | r13 | diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c index 6e467e3585b..333238564b6 100644 --- a/arch/arc/kernel/ptrace.c +++ b/arch/arc/kernel/ptrace.c @@ -48,6 +48,7 @@ static int genregs_get(struct task_struct *target, REG_O_ZERO(pad); REG_O_CHUNK(scratch, callee, ptregs); + REG_O_ZERO(pad2); REG_O_CHUNK(callee, efa, cregs); REG_O_CHUNK(efa, stop_pc, &target->thread.fault_address); @@ -96,8 +97,9 @@ static int genregs_set(struct task_struct *target, offsetof(struct user_regs_struct, LOC) + 4); REG_IGNORE_ONE(pad); - /* TBD: disallow updates to STATUS32, orig_r8 etc*/ - REG_IN_CHUNK(scratch, callee, ptregs); /* pt_regs[bta..orig_r8] */ + /* TBD: disallow updates to STATUS32 etc*/ + REG_IN_CHUNK(scratch, pad2, ptregs); /* pt_regs[bta..sp] */ + REG_IGNORE_ONE(pad2); REG_IN_CHUNK(callee, efa, cregs); /* callee_regs[r25..r13] */ REG_IGNORE_ONE(efa); /* efa update invalid */ REG_IN_ONE(stop_pc, &ptregs->ret); /* stop_pc: PC update */ diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c index ca0207b9d5b..f8b7d880304 100644 --- a/arch/arc/kernel/stacktrace.c +++ b/arch/arc/kernel/stacktrace.c @@ -79,7 +79,7 @@ static void seed_unwind_frame_info(struct task_struct *tsk, * assembly code */ frame_info->regs.r27 = 0; - frame_info->regs.r28 += 64; + frame_info->regs.r28 += 60; frame_info->call_frame = 0; } else { -- cgit v1.2.3-70-g09d2 From 359105bdb06f8421fd8e69ae47fd052e398b6778 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Tue, 28 May 2013 13:50:41 +0530 Subject: ARC: pt_regs update #4: r25 saved/restored unconditionally (This is a VERY IMP change for low level interrupt/exception handling) ----------------------------------------------------------------------- WHAT ----------------------------------------------------------------------- * User 25 now saved in pt_regs->user_r25 (vs. tsk->thread_info.user_r25) * This allows Low level interrupt code to unconditionally save r25 (vs. the prev version which would only do it for U->K transition). Ofcourse for nested interrupts, only the pt_regs->user_r25 of bottom-most frame is useful. * simplifies the interrupt prologue/epilogue * Needed for ARCv2 ISA code and done here to keep design similar with ARCompact event handling ----------------------------------------------------------------------- WHY ------------------------------------------------------------------------- With CONFIG_ARC_CURR_IN_REG, r25 is used to cache "current" task pointer in kernel mode. So when entering kernel mode from User Mode - user r25 is specially safe-kept (it being a callee reg is NOT part of pt_regs which are saved by default on each interrupt/trap/exception) - r25 loaded with current task pointer. Further, if interrupt was taken in kernel mode, this is skipped since we know that r25 already has valid "current" pointer. With 2 level of interrupts in ARCompact ISA, detecting this is difficult but still possible, since we could be in kernel mode but r25 not already saved (in fact the stack itself might not have been switched). A. User mode B. L1 IRQ taken C. L2 IRQ taken (while on 1st line of L1 ISR) So in #C, although in kernel mode, r25 not saved (infact SP not switched at all) Given that ARcompact has manual stack switching, we could use a bit of trickey - The low level code would make sure that SP is only set to kernel mode value at the very end (after saving r25). So a non kernel mode SP, even if in kernel mode, meant r25 was NOT saved. The same paradigm won't work in ARCv2 ISA since SP is auto-switched so it's setting can't be delayed/constrained. Signed-off-by: Vineet Gupta --- arch/arc/include/asm/entry.h | 43 +++++++++++++++++++--------------------- arch/arc/include/asm/processor.h | 3 --- arch/arc/include/asm/ptrace.h | 2 ++ arch/arc/kernel/asm-offsets.c | 4 +--- arch/arc/kernel/entry.S | 11 ---------- arch/arc/kernel/process.c | 1 + 6 files changed, 24 insertions(+), 40 deletions(-) (limited to 'arch/arc/include/asm/processor.h') diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h index 2cf6aa08cfc..72a7ed47117 100644 --- a/arch/arc/include/asm/entry.h +++ b/arch/arc/include/asm/entry.h @@ -102,6 +102,10 @@ POP r2 POP r1 POP r0 + +#ifdef CONFIG_ARC_CURR_IN_REG + ld r25, [sp, 12] +#endif .endm /*-------------------------------------------------------------- @@ -138,6 +142,7 @@ POP r13 .endm +#define OFF_USER_R25_FROM_R24 (SZ_CALLEE_REGS + SZ_PT_REGS - 8)/4 /*-------------------------------------------------------------- * Collect User Mode callee regs as struct callee_regs - needed by @@ -155,7 +160,7 @@ #ifdef CONFIG_ARC_CURR_IN_REG ; Retrieve orig r25 and save it on stack - ld r12, [r25, TASK_THREAD + THREAD_USER_R25] + ld.as r12, [sp, OFF_USER_R25_FROM_R24] st.a r12, [sp, -4] #else PUSH r25 @@ -204,7 +209,7 @@ #ifdef CONFIG_ARC_CURR_IN_REG ld.ab r12, [sp, 4] - st r12, [r25, TASK_THREAD + THREAD_USER_R25] + st.as r12, [sp, OFF_USER_R25_FROM_R24] #else POP r25 #endif @@ -218,13 +223,6 @@ add sp, sp, SZ_CALLEE_REGS .endm -/*-------------------------------------------------------------- - * Restore User mode r25 saved in task_struct->thread.user_r25 - *-------------------------------------------------------------*/ -.macro RESTORE_USER_R25 - ld r25, [r25, TASK_THREAD + THREAD_USER_R25] -.endm - /*------------------------------------------------------------- * given a tsk struct, get to the base of it's kernel mode stack * tsk->thread_info is really a PAGE, whose bottom hoists stack @@ -297,22 +295,21 @@ GET_CURR_TASK_ON_CPU r9 -#ifdef CONFIG_ARC_CURR_IN_REG - - /* If current task pointer cached in r25, time to - * -safekeep USER r25 in task->thread_struct->user_r25 - * -load r25 with current task ptr - */ - st.as r25, [r9, (TASK_THREAD + THREAD_USER_R25)/4] - mov r25, r9 -#endif - /* With current tsk in r9, get it's kernel mode stack base */ GET_TSK_STACK_BASE r9, r9 66: +#ifdef CONFIG_ARC_CURR_IN_REG + /* + * Treat r25 as scratch reg, save it on stack first + * Load it with current task pointer + */ + st r25, [r9, -4] + GET_CURR_TASK_ON_CPU r25 +#endif + /* Save Pre Intr/Exception User SP on kernel stack */ - st.a sp, [r9, -12] ; Make room for orig_r0 and orig_r8 + st.a sp, [r9, -16] ; Make room for orig_r0, orig_r8, user_r25 /* CAUTION: * SP should be set at the very end when we are done with everything @@ -466,7 +463,7 @@ RESTORE_R12_TO_R0 ld sp, [sp] /* restore original sp */ - /* orig_r0 and orig_r8 skipped automatically */ + /* orig_r0, orig_r8, user_r25 skipped automatically */ .endm @@ -549,7 +546,7 @@ RESTORE_R12_TO_R0 ld sp, [sp] /* restore original sp */ - /* orig_r0 and orig_r8 skipped automatically */ + /* orig_r0, orig_r8, user_r25 skipped automatically */ .endm .macro RESTORE_ALL_INT2 @@ -568,7 +565,7 @@ RESTORE_R12_TO_R0 ld sp, [sp] /* restore original sp */ - /* orig_r0 and orig_r8 skipped automatically */ + /* orig_r0, orig_r8, user_r25 skipped automatically */ .endm diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h index 8c77e623c4e..b0b5d2d9b3d 100644 --- a/arch/arc/include/asm/processor.h +++ b/arch/arc/include/asm/processor.h @@ -30,9 +30,6 @@ struct thread_struct { unsigned long callee_reg; /* pointer to callee regs */ unsigned long fault_address; /* dbls as brkpt holder as well */ unsigned long cause_code; /* Exception Cause Code (ECR) */ -#ifdef CONFIG_ARC_CURR_IN_REG - unsigned long user_r25; -#endif #ifdef CONFIG_ARC_FPU_SAVE_RESTORE struct arc_fpu fpu; #endif diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index 47801ba135b..7b2de6f7025 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h @@ -54,6 +54,8 @@ struct pt_regs { #endif long orig_r8_word; }; + + long user_r25; }; /* Callee saved registers - need to be saved only when you are scheduled out */ diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c index fdcd76532b7..75f05b83d77 100644 --- a/arch/arc/kernel/asm-offsets.c +++ b/arch/arc/kernel/asm-offsets.c @@ -24,9 +24,6 @@ int main(void) DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); DEFINE(THREAD_CALLEE_REG, offsetof(struct thread_struct, callee_reg)); -#ifdef CONFIG_ARC_CURR_IN_REG - DEFINE(THREAD_USER_R25, offsetof(struct thread_struct, user_r25)); -#endif DEFINE(THREAD_FAULT_ADDR, offsetof(struct thread_struct, fault_address)); @@ -61,5 +58,6 @@ int main(void) DEFINE(PT_r7, offsetof(struct pt_regs, r7)); DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs)); + DEFINE(SZ_PT_REGS, sizeof(struct pt_regs)); return 0; } diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index 919e2f065d2..fd5f9160bbd 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -680,17 +680,6 @@ restore_regs : ; XXX can this be optimised out IRQ_DISABLE_SAVE r9, r10 ;@r10 has prisitine (pre-disable) copy -#ifdef CONFIG_ARC_CURR_IN_REG - ; Restore User R25 - ; Earlier this used to be only for returning to user mode - ; However with 2 levels of IRQ this can also happen even if - ; in kernel mode - ld r9, [sp, PT_sp] - brhs r9, VMALLOC_START, 8f - RESTORE_USER_R25 -8: -#endif - ; Restore REG File. In case multiple Events outstanding, ; use the same priorty as rtie: EXCPN, L2 IRQ, L1 IRQ, None ; Note that we use realtime STATUS32 (not pt_regs->status32) to diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c index c6e22e06057..a3cc6a57703 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -77,6 +77,7 @@ asmlinkage void ret_from_fork(void); * | SP | * | orig_r0 | * | orig_r8 | + * | user_r25 | * ------------------ <===== END of PAGE */ int copy_thread(unsigned long clone_flags, -- cgit v1.2.3-70-g09d2 From 38a9ff6d247cf9afcbe55ea245b650b8955029fd Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Wed, 12 Jun 2013 15:13:40 +0530 Subject: ARC: Remove explicit passing around of ECR With ECR now part of pt_regs * No need to propagate from lowest asm handlers as arg * No need to save it in tsk->thread.cause_code * Avoid bit chopping to access the bit-fields More code consolidation, cleanup Signed-off-by: Vineet Gupta --- arch/arc/include/asm/bug.h | 5 ++-- arch/arc/include/asm/kgdb.h | 4 ++-- arch/arc/include/asm/kprobes.h | 6 ++--- arch/arc/include/asm/processor.h | 1 - arch/arc/include/asm/unaligned.h | 4 ++-- arch/arc/kernel/entry.S | 40 +++++++++++++------------------ arch/arc/kernel/kgdb.c | 2 +- arch/arc/kernel/kprobes.c | 5 ++-- arch/arc/kernel/traps.c | 52 +++++++++++++++++++--------------------- arch/arc/kernel/troubleshoot.c | 3 +-- arch/arc/kernel/unaligned.c | 2 +- arch/arc/mm/fault.c | 12 ++++------ arch/arc/mm/tlbex.S | 1 - 13 files changed, 59 insertions(+), 78 deletions(-) (limited to 'arch/arc/include/asm/processor.h') diff --git a/arch/arc/include/asm/bug.h b/arch/arc/include/asm/bug.h index 2ad8f9b1c54..5b18e94c667 100644 --- a/arch/arc/include/asm/bug.h +++ b/arch/arc/include/asm/bug.h @@ -18,9 +18,8 @@ struct task_struct; void show_regs(struct pt_regs *regs); void show_stacktrace(struct task_struct *tsk, struct pt_regs *regs); void show_kernel_fault_diag(const char *str, struct pt_regs *regs, - unsigned long address, unsigned long cause_reg); -void die(const char *str, struct pt_regs *regs, unsigned long address, - unsigned long cause_reg); + unsigned long address); +void die(const char *str, struct pt_regs *regs, unsigned long address); #define BUG() do { \ dump_stack(); \ diff --git a/arch/arc/include/asm/kgdb.h b/arch/arc/include/asm/kgdb.h index 4930957ca3d..b65fca7ffeb 100644 --- a/arch/arc/include/asm/kgdb.h +++ b/arch/arc/include/asm/kgdb.h @@ -31,7 +31,7 @@ static inline void arch_kgdb_breakpoint(void) __asm__ __volatile__ ("trap_s 0x4\n"); } -extern void kgdb_trap(struct pt_regs *regs, int param); +extern void kgdb_trap(struct pt_regs *regs); enum arc700_linux_regnums { _R0 = 0, @@ -53,7 +53,7 @@ enum arc700_linux_regnums { }; #else -#define kgdb_trap(regs, param) +#define kgdb_trap(regs) #endif #endif /* __ARC_KGDB_H__ */ diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h index 4d9c211fce7..944dbedb38b 100644 --- a/arch/arc/include/asm/kprobes.h +++ b/arch/arc/include/asm/kprobes.h @@ -50,11 +50,9 @@ struct kprobe_ctlblk { int kprobe_fault_handler(struct pt_regs *regs, unsigned long cause); void kretprobe_trampoline(void); -void trap_is_kprobe(unsigned long cause, unsigned long address, - struct pt_regs *regs); +void trap_is_kprobe(unsigned long address, struct pt_regs *regs); #else -static void trap_is_kprobe(unsigned long cause, unsigned long address, - struct pt_regs *regs) +static void trap_is_kprobe(unsigned long address, struct pt_regs *regs) { } #endif diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h index b0b5d2d9b3d..15334ab66b5 100644 --- a/arch/arc/include/asm/processor.h +++ b/arch/arc/include/asm/processor.h @@ -29,7 +29,6 @@ struct thread_struct { unsigned long ksp; /* kernel mode stack pointer */ unsigned long callee_reg; /* pointer to callee regs */ unsigned long fault_address; /* dbls as brkpt holder as well */ - unsigned long cause_code; /* Exception Cause Code (ECR) */ #ifdef CONFIG_ARC_FPU_SAVE_RESTORE struct arc_fpu fpu; #endif diff --git a/arch/arc/include/asm/unaligned.h b/arch/arc/include/asm/unaligned.h index 5dbe63f17b6..60702f3751d 100644 --- a/arch/arc/include/asm/unaligned.h +++ b/arch/arc/include/asm/unaligned.h @@ -16,11 +16,11 @@ #ifdef CONFIG_ARC_MISALIGN_ACCESS int misaligned_fixup(unsigned long address, struct pt_regs *regs, - unsigned long cause, struct callee_regs *cregs); + struct callee_regs *cregs); #else static inline int misaligned_fixup(unsigned long address, struct pt_regs *regs, - unsigned long cause, struct callee_regs *cregs) + struct callee_regs *cregs) { return 0; } diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index fb0fe326563..1d7165156e1 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -274,10 +274,8 @@ ARC_ENTRY instr_service SWITCH_TO_KERNEL_STK SAVE_ALL_SYS - lr r0, [ecr] - lr r1, [efa] - - mov r2, sp + lr r0, [efa] + mov r1, sp FAKE_RET_FROM_EXCPN r9 @@ -298,9 +296,8 @@ ARC_ENTRY mem_service SWITCH_TO_KERNEL_STK SAVE_ALL_SYS - lr r0, [ecr] - lr r1, [efa] - mov r2, sp + lr r0, [efa] + mov r1, sp bl do_memory_error b ret_from_exception ARC_EXIT mem_service @@ -317,11 +314,11 @@ ARC_ENTRY EV_MachineCheck SWITCH_TO_KERNEL_STK SAVE_ALL_SYS - lr r0, [ecr] - lr r1, [efa] - mov r2, sp + lr r2, [ecr] + lr r0, [efa] + mov r1, sp - lsr r3, r0, 8 + lsr r3, r2, 8 bmsk r3, r3, 7 brne r3, ECR_C_MCHK_DUP_TLB, 1f @@ -384,12 +381,12 @@ ARC_ENTRY EV_TLBProtV ;========== (6b) Non aligned access ============ 4: - mov r0, r2 ; cause code - mov r2, sp ; pt_regs + mov r0, r1 + mov r1, sp ; pt_regs #ifdef CONFIG_ARC_MISALIGN_ACCESS SAVE_CALLEE_SAVED_USER - mov r3, sp ; callee_regs + mov r2, sp ; callee_regs bl do_misaligned_access @@ -416,9 +413,8 @@ ARC_ENTRY EV_PrivilegeV SWITCH_TO_KERNEL_STK SAVE_ALL_SYS - lr r0, [ecr] - lr r1, [efa] - mov r2, sp + lr r0, [efa] + mov r1, sp FAKE_RET_FROM_EXCPN r9 @@ -437,9 +433,8 @@ ARC_ENTRY EV_Extension SWITCH_TO_KERNEL_STK SAVE_ALL_SYS - lr r0, [ecr] - lr r1, [efa] - mov r2, sp + lr r0, [efa] + mov r1, sp bl do_extension_fault b ret_from_exception ARC_EXIT EV_Extension @@ -495,9 +490,8 @@ tracesys_exit: trap_with_param: ; stop_pc info by gdb needs this info - mov r0, r12 - lr r1, [efa] - mov r2, sp + lr r0, [efa] + mov r1, sp ; Now that we have read EFA, its safe to do "fake" rtie ; and get out of CPU exception mode diff --git a/arch/arc/kernel/kgdb.c b/arch/arc/kernel/kgdb.c index 84f1bb8208b..a7698fb1481 100644 --- a/arch/arc/kernel/kgdb.c +++ b/arch/arc/kernel/kgdb.c @@ -169,7 +169,7 @@ int kgdb_arch_init(void) return 0; } -void kgdb_trap(struct pt_regs *regs, int param) +void kgdb_trap(struct pt_regs *regs) { /* trap_s 3 is used for breakpoints that overwrite existing * instructions, while trap_s 4 is used for compiled breakpoints. diff --git a/arch/arc/kernel/kprobes.c b/arch/arc/kernel/kprobes.c index 5a7b80e2d88..72f97822784 100644 --- a/arch/arc/kernel/kprobes.c +++ b/arch/arc/kernel/kprobes.c @@ -517,8 +517,7 @@ int __kprobes arch_trampoline_kprobe(struct kprobe *p) return 0; } -void trap_is_kprobe(unsigned long cause, unsigned long address, - struct pt_regs *regs) +void trap_is_kprobe(unsigned long address, struct pt_regs *regs) { - notify_die(DIE_TRAP, "kprobe_trap", regs, address, cause, SIGTRAP); + notify_die(DIE_TRAP, "kprobe_trap", regs, address, 0, SIGTRAP); } diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c index 0471d9c9dd5..e21692d2fda 100644 --- a/arch/arc/kernel/traps.c +++ b/arch/arc/kernel/traps.c @@ -28,10 +28,9 @@ void __init trap_init(void) return; } -void die(const char *str, struct pt_regs *regs, unsigned long address, - unsigned long cause_reg) +void die(const char *str, struct pt_regs *regs, unsigned long address) { - show_kernel_fault_diag(str, regs, address, cause_reg); + show_kernel_fault_diag(str, regs, address); /* DEAD END */ __asm__("flag 1"); @@ -42,14 +41,13 @@ void die(const char *str, struct pt_regs *regs, unsigned long address, * -for user faults enqueues requested signal * -for kernel, chk if due to copy_(to|from)_user, otherwise die() */ -static noinline int handle_exception(unsigned long cause, char *str, - struct pt_regs *regs, siginfo_t *info) +static noinline int +handle_exception(const char *str, struct pt_regs *regs, siginfo_t *info) { if (user_mode(regs)) { struct task_struct *tsk = current; tsk->thread.fault_address = (__force unsigned int)info->si_addr; - tsk->thread.cause_code = cause; force_sig_info(info->si_signo, info, tsk); @@ -58,14 +56,14 @@ static noinline int handle_exception(unsigned long cause, char *str, if (fixup_exception(regs)) return 0; - die(str, regs, (unsigned long)info->si_addr, cause); + die(str, regs, (unsigned long)info->si_addr); } return 1; } #define DO_ERROR_INFO(signr, str, name, sicode) \ -int name(unsigned long cause, unsigned long address, struct pt_regs *regs) \ +int name(unsigned long address, struct pt_regs *regs) \ { \ siginfo_t info = { \ .si_signo = signr, \ @@ -73,7 +71,7 @@ int name(unsigned long cause, unsigned long address, struct pt_regs *regs) \ .si_code = sicode, \ .si_addr = (void __user *)address, \ }; \ - return handle_exception(cause, str, regs, &info);\ + return handle_exception(str, regs, &info);\ } /* @@ -90,11 +88,11 @@ DO_ERROR_INFO(SIGBUS, "Misaligned Access", do_misaligned_error, BUS_ADRALN) /* * Entry Point for Misaligned Data access Exception, for emulating in software */ -int do_misaligned_access(unsigned long cause, unsigned long address, - struct pt_regs *regs, struct callee_regs *cregs) +int do_misaligned_access(unsigned long address, struct pt_regs *regs, + struct callee_regs *cregs) { - if (misaligned_fixup(address, regs, cause, cregs) != 0) - return do_misaligned_error(cause, address, regs); + if (misaligned_fixup(address, regs, cregs) != 0) + return do_misaligned_error(address, regs); return 0; } @@ -104,10 +102,9 @@ int do_misaligned_access(unsigned long cause, unsigned long address, * Entry point for miscll errors such as Nested Exceptions * -Duplicate TLB entry is handled seperately though */ -void do_machine_check_fault(unsigned long cause, unsigned long address, - struct pt_regs *regs) +void do_machine_check_fault(unsigned long address, struct pt_regs *regs) { - die("Machine Check Exception", regs, address, cause); + die("Machine Check Exception", regs, address); } @@ -120,23 +117,22 @@ void do_machine_check_fault(unsigned long cause, unsigned long address, * -1 used for software breakpointing (gdb) * -2 used by kprobes */ -void do_non_swi_trap(unsigned long cause, unsigned long address, - struct pt_regs *regs) +void do_non_swi_trap(unsigned long address, struct pt_regs *regs) { - unsigned int param = cause & 0xff; + unsigned int param = regs->ecr_param; switch (param) { case 1: - trap_is_brkpt(cause, address, regs); + trap_is_brkpt(address, regs); break; case 2: - trap_is_kprobe(param, address, regs); + trap_is_kprobe(address, regs); break; case 3: case 4: - kgdb_trap(regs, param); + kgdb_trap(regs); break; default: @@ -149,14 +145,14 @@ void do_non_swi_trap(unsigned long cause, unsigned long address, * -For a corner case, ARC kprobes implementation resorts to using * this exception, hence the check */ -void do_insterror_or_kprobe(unsigned long cause, - unsigned long address, - struct pt_regs *regs) +void do_insterror_or_kprobe(unsigned long address, struct pt_regs *regs) { + int rc; + /* Check if this exception is caused by kprobes */ - if (notify_die(DIE_IERR, "kprobe_ierr", regs, address, - cause, SIGILL) == NOTIFY_STOP) + rc = notify_die(DIE_IERR, "kprobe_ierr", regs, address, 0, SIGILL); + if (rc == NOTIFY_STOP) return; - insterror_is_error(cause, address, regs); + insterror_is_error(address, regs); } diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c index 977464126be..7f85bc3f710 100644 --- a/arch/arc/kernel/troubleshoot.c +++ b/arch/arc/kernel/troubleshoot.c @@ -209,10 +209,9 @@ void show_regs(struct pt_regs *regs) } void show_kernel_fault_diag(const char *str, struct pt_regs *regs, - unsigned long address, unsigned long cause_reg) + unsigned long address) { current->thread.fault_address = address; - current->thread.cause_code = cause_reg; /* Caller and Callee regs */ show_regs(regs); diff --git a/arch/arc/kernel/unaligned.c b/arch/arc/kernel/unaligned.c index 4cd81633feb..c0f832f595d 100644 --- a/arch/arc/kernel/unaligned.c +++ b/arch/arc/kernel/unaligned.c @@ -187,7 +187,7 @@ fault: state->fault = 1; * Returns 0 if successfully handled, 1 if some error happened */ int misaligned_fixup(unsigned long address, struct pt_regs *regs, - unsigned long cause, struct callee_regs *cregs) + struct callee_regs *cregs) { struct disasm_state state; char buf[TASK_COMM_LEN]; diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c index fdafeb1917c..318164cabdf 100644 --- a/arch/arc/mm/fault.c +++ b/arch/arc/mm/fault.c @@ -52,15 +52,14 @@ bad_area: return 1; } -void do_page_fault(struct pt_regs *regs, unsigned long address, - unsigned long cause_code) +void do_page_fault(struct pt_regs *regs, unsigned long address) { struct vm_area_struct *vma = NULL; struct task_struct *tsk = current; struct mm_struct *mm = tsk->mm; siginfo_t info; int fault, ret; - int write = cause_code & (1 << ECR_C_BIT_DTLB_ST_MISS); /* ST/EX */ + int write = regs->ecr_cause & ECR_C_PROTV_STORE; /* ST/EX */ unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | (write ? FAULT_FLAG_WRITE : 0); @@ -111,7 +110,8 @@ good_area: /* Handle protection violation, execute on heap or stack */ - if (cause_code == ((ECR_V_PROTV << 16) | ECR_C_PROTV_INST_FETCH)) + if ((regs->ecr_vec == ECR_V_PROTV) && + (regs->ecr_cause == ECR_C_PROTV_INST_FETCH)) goto bad_area; if (write) { @@ -178,7 +178,6 @@ bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { tsk->thread.fault_address = address; - tsk->thread.cause_code = cause_code; info.si_signo = SIGSEGV; info.si_errno = 0; /* info.si_code has been set above */ @@ -199,7 +198,7 @@ no_context: if (fixup_exception(regs)) return; - die("Oops", regs, address, cause_code); + die("Oops", regs, address); out_of_memory: if (is_global_init(tsk)) { @@ -220,7 +219,6 @@ do_sigbus: goto no_context; tsk->thread.fault_address = address; - tsk->thread.cause_code = cause_code; info.si_signo = SIGBUS; info.si_errno = 0; info.si_code = BUS_ADRERR; diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S index bd8bc90f61d..8d61fdf7a43 100644 --- a/arch/arc/mm/tlbex.S +++ b/arch/arc/mm/tlbex.S @@ -382,7 +382,6 @@ do_slow_path_pf: ; ------- setup args for Linux Page fault Hanlder --------- mov_s r0, sp lr r1, [efa] - lr r2, [ecr] ; We don't want exceptions to be disabled while the fault is handled. ; Now that we have saved the context we return from exception hence -- cgit v1.2.3-70-g09d2