static void kernel_reportAPI(const AE_DEFECT_ATTR attr,const int db_opt, const char *module, const char *msg) { struct aee_oops *oops; oops = aee_oops_create(attr, AE_KERNEL_PROBLEM_REPORT, module); if(NULL !=oops){ oops->detail = (char *)msg; oops->detail_len = strlen(msg) + 1; oops->dump_option = db_opt; xlog_printk(ANDROID_LOG_INFO, AEK_LOG_TAG, "%s,%s,%s,0x%x", __func__, module, msg, db_opt); ke_gen_ind_msg(oops); } }
static struct aee_oops *emmc_ipanic_oops_copy(void) { struct aee_oops *oops = NULL; struct ipanic_header *hdr = NULL; int hdr_size = ALIGN(sizeof(struct ipanic_header), EMMC_BLOCK_SIZE); hdr = kzalloc(hdr_size, GFP_KERNEL); if (hdr == NULL) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: Cannot allocate ipanic header memory\n", __FUNCTION__); return NULL; } if (card_dump_func_read((unsigned char *)hdr, hdr_size, 0, EMMC_ID) < 0) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: emmc panic log header read failed\n", __func__); return NULL; } ipanic_block_scramble((unsigned char *)hdr, hdr_size); if (ipanic_header_check(hdr) != 0) { return NULL; } oops = aee_oops_create(AE_DEFECT_FATAL, AE_KE, IPANIC_MODULE_TAG); if (oops != NULL) { struct ipanic_oops_header *oops_header = (struct ipanic_oops_header *) emmc_allocate_and_read(hdr->oops_header_offset, hdr->oops_header_length); if (oops_header == NULL) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: Can't read oops header(len:%d)\n", __FUNCTION__, hdr->oops_header_length); goto error_return; } aee_oops_set_process_path(oops, oops_header->process_path); aee_oops_set_backtrace(oops, oops_header->backtrace); kfree(oops_header); if(hdr->oops_detail_length != 0) { oops->detail = emmc_allocate_and_read(hdr->oops_detail_offset, hdr->oops_detail_length); oops->detail_len = hdr->oops_detail_length; }else { #define TMPDETAILSTR "panic detail is empty" oops->detail = kstrdup(TMPDETAILSTR, GFP_KERNEL); oops->detail_len = sizeof TMPDETAILSTR; } if (oops->detail == NULL) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: read detail failed(len: %d)\n", __FUNCTION__, oops->detail_len); goto error_return; } oops->console = emmc_allocate_and_read(hdr->console_offset, hdr->console_length); oops->console_len = hdr->console_length; if (oops->console == NULL) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: read console failed(len: %d)\n", __FUNCTION__, oops->console_len); goto error_return; } /*If panic from kernel context, no user sapce info available. Shouldn't fail*/ if (0 == hdr->userspace_info_length) { oops->userspace_info = NULL; oops->userspace_info_len = 0; } else { oops->userspace_info = emmc_allocate_and_read(hdr->userspace_info_offset, hdr->userspace_info_length); oops->userspace_info_len = hdr->userspace_info_length; if (oops->userspace_info == NULL) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: read usrespace info failed\n", __FUNCTION__); goto error_return; } } oops->android_main = emmc_allocate_and_read(hdr->android_main_offset, hdr->android_main_length); oops->android_main_len = hdr->android_main_length; if (oops->android_main == NULL) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: read android_main failed\n", __FUNCTION__); goto error_return; } oops->android_radio = emmc_allocate_and_read(hdr->android_radio_offset, hdr->android_radio_length); oops->android_radio_len = hdr->android_radio_length; if (oops->android_radio == NULL) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: read android_radio failed\n", __FUNCTION__); goto error_return; } oops->android_system = emmc_allocate_and_read(hdr->android_system_offset, hdr->android_system_length); oops->android_system_len = hdr->android_system_length; if (oops->android_system == NULL) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: read android_system failed\n", __FUNCTION__); goto error_return; } xlog_printk(ANDROID_LOG_DEBUG, IPANIC_LOG_TAG, "ipanic_oops_copy return OK\n"); kfree(hdr); return oops; } else { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: kmalloc failed at header\n", __FUNCTION__); kfree(hdr); return NULL; } error_return: kfree(hdr); aee_oops_free(oops); return NULL; }
struct ipanic_header *ipanic_header_from_sd(unsigned int offset, unsigned int magic) { struct ipanic_data_header *dheader; int dt; char str[256]; size_t size = 0; struct ipanic_header *header; struct ipanic_data_header dheader_header = { .type = IPANIC_DT_HEADER, .offset = offset, .used = sizeof(struct ipanic_header), }; header = (struct ipanic_header *)ipanic_data_from_sd(&dheader_header, 0); if (IS_ERR_OR_NULL((void *)header)) { LOGD("read header failed[%ld]\n", PTR_ERR((void *)header)); header = NULL; } else if (header->magic != magic) { LOGD("no ipanic data[%x]\n", header->magic); kfree(header); header = NULL; ipanic_erase(); } else { for (dt = IPANIC_DT_HEADER + 1; dt < IPANIC_DT_RESERVED31; dt++) { dheader = &header->data_hdr[dt]; if (dheader->valid) { size += snprintf(str + size, 256 - size, "%s[%x@%x],", dheader->name, dheader->used, dheader->offset); } } LOGD("ipanic data available^v^%s^v^\n", str); } return header; } struct aee_oops *ipanic_oops_from_sd(void) { struct aee_oops *oops = NULL; struct ipanic_header *hdr = NULL; struct ipanic_data_header *dheader; char *data; int i; hdr = ipanic_header_from_sd(0, AEE_IPANIC_MAGIC); if (hdr == NULL) { return NULL; } oops = aee_oops_create(AE_DEFECT_FATAL, AE_KE, IPANIC_MODULE_TAG); if (oops == NULL) { LOGE("%s: can not allocate buffer\n", __func__); return NULL; } for (i = IPANIC_DT_HEADER + 1; i < IPANIC_DT_RESERVED31; i++) { dheader = &hdr->data_hdr[i]; if (dheader->valid == 0) { continue; } data = ipanic_data_from_sd(dheader, 1); if (data) { switch (i) { case IPANIC_DT_KERNEL_LOG: oops->console = data; oops->console_len = dheader->used; break; case IPANIC_DT_MINI_RDUMP: oops->mini_rdump = data; oops->mini_rdump_len = dheader->used; break; case IPANIC_DT_MAIN_LOG: oops->android_main = data; oops->android_main_len = dheader->used; break; case IPANIC_DT_SYSTEM_LOG: oops->android_system = data; oops->android_system_len = dheader->used; break; case IPANIC_DT_EVENTS_LOG: /* Todo .. */ break; case IPANIC_DT_RADIO_LOG: oops->android_radio = data; oops->android_radio_len = dheader->used; break; case IPANIC_DT_CURRENT_TSK: memcpy(oops->process_path, data, sizeof(struct aee_process_info)); break; case IPANIC_DT_MMPROFILE: oops->mmprofile = data; oops->mmprofile_len = dheader->used; break; default: LOGI("%s: [%d] NOT USED.\n", __func__, i); } } else { LOGW("%s: read %s failed, %x@%x\n", __func__, dheader->name, dheader->used, dheader->offset); } } return oops; } int ipanic(struct notifier_block *this, unsigned long event, void *ptr) { struct ipanic_data_header *dheader; struct kmsg_dumper dumper; ipanic_atf_log_rec_t atf_log = {ATF_LOG_SIZE, 0, 0}; int dt; int errno; struct ipanic_header *ipanic_hdr; aee_rr_rec_fiq_step(AEE_FIQ_STEP_KE_IPANIC_START); aee_rr_rec_exp_type(2); bust_spinlocks(1); spin_lock_irq(&ipanic_lock); aee_disable_api(); mrdump_mini_ke_cpu_regs(NULL); ipanic_mrdump_mini(AEE_REBOOT_MODE_KERNEL_PANIC, "kernel PANIC"); if (!ipanic_data_is_valid(IPANIC_DT_KERNEL_LOG)) { ipanic_klog_region(&dumper); errno = ipanic_data_to_sd(IPANIC_DT_KERNEL_LOG, &dumper); if (errno == -1) aee_nested_printf("$"); } ipanic_klog_region(&dumper); errno = ipanic_data_to_sd(IPANIC_DT_OOPS_LOG, &dumper); if (errno == -1) aee_nested_printf("$"); ipanic_data_to_sd(IPANIC_DT_CURRENT_TSK, 0); /* kick wdt after save the most critical infos */ ipanic_kick_wdt(); ipanic_data_to_sd(IPANIC_DT_MAIN_LOG, (void *)1); ipanic_data_to_sd(IPANIC_DT_SYSTEM_LOG, (void *)4); ipanic_data_to_sd(IPANIC_DT_EVENTS_LOG, (void *)2); ipanic_data_to_sd(IPANIC_DT_RADIO_LOG, (void *)3); aee_wdt_dump_info(); ipanic_klog_region(&dumper); ipanic_data_to_sd(IPANIC_DT_WDT_LOG, &dumper); #ifdef CONFIG_MTK_WQ_DEBUG mt_dump_wq_debugger(); #endif ipanic_klog_region(&dumper); ipanic_data_to_sd(IPANIC_DT_WQ_LOG, &dumper); ipanic_data_to_sd(IPANIC_DT_MMPROFILE, 0); ipanic_data_to_sd(IPANIC_DT_ATF_LOG, &atf_log); errno = ipanic_header_to_sd(0); if (!IS_ERR(ERR_PTR(errno))) mrdump_mini_ipanic_done(); ipanic_klog_region(&dumper); ipanic_data_to_sd(IPANIC_DT_LAST_LOG, &dumper); LOGD("ipanic done^_^"); ipanic_hdr = ipanic_header(); for (dt = IPANIC_DT_HEADER + 1; dt < IPANIC_DT_RESERVED31; dt++) { dheader = &ipanic_hdr->data_hdr[dt]; if (dheader->valid) { LOGD("%s[%x@%x],", dheader->name, dheader->used, dheader->offset); } } LOGD("^_^\n"); aee_rr_rec_fiq_step(AEE_FIQ_STEP_KE_IPANIC_DONE); return NOTIFY_DONE; } void ipanic_recursive_ke(struct pt_regs *regs, struct pt_regs *excp_regs, int cpu) { int errno; struct kmsg_dumper dumper; aee_nested_printf("minidump\n"); aee_rr_rec_exp_type(3); bust_spinlocks(1); flush_cache_all(); #ifdef __aarch64__ cpu_cache_off(); #else cpu_proc_fin(); #endif mrdump_mini_ke_cpu_regs(excp_regs); mrdump_mini_per_cpu_regs(cpu, regs); flush_cache_all(); ipanic_mrdump_mini(AEE_REBOOT_MODE_NESTED_EXCEPTION, "Nested Panic"); ipanic_data_to_sd(IPANIC_DT_CURRENT_TSK, 0); ipanic_kick_wdt(); ipanic_klog_region(&dumper); ipanic_data_to_sd(IPANIC_DT_KERNEL_LOG, &dumper); errno = ipanic_header_to_sd(0); if (!IS_ERR(ERR_PTR(errno))) mrdump_mini_ipanic_done(); if (ipanic_dt_active(IPANIC_DT_RAM_DUMP)) { aee_nested_printf("RAMDUMP.\n"); __mrdump_create_oops_dump(AEE_REBOOT_MODE_NESTED_EXCEPTION, excp_regs, "Nested Panic"); } bust_spinlocks(0); }
static struct aee_oops *mtd_ipanic_oops_copy(void) { struct mtd_ipanic_data *ctx = &mtd_drv_ctx; struct aee_oops *oops; if ((ctx->curr.magic != AEE_IPANIC_MAGIC) || (ctx->curr.version != AEE_IPANIC_PHDR_VERSION)) { return NULL; } oops = aee_oops_create(AE_DEFECT_FATAL, AE_KE, IPANIC_MODULE_TAG); if (oops != NULL) { struct ipanic_oops_header *oops_header = kzalloc(sizeof(struct ipanic_oops_header), GFP_KERNEL); if (oops_header == NULL) goto error_return; if (mtd_ipanic_block_read(ctx, ctx->curr.oops_header_offset, ctx->curr.oops_header_length, oops_header) != 0) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: mtd read header failed\n", __FUNCTION__); kfree(oops_header); goto error_return; } aee_oops_set_process_path(oops, oops_header->process_path); aee_oops_set_backtrace(oops, oops_header->backtrace); kfree(oops_header); if(ctx->curr.oops_detail_length != 0) { oops->detail = kmalloc(ctx->curr.oops_detail_length, GFP_KERNEL); oops->detail_len = ctx->curr.oops_detail_length; if (oops->detail != NULL) { if (mtd_ipanic_block_read(ctx, ctx->curr.oops_detail_offset, ctx->curr.oops_detail_length, oops->detail) != 0) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: mtd read detail failed\n", __FUNCTION__); kfree(oops->detail); goto error_return; } } }else { #define TMPDETAILSTR "panic detail is empty" oops->detail = kstrdup(TMPDETAILSTR,GFP_KERNEL); oops->detail_len = sizeof TMPDETAILSTR; } if(oops->detail == NULL) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: kmalloc failed at detail\n", __FUNCTION__); kfree(oops); return NULL; } oops->console = kmalloc(ctx->curr.console_length, GFP_KERNEL); oops->console_len = ctx->curr.console_length; if (oops->console != NULL) { if (mtd_ipanic_block_read(ctx, ctx->curr.console_offset, ctx->curr.console_length, oops->console) != 0) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: mtd read console failed\n", __FUNCTION__); kfree(oops->detail); goto error_return; } } else { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: kmalloc failed at detail\n", __FUNCTION__); kfree(oops); return NULL; } /* Android log */ oops->android_main = kmalloc(ctx->curr.android_main_length, GFP_KERNEL); oops->android_main_len = ctx->curr.android_main_length; if (oops->android_main) { if (mtd_ipanic_block_read(ctx, ctx->curr.android_main_offset, ctx->curr.android_main_length, oops->android_main) != 0) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: mtd read android_main failed\n", __FUNCTION__); kfree(oops->detail); kfree(oops->console); goto error_return; } } else { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: kmalloc failed at android_main\n", __FUNCTION__); aee_oops_free(oops); return NULL; } oops->android_radio = kmalloc(ctx->curr.android_radio_length, GFP_KERNEL); oops->android_radio_len = ctx->curr.android_radio_length; if (oops->android_radio) { if (mtd_ipanic_block_read(ctx, ctx->curr.android_radio_offset, ctx->curr.android_radio_length, oops->android_radio) != 0) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: mtd read android_radio failed\n", __FUNCTION__); kfree(oops->detail); kfree(oops->console); kfree(oops->android_main); goto error_return; } } else { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: kmalloc failed at android_radio\n", __FUNCTION__); aee_oops_free(oops); return NULL; } oops->android_system = kmalloc(ctx->curr.android_system_length, GFP_KERNEL); oops->android_system_len = ctx->curr.android_system_length; if (oops->android_system) { if (mtd_ipanic_block_read(ctx, ctx->curr.android_system_offset, ctx->curr.android_system_length, oops->android_system) != 0) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: mtd read android_system failed\n", __FUNCTION__); kfree(oops->detail); kfree(oops->console); kfree(oops->android_main); kfree(oops->android_radio); goto error_return; } } else { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: kmalloc failed at android_system\n", __FUNCTION__); aee_oops_free(oops); return NULL; } #if 0 xlog_printk(ANDROID_LOG_INFO, IPANIC_LOG_TAG, "android log length, 0x%x, 0x%x, 0x%x, 0x%x\n", oops->android_main_len,oops->android_event_len,oops->android_radio_len,oops->android_system_len); #endif /* Process dump */ oops->userspace_info = kmalloc(ctx->curr.userspace_info_length, GFP_KERNEL); oops->userspace_info_len = ctx->curr.userspace_info_length; if (oops->userspace_info) { if (mtd_ipanic_block_read(ctx, ctx->curr.userspace_info_offset, ctx->curr.userspace_info_length, oops->userspace_info) != 0) { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: mtd read usrespace info failed\n", __FUNCTION__); kfree(oops->detail); kfree(oops->console); kfree(oops->android_main); kfree(oops->android_radio); kfree(oops->userspace_info); goto error_return; } } else { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: kmalloc failed at userspace info failed\n", __FUNCTION__); aee_oops_free(oops); return NULL; } xlog_printk(ANDROID_LOG_DEBUG, IPANIC_LOG_TAG, "ipanic_oops_copy return OK\n"); return oops; } else { xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: kmalloc failed at header\n", __FUNCTION__); return NULL; } error_return: kfree(oops); memset(&ctx->curr, 0, sizeof(struct ipanic_header)); mtd_ipanic_block_erase(); return NULL; }