void aee_stop_nested_panic(struct pt_regs *regs) { struct thread_info *thread = current_thread_info(); int len = 0; int timeout = 1000000; int res = 0, cpu = 0; struct wd_api *wd_api = NULL; struct pt_regs *excp_regs = NULL; int prev_fiq_step = aee_rr_curr_fiq_step(); /* everytime enter nested_panic flow, add 8 */ static int step_base = -8; step_base = step_base < 48 ? step_base + 8 : 56; aee_rec_step_nested_panic(step_base); local_irq_disable(); preempt_disable(); aee_rec_step_nested_panic(step_base + 1); cpu = get_HW_cpuid(); aee_rec_step_nested_panic(step_base + 2); /*nested panic may happens more than once on many/single cpus */ if (atomic_read(&nested_panic_time) < 3) aee_nested_printf("\nCPU%dpanic%d@%d\n", cpu, nested_panic_time, prev_fiq_step); atomic_inc(&nested_panic_time); switch (atomic_read(&nested_panic_time)) { case 2: aee_print_regs(regs); aee_nested_printf("backtrace:"); aee_print_bt(regs); break; /* must guarantee Only one cpu can run here */ /* first check if thread valid */ case 1: if (virt_addr_valid(thread) && virt_addr_valid(thread->regs_on_excp)) { excp_regs = thread->regs_on_excp; } else { /* if thread invalid, which means wrong sp or thread_info corrupted, check global aee_excp_regs instead */ aee_nested_printf("invalid thread [%x], excp_regs [%x]\n", thread, aee_excp_regs); excp_regs = aee_excp_regs; } aee_nested_printf("Nested panic\n"); if (excp_regs) { aee_nested_printf("Previous\n"); aee_print_regs(excp_regs); } aee_nested_printf("Current\n"); aee_print_regs(regs); /*should not print stack info. this may overwhelms ram console used by fiq */ if (0 != in_fiq_handler()) { aee_nested_printf("in fiq hander\n"); } else { /*Dump first panic stack */ aee_nested_printf("Previous\n"); if (excp_regs) { len = aee_nested_save_stack(excp_regs); aee_nested_printf("\nbacktrace:"); aee_print_bt(excp_regs); } /*Dump second panic stack */ aee_nested_printf("Current\n"); if (virt_addr_valid(regs)) { len = aee_nested_save_stack(regs); aee_nested_printf("\nbacktrace:"); aee_print_bt(regs); } } aee_rec_step_nested_panic(step_base + 5); ipanic_recursive_ke(regs, excp_regs, cpu); aee_rec_step_nested_panic(step_base + 6); /* we donot want a FIQ after this, so disable hwt */ res = get_wd_api(&wd_api); if (res) { aee_nested_printf("get_wd_api error\n"); } else { wd_api->wd_aee_confirm_hwreboot(); } aee_rec_step_nested_panic(step_base + 7); break; default: break; } /* waiting for the WDT timeout */ while (1) { /* output to UART directly to avoid printk nested panic */ /* mt_fiq_printf("%s hang here%d\t", __func__, i++); */ while (timeout--) { udelay(1); } timeout = 1000000; } }
void aee_stop_nested_panic(struct pt_regs *regs) { struct thread_info *thread = current_thread_info(); int i = 0; int len = 0; int timeout = 1000000; local_irq_disable(); preempt_disable(); /*Data abort handler data abort again on many cpu. Since ram console api is lockless, this should be prevented*/ if(atomic_xchg(&nested_panic_time, 1) != 0) { aee_nested_printf("multicore enters nested panic\n"); goto out; } mtk_wdt_restart(WK_WDT_LOC_TYPE_NOLOCK); hw_reboot_mode(); /*must guarantee Only one cpu can run here*/ aee_nested_printf("Nested panic\n"); aee_nested_printf("Log for the previous panic:\n"); aee_nested_printf("pc: %08lx lr: %08lx psr: %08lx\n", ((struct pt_regs *)thread->regs_on_excp)->ARM_pc, ((struct pt_regs *)thread->regs_on_excp)->ARM_lr, ((struct pt_regs *)thread->regs_on_excp)->ARM_cpsr); aee_nested_printf("sp: %08lx ip: %08lx fp: %08lx\n", ((struct pt_regs *)thread->regs_on_excp)->ARM_sp, ((struct pt_regs *)thread->regs_on_excp)->ARM_ip, ((struct pt_regs *)thread->regs_on_excp)->ARM_fp); aee_nested_printf("r10: %08lx r9: %08lx r8: %08lx\n", ((struct pt_regs *)thread->regs_on_excp)->ARM_r10, ((struct pt_regs *)thread->regs_on_excp)->ARM_r9, ((struct pt_regs *)thread->regs_on_excp)->ARM_r8); aee_nested_printf("r7: %08lx r6: %08lx r5: %08lx r4: %08lx\n", ((struct pt_regs *)thread->regs_on_excp)->ARM_r7, ((struct pt_regs *)thread->regs_on_excp)->ARM_r6, ((struct pt_regs *)thread->regs_on_excp)->ARM_r5, ((struct pt_regs *)thread->regs_on_excp)->ARM_r4); aee_nested_printf("r3: %08lx r2: %08lx r1: %08lx r0: %08lx\n", ((struct pt_regs *)thread->regs_on_excp)->ARM_r3, ((struct pt_regs *)thread->regs_on_excp)->ARM_r2, ((struct pt_regs *)thread->regs_on_excp)->ARM_r1, ((struct pt_regs *)thread->regs_on_excp)->ARM_r0); aee_nested_printf("Log for the current panic:\n"); aee_nested_printf("pc: %08lx lr: %08lx psr: %08lx\n", regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr); aee_nested_printf("sp: %08lx ip: %08lx fp: %08lx\n", regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); aee_nested_printf("r10: %08lx r9: %08lx r8: %08lx\n", regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); aee_nested_printf("r7: %08lx r6: %08lx r5: %08lx r4: %08lx\n", regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); len = aee_nested_printf("r3: %08lx r2: %08lx r1: %08lx r0: %08lx\n", regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0); /*should not print stack info. this may overwhelms ram console used by fiq*/ if(0!= in_fiq_handler()) { goto out; } aee_nested_printf("stack [%08lx %08lx]", ((struct pt_regs *)thread->regs_on_excp)->ARM_sp, ((struct pt_regs *)thread->regs_on_excp)->ARM_sp + 512); /*Dump first panic stack*/ len = aee_dump_stack_top_binary(nested_panic_buf, sizeof(nested_panic_buf), ((struct pt_regs *)thread->regs_on_excp)->ARM_sp, ((struct pt_regs *)thread->regs_on_excp)->ARM_sp + 512 ); if(len > 0) { aee_sram_fiq_save_bin(nested_panic_buf, len); }else{ print_error_msg(len); } aee_nested_printf("stack [%08lx %08lx]", regs->ARM_sp, regs->ARM_sp + 256); /*Dump second panic stack*/ len = aee_dump_stack_top_binary(nested_panic_buf, sizeof(nested_panic_buf), regs->ARM_sp, regs->ARM_sp + 256); if(len > 0) { aee_sram_fiq_save_bin(nested_panic_buf, len); }else { print_error_msg(len); } out: /* waiting for the WDT timeout */ while (1) { printk("%s hang here%d\t", __func__, i++); while(timeout--) { udelay(1); } timeout = 1000000; } }