#include <asm/unwind.h>
#include <asm/tls.h>
#include <asm/system_misc.h>
-
-#include "signal.h"
-
-static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
+#include <linux/aee.h>
+static const char *handler[]= {
+ "prefetch abort",
+ "data abort",
+ "address exception",
+ "interrupt",
+ "undefined instruction",
+};
void *vectors_page;
}
#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);
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;
/* 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);
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);
}
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())
int is_valid_bugaddr(unsigned long pc)
{
#ifdef CONFIG_THUMB2_KERNEL
- unsigned short bkpt;
+ u16 bkpt;
+ u16 insn = __opcode_to_mem_thumb16(BUG_INSTR_VALUE);
#else
- unsigned long bkpt;
+ u32 bkpt;
+ u32 insn = __opcode_to_mem_arm(BUG_INSTR_VALUE);
#endif
if (probe_kernel_address((unsigned *)pc, bkpt))
return 0;
- return bkpt == BUG_INSTR_VALUE;
+ return bkpt == insn;
}
#endif
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) {
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
}
#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)
{
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) {
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;
}
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);
}