X-Git-Url: https://git.stricted.de/?p=GitHub%2Fmt8127%2Fandroid_kernel_alcatel_ttab.git;a=blobdiff_plain;f=arch%2Farm%2Fkernel%2Ftraps.c;h=536d4c803b85d17bc4a0b406b4634dda46aa80a2;hp=18b32e8e4497f4c1966f43ac6fbb4963315fb968;hb=b4350432998578500203d562d5b093c6a5beadd2;hpb=297b8a07347555f0d2fafa4a1ddfc332d2d4afa9 diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 18b32e8e4497..536d4c803b85 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -34,10 +34,14 @@ #include #include #include - -#include "signal.h" - -static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; +#include +static const char *handler[]= { + "prefetch abort", + "data abort", + "address exception", + "interrupt", + "undefined instruction", +}; void *vectors_page; @@ -204,6 +208,13 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) } #endif +void dump_stack(void) +{ + dump_backtrace(NULL, NULL); +} + +EXPORT_SYMBOL(dump_stack); + void show_stack(struct task_struct *tsk, unsigned long *sp) { dump_backtrace(NULL, tsk); @@ -229,6 +240,7 @@ void show_stack(struct task_struct *tsk, unsigned long *sp) static int __die(const char *str, int err, struct pt_regs *regs) { struct task_struct *tsk = current; + unsigned long sp, stack; static int die_counter; int ret; @@ -238,7 +250,7 @@ static int __die(const char *str, int err, struct pt_regs *regs) /* trap and error numbers are mostly meaningless on ARM */ ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV); if (ret == NOTIFY_STOP) - return 1; + return ret; print_modules(); __show_regs(regs); @@ -246,8 +258,13 @@ static int __die(const char *str, int err, struct pt_regs *regs) TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), end_of_stack(tsk)); if (!user_mode(regs) || in_interrupt()) { - dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp, - THREAD_SIZE + (unsigned long)task_stack_page(tsk)); + sp = regs->ARM_sp; + stack = (unsigned long)task_stack_page(tsk); + dump_mem(KERN_EMERG, "Stack: ", sp, ALIGN(sp, THREAD_SIZE)); + if (sp < stack || (sp - stack) > THREAD_SIZE) { + printk(KERN_EMERG "Invalid sp[%lx] or stack address[%lx]\n", sp, stack); + dump_mem(KERN_EMERG, "Stack(backup) ", stack, THREAD_SIZE + stack); + } dump_backtrace(regs, tsk); dump_instr(KERN_EMERG, regs); } @@ -294,7 +311,8 @@ static void oops_end(unsigned long flags, struct pt_regs *regs, int signr) if (!die_nest_count) /* Nest count reaches zero, release the lock. */ arch_spin_unlock(&die_lock); - raw_local_irq_restore(flags); + /* not enable irq incase softirq many turn off msdc clock */ + //raw_local_irq_restore(flags); oops_exit(); if (in_interrupt()) @@ -393,12 +411,29 @@ static int call_undef_hook(struct pt_regs *regs, unsigned int instr) return fn ? fn(regs, instr) : 1; } +volatile static void __user *prev_undefinstr_pc=0; +volatile static int prev_undefinstr_counter=0; +volatile static unsigned long prev_undefinstr_curr=0; + asmlinkage void __exception do_undefinstr(struct pt_regs *regs) { + struct thread_info *thread = current_thread_info(); + int ret; unsigned int instr; siginfo_t info; void __user *pc; + if (!user_mode(regs)) { + thread->cpu_excp++; + if (thread->cpu_excp == 1) { + thread->regs_on_excp = (void *)regs; + aee_excp_regs = (void*)regs; + } + if (thread->cpu_excp >= 2) { + aee_stop_nested_panic(regs); + } + } + pc = (void __user *)instruction_pointer(regs); if (processor_mode(regs) == SVC_MODE) { @@ -426,8 +461,13 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) goto die_sig; } - if (call_undef_hook(regs, instr) == 0) + ret = call_undef_hook(regs, instr); + if (ret == 0) { + if (!user_mode(regs)) { + thread->cpu_excp--; + } return; + } die_sig: #ifdef CONFIG_DEBUG_USER @@ -438,13 +478,54 @@ die_sig: } #endif + /* Place the SIGILL ICache Invalidate after the Debugger Undefined-Instruction Solution. */ + if ((processor_mode(regs) == USR_MODE) || (processor_mode(regs) == SVC_MODE)) { + /* Only do it for User-Space Application. */ + printk("USR_MODE/SVC_MODE Undefined Instruction Address curr:%p pc=%p:%p\n", + (void *)current, (void *)pc, (void *)prev_undefinstr_pc); + if ((prev_undefinstr_pc != pc) || (prev_undefinstr_curr != (unsigned long)current)) { + /* If the current process or program counter is changed......renew the counter. */ + printk("First Time Recovery curr:%p pc=%p:%p\n", + (void *)current, (void *)pc, (void *)prev_undefinstr_pc); + prev_undefinstr_pc = pc; + prev_undefinstr_curr = (unsigned long)current; + prev_undefinstr_counter = 0; + __cpuc_flush_icache_all(); + flush_cache_all(); + if (!user_mode(regs)) { + thread->cpu_excp--; + } + return; + } + else if(prev_undefinstr_counter < 1) { + printk("2nd Time Recovery curr:%p pc=%p:%p\n", + (void *)current, (void *)pc, (void *)prev_undefinstr_pc); + prev_undefinstr_counter++; + __cpuc_flush_icache_all(); + flush_cache_all(); + if (!user_mode(regs)) { + thread->cpu_excp--; + } + return; + } + prev_undefinstr_counter++; + if(prev_undefinstr_counter >= 4) { + /* 2=first time SigILL,3=2nd time NE-SigILL,4=3rd time CoreDump-SigILL */ + prev_undefinstr_pc = 0; + prev_undefinstr_curr = 0; + prev_undefinstr_counter = 0; + } + printk("Go to ARM Notify Die curr:%p pc=%p:%p\n", + (void *)current, (void *)pc, (void *)prev_undefinstr_pc); + } + info.si_signo = SIGILL; info.si_errno = 0; info.si_code = ILL_ILLOPC; info.si_addr = pc; arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6); -} + } asmlinkage void do_unexp_fiq (struct pt_regs *regs) { @@ -581,7 +662,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) return regs->ARM_r0; case NR(set_tls): - thread->tp_value = regs->ARM_r0; + thread->tp_value[0] = regs->ARM_r0; if (tls_emu) return 0; if (has_tls_reg) { @@ -699,7 +780,7 @@ static int get_tp_trap(struct pt_regs *regs, unsigned int instr) int reg = (instr >> 12) & 15; if (reg == 15) return 1; - regs->uregs[reg] = current_thread_info()->tp_value; + regs->uregs[reg] = current_thread_info()->tp_value[0]; regs->ARM_pc += 4; return 0; } @@ -800,47 +881,55 @@ void __init trap_init(void) return; } -static void __init kuser_get_tls_init(unsigned long vectors) +#ifdef CONFIG_KUSER_HELPERS +static void __init kuser_init(void *vectors) { + extern char __kuser_helper_start[], __kuser_helper_end[]; + int kuser_sz = __kuser_helper_end - __kuser_helper_start; + + memcpy(vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz); + /* * vectors + 0xfe0 = __kuser_get_tls * vectors + 0xfe8 = hardware TLS instruction at 0xffff0fe8 */ if (tls_emu || has_tls_reg) - memcpy((void *)vectors + 0xfe0, (void *)vectors + 0xfe8, 4); + memcpy(vectors + 0xfe0, vectors + 0xfe8, 4); } +#else +static void __init kuser_init(void *vectors) +{ +} +#endif void __init early_trap_init(void *vectors_base) { unsigned long vectors = (unsigned long)vectors_base; extern char __stubs_start[], __stubs_end[]; extern char __vectors_start[], __vectors_end[]; - extern char __kuser_helper_start[], __kuser_helper_end[]; - int kuser_sz = __kuser_helper_end - __kuser_helper_start; + unsigned i; vectors_page = vectors_base; + /* + * Poison the vectors page with an undefined instruction. This + * instruction is chosen to be undefined for both ARM and Thumb + * ISAs. The Thumb version is an undefined instruction with a + * branch back to the undefined instruction. + */ + for (i = 0; i < PAGE_SIZE / sizeof(u32); i++) + ((u32 *)vectors_base)[i] = 0xe7fddef1; + /* * Copy the vectors, stubs and kuser helpers (in entry-armv.S) * into the vector page, mapped at 0xffff0000, and ensure these * are visible to the instruction stream. */ memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); - memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start); - memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz); + memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start); - /* - * Do processor specific fixups for the kuser helpers - */ - kuser_get_tls_init(vectors); - - /* - * Copy signal return handlers into the vector page, and - * set sigreturn to be a pointer to these. - */ - memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE), - sigreturn_codes, sizeof(sigreturn_codes)); + kuser_init(vectors_base); - flush_icache_range(vectors, vectors + PAGE_SIZE); + flush_icache_range(vectors, vectors + PAGE_SIZE * 2); modify_domain(DOMAIN_USER, DOMAIN_CLIENT); }