/** * Setup mobicore kernel log. It assumes it's running on CORE 0! * The fastcall will complain is that is not the case! */ long mobicore_log_setup(void *data) { unsigned long phys_log_buf; union fc_generic fc_log; long ret; log_pos = 0; log_buf = NULL; log_thread = NULL; log_line = NULL; log_line_len = 0; /* Sanity check for the log size */ if (log_size < PAGE_SIZE) return -EFAULT; else log_size = PAGE_ALIGN(log_size); log_line = kzalloc(LOG_LINE_SIZE, GFP_KERNEL); if (IS_ERR(log_line)) { MCDRV_DBG_ERROR("failed to allocate log line!"); return -ENOMEM; } log_thread = kthread_create(log_worker, NULL, "mobicore_log"); if (IS_ERR(log_thread)) { MCDRV_DBG_ERROR("mobicore log thread creation failed!"); ret = -EFAULT; goto mobicore_log_setup_log_line; } /* We are going to map this buffer into virtual address space in SWd. * To reduce complexity there, we use a contiguous buffer. */ log_buf = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(log_size)); if (!log_buf) { MCDRV_DBG_ERROR("Failed to get page for logger!"); ret = -ENOMEM; goto mobicore_log_setup_kthread; } phys_log_buf = virt_to_phys(log_buf); memset(&fc_log, 0, sizeof(fc_log)); fc_log.as_in.cmd = MC_FC_NWD_TRACE; fc_log.as_in.param[0] = phys_log_buf; fc_log.as_in.param[1] = log_size; MCDRV_DBG("fc_log virt=%p phys=%p ", log_buf, (void *)phys_log_buf); mc_fastcall(&fc_log); MCDRV_DBG("fc_log out ret=0x%08x", fc_log.as_out.ret); /* If the setup failed we must free the memory allocated */ if (fc_log.as_out.ret) { MCDRV_DBG_ERROR("MobiCore shared traces setup failed!"); free_pages((unsigned long)log_buf, get_order(log_size)); log_buf = NULL; ret = -EIO; goto mobicore_log_setup_kthread; } MCDRV_DBG("fc_log Logger version %u\n", log_buf->version); return 0; mobicore_log_setup_kthread: kthread_stop(log_thread); log_thread = NULL; mobicore_log_setup_log_line: kfree(log_line); log_line = NULL; return ret; }
/* * Setup MobiCore kernel log. It assumes it's running on CORE 0! * The fastcall will complain is that is not the case! */ long mobicore_log_setup(void) { unsigned long phys_log_buf; union fc_generic fc_log; struct sched_param param = { .sched_priority = 1 }; long ret; log_pos = 0; log_buf = NULL; log_thread = NULL; log_line = NULL; log_line_len = 0; /* Sanity check for the log size */ if (log_size < PAGE_SIZE) return -EFAULT; else log_size = PAGE_ALIGN(log_size); log_line = kzalloc(LOG_LINE_SIZE, GFP_KERNEL); if (IS_ERR(log_line)) { MCDRV_DBG_ERROR(mcd, "failed to allocate log line!"); return -ENOMEM; } log_thread = kthread_create(log_worker, NULL, "mobicore_log"); if (IS_ERR(log_thread)) { MCDRV_DBG_ERROR(mcd, "MobiCore log thread creation failed!"); ret = -EFAULT; goto mobicore_log_setup_log_line; } sched_setscheduler(log_thread, SCHED_IDLE, ¶m); /* * We are going to map this buffer into virtual address space in SWd. * To reduce complexity there, we use a contiguous buffer. */ log_buf = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(log_size)); if (!log_buf) { MCDRV_DBG_ERROR(mcd, "Failed to get page for logger!"); ret = -ENOMEM; goto mobicore_log_setup_kthread; } phys_log_buf = virt_to_phys(log_buf); memset(&fc_log, 0, sizeof(fc_log)); fc_log.as_in.cmd = MC_FC_NWD_TRACE; fc_log.as_in.param[0] = phys_log_buf; fc_log.as_in.param[1] = log_size; MCDRV_DBG(mcd, "fc_log virt=%p phys=%p ", log_buf, (void *)phys_log_buf); mc_fastcall(&fc_log); MCDRV_DBG(mcd, "fc_log out ret=0x%08x", fc_log.as_out.ret); /* If the setup failed we must free the memory allocated */ if (fc_log.as_out.ret) { MCDRV_DBG_ERROR(mcd, "MobiCore shared traces setup failed!"); free_pages((unsigned long)log_buf, get_order(log_size)); log_buf = NULL; ret = -EIO; goto mobicore_log_setup_kthread; } MCDRV_DBG(mcd, "fc_log Logger version %u\n", log_buf->version); return 0; mobicore_log_setup_kthread: kthread_stop(log_thread); log_thread = NULL; mobicore_log_setup_log_line: kfree(log_line); log_line = NULL; return ret; } /* * Free kernel log components. * ATTN: We can't free the log buffer because it's also in use by MobiCore and * even if the module is unloaded MobiCore is still running. */ void mobicore_log_free(void) { if (log_thread && !IS_ERR(log_thread)) { /* We don't really care what the thread returns for exit */ kthread_stop(log_thread); } kfree(log_line); }