From 38a9ff6d247cf9afcbe55ea245b650b8955029fd Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Wed, 12 Jun 2013 15:13:40 +0530 Subject: [PATCH] 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(-) diff --git a/arch/arc/include/asm/bug.h b/arch/arc/include/asm/bug.h index 2ad8f9b..5b18e94 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 4930957..b65fca7 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 4d9c211..944dbed 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 b0b5d2d..15334ab 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 5dbe63f..60702f3 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 fb0fe32..1d71651 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 84f1bb8..a7698fb 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 5a7b80e..72f9782 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 0471d9c..e21692d 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 9774641..7f85bc3 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 4cd8163..c0f832f 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 fdafeb1..318164c 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 bd8bc90..8d61fdf 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 -- 2.7.4