Loading drivers/firmware/qcom/tz_log.c +205 −39 Original line number Diff line number Diff line Loading @@ -23,11 +23,22 @@ /* QSEE_LOG_BUF_SIZE = 32K */ #define QSEE_LOG_BUF_SIZE 0x8000 /* MAX_ENCR_LOG_BUFF_SIZE = 36K (include header, and page align) */ #define MAX_ENCR_LOG_BUFF_SIZE (QSEE_LOG_BUF_SIZE + PAGE_SIZE) /* enlarged qsee log buf size is 128K by default */ #define QSEE_LOG_BUF_SIZE_V2 0x20000 /* TZ Diagnostic Area legacy version number */ #define TZBSP_DIAG_MAJOR_VERSION_LEGACY 2 /* TZ Diagnostic Area version number */ #define TZBSP_FVER_MAJOR_MINOR_MASK 0x3FF /* 10 bits */ #define TZBSP_FVER_MAJOR_SHIFT 22 #define TZBSP_FVER_MINOR_SHIFT 12 #define TZBSP_DIAG_MAJOR_VERSION_V9 9 #define TZBSP_DIAG_MINOR_VERSION_V2 2 /* TZ Diag Feature Version Id */ #define QCOM_SCM_FEAT_DIAG_ID 0x06 /* * Preprocessor Definitions and Constants */ Loading Loading @@ -160,6 +171,11 @@ struct tzdbg_log_pos_t { uint16_t offset; }; struct tzdbg_log_pos_v2_t { uint32_t wrap; uint32_t offset; }; /* * Log ring buffer */ Loading @@ -169,6 +185,12 @@ struct tzdbg_log_t { uint8_t log_buf[]; }; struct tzdbg_log_v2_t { struct tzdbg_log_pos_v2_t log_pos; /* open ended array to the end of the 4K IMEM buffer */ uint8_t log_buf[]; }; /* * Diagnostic Table * Note: This is the reference data structure for tz diagnostic table Loading Loading @@ -309,6 +331,7 @@ struct tzdbg { bool is_hyplog_enabled; uint32_t tz_version; bool is_encrypted_log_enabled; bool is_enlarged_buf; }; struct tzbsp_encr_log_t { Loading Loading @@ -350,9 +373,11 @@ static struct tzdbg tzdbg = { }; static struct tzdbg_log_t *g_qsee_log; static struct tzdbg_log_v2_t *g_qsee_log_v2; static dma_addr_t coh_pmem; static uint32_t debug_rw_buf_size; static uint32_t display_buf_size; static uint32_t qseelog_buf_size; static phys_addr_t disp_buf_paddr; static uint64_t qseelog_shmbridge_handle; Loading Loading @@ -634,6 +659,83 @@ static int _disp_log_stats(struct tzdbg_log_t *log, log_start->offset = (log->log_pos.offset + 1) % log_len; } pr_debug("diag_buf wrap = %u, offset = %u\n", log->log_pos.wrap, log->log_pos.offset); while (log_start->offset == log->log_pos.offset) { /* * No data in ring buffer, * so we'll hang around until something happens */ unsigned long t = msleep_interruptible(50); if (t != 0) { /* Some event woke us up, so let's quit */ return 0; } if (buf_idx == TZDBG_LOG) memcpy_fromio((void *)tzdbg.diag_buf, tzdbg.virt_iobase, debug_rw_buf_size); } max_len = (count > debug_rw_buf_size) ? debug_rw_buf_size : count; pr_debug("diag_buf wrap = %u, offset = %u\n", log->log_pos.wrap, log->log_pos.offset); /* * Read from ring buff while there is data and space in return buff */ while ((log_start->offset != log->log_pos.offset) && (len < max_len)) { tzdbg.disp_buf[i++] = log->log_buf[log_start->offset]; log_start->offset = (log_start->offset + 1) % log_len; if (log_start->offset == 0) ++log_start->wrap; ++len; } /* * return buffer to caller */ tzdbg.stat[buf_idx].data = tzdbg.disp_buf; return len; } static int _disp_log_stats_v2(struct tzdbg_log_v2_t *log, struct tzdbg_log_pos_v2_t *log_start, uint32_t log_len, size_t count, uint32_t buf_idx) { uint32_t wrap_start; uint32_t wrap_end; uint32_t wrap_cnt; int max_len; int len = 0; int i = 0; wrap_start = log_start->wrap; wrap_end = log->log_pos.wrap; /* Calculate difference in # of buffer wrap-arounds */ if (wrap_end >= wrap_start) wrap_cnt = wrap_end - wrap_start; else { /* wrap counter has wrapped around, invalidate start position */ wrap_cnt = 2; } if (wrap_cnt > 1) { /* end position has wrapped around more than once, */ /* current start no longer valid */ log_start->wrap = log->log_pos.wrap - 1; log_start->offset = (log->log_pos.offset + 1) % log_len; } else if ((wrap_cnt == 1) && (log->log_pos.offset > log_start->offset)) { /* end position has overwritten start */ log_start->offset = (log->log_pos.offset + 1) % log_len; } pr_debug("diag_buf wrap = %u, offset = %u\n", log->log_pos.wrap, log->log_pos.offset); while (log_start->offset == log->log_pos.offset) { /* * No data in ring buffer, Loading @@ -654,6 +756,9 @@ static int _disp_log_stats(struct tzdbg_log_t *log, max_len = (count > debug_rw_buf_size) ? debug_rw_buf_size : count; pr_debug("diag_buf wrap = %u, offset = %u\n", log->log_pos.wrap, log->log_pos.offset); /* * Read from ring buff while there is data and space in return buff */ Loading Loading @@ -827,15 +932,28 @@ static int _disp_encrpted_log_stats(struct encrypted_log_info *enc_log_info, static int _disp_tz_log_stats(size_t count) { if (!tzdbg.is_enlarged_buf) { static struct tzdbg_log_pos_t log_start = {0}; struct tzdbg_log_t *log_ptr; log_ptr = (struct tzdbg_log_t *)((unsigned char *)tzdbg.diag_buf + log_ptr = (struct tzdbg_log_t *)( (unsigned char *)tzdbg.diag_buf + tzdbg.diag_buf->ring_off - offsetof(struct tzdbg_log_t, log_buf)); return _disp_log_stats(log_ptr, &log_start, tzdbg.diag_buf->ring_len, count, TZDBG_LOG); } else { static struct tzdbg_log_pos_v2_t log_start_v2 = {0}; struct tzdbg_log_v2_t *log_v2_ptr; log_v2_ptr = (struct tzdbg_log_v2_t *)( (unsigned char *)tzdbg.diag_buf + tzdbg.diag_buf->ring_off - offsetof(struct tzdbg_log_v2_t, log_buf)); return _disp_log_stats_v2(log_v2_ptr, &log_start_v2, tzdbg.diag_buf->ring_len, count, TZDBG_LOG); } } static int _disp_hyp_log_stats(size_t count) Loading @@ -852,11 +970,19 @@ static int _disp_hyp_log_stats(size_t count) static int _disp_qsee_log_stats(size_t count) { if (!tzdbg.is_enlarged_buf) { static struct tzdbg_log_pos_t log_start = {0}; return _disp_log_stats(g_qsee_log, &log_start, QSEE_LOG_BUF_SIZE - sizeof(struct tzdbg_log_pos_t), count, TZDBG_QSEE_LOG); } else { static struct tzdbg_log_pos_v2_t log_start_v2 = {0}; return _disp_log_stats_v2(g_qsee_log_v2, &log_start_v2, QSEE_LOG_BUF_SIZE - sizeof(struct tzdbg_log_pos_v2_t), count, TZDBG_QSEE_LOG); } } static int _disp_hyp_general_stats(size_t count) Loading Loading @@ -903,7 +1029,8 @@ static ssize_t tzdbgfs_read_unencrypted(struct file *file, char __user *buf, if (tz_id == TZDBG_BOOT || tz_id == TZDBG_RESET || tz_id == TZDBG_INTERRUPT || tz_id == TZDBG_GENERAL || tz_id == TZDBG_VMID || tz_id == TZDBG_LOG) tz_id == TZDBG_VMID || tz_id == TZDBG_LOG || tz_id == TZDBG_QSEE_LOG) memcpy_fromio((void *)tzdbg.diag_buf, tzdbg.virt_iobase, debug_rw_buf_size); Loading Loading @@ -966,7 +1093,7 @@ static ssize_t tzdbgfs_read_encrypted(struct file *file, char __user *buf, int tz_id = *(int *)(file->private_data); struct tzdbg_stat *stat = &(tzdbg.stat[tz_id]); pr_debug("tz_id = %d\n", tz_id); pr_debug("%s: tz_id = %d\n", __func__, tz_id); if (tz_id >= TZDBG_STATS_MAX) { pr_err("invalid encrypted log id %d\n", tz_id); Loading Loading @@ -1023,20 +1150,31 @@ static const struct file_operations tzdbg_fops = { */ static int tzdbg_register_qsee_log_buf(struct platform_device *pdev) { size_t len = QSEE_LOG_BUF_SIZE; int ret = 0; void *buf = NULL; uint32_t ns_vmids[] = {VMID_HLOS}; uint32_t ns_vm_perms[] = {PERM_READ | PERM_WRITE}; uint32_t ns_vm_nums = 1; buf = dma_alloc_coherent(&pdev->dev, len, &coh_pmem, GFP_KERNEL); if (tzdbg.is_enlarged_buf) { if (of_property_read_u32((&pdev->dev)->of_node, "qseelog-buf-size-v2", &qseelog_buf_size)) { pr_debug("Enlarged qseelog buf size isn't defined\n"); qseelog_buf_size = QSEE_LOG_BUF_SIZE_V2; } } else { qseelog_buf_size = QSEE_LOG_BUF_SIZE; } pr_debug("qseelog buf size is 0x%x\n", qseelog_buf_size); buf = dma_alloc_coherent(&pdev->dev, qseelog_buf_size, &coh_pmem, GFP_KERNEL); if (buf == NULL) return -ENOMEM; if (!tzdbg.is_encrypted_log_enabled) { ret = qtee_shmbridge_register(coh_pmem, len, ns_vmids, ns_vm_perms, ns_vm_nums, qseelog_buf_size, ns_vmids, ns_vm_perms, ns_vm_nums, PERM_READ | PERM_WRITE, &qseelog_shmbridge_handle); if (ret) { Loading @@ -1048,7 +1186,10 @@ static int tzdbg_register_qsee_log_buf(struct platform_device *pdev) g_qsee_log = (struct tzdbg_log_t *)buf; g_qsee_log->log_pos.wrap = g_qsee_log->log_pos.offset = 0; ret = qcom_scm_register_qsee_log_buf(coh_pmem, len); g_qsee_log_v2 = (struct tzdbg_log_v2_t *)buf; g_qsee_log_v2->log_pos.wrap = g_qsee_log_v2->log_pos.offset = 0; ret = qcom_scm_register_qsee_log_buf(coh_pmem, qseelog_buf_size); if (ret != QSEOS_RESULT_SUCCESS) { pr_err( "%s: scm_call to register log buf failed, resp result =%lld\n", Loading @@ -1062,17 +1203,17 @@ static int tzdbg_register_qsee_log_buf(struct platform_device *pdev) if (!tzdbg.is_encrypted_log_enabled) qtee_shmbridge_deregister(qseelog_shmbridge_handle); exit_free_mem: dma_free_coherent(&pdev->dev, len, (void *)g_qsee_log, coh_pmem); dma_free_coherent(&pdev->dev, qseelog_buf_size, (void *)g_qsee_log, coh_pmem); return ret; } static void tzdbg_free_qsee_log_buf(struct platform_device *pdev) { size_t len = QSEE_LOG_BUF_SIZE; if (!tzdbg.is_encrypted_log_enabled) qtee_shmbridge_deregister(qseelog_shmbridge_handle); dma_free_coherent(&pdev->dev, len, (void *)g_qsee_log, coh_pmem); dma_free_coherent(&pdev->dev, qseelog_buf_size, (void *)g_qsee_log, coh_pmem); } static int tzdbg_allocate_encrypted_log_buf(struct platform_device *pdev) Loading @@ -1085,7 +1226,8 @@ static int tzdbg_allocate_encrypted_log_buf(struct platform_device *pdev) if (!tzdbg.is_encrypted_log_enabled) return 0; enc_qseelog_info.size = MAX_ENCR_LOG_BUFF_SIZE; /* max encrypted qsee log buf zize (include header, and page align) */ enc_qseelog_info.size = qseelog_buf_size + PAGE_SIZE; enc_qseelog_info.vaddr = dma_alloc_coherent(&pdev->dev, enc_qseelog_info.size, Loading Loading @@ -1233,18 +1375,36 @@ static int __update_hypdbg_base(struct platform_device *pdev, return 0; } static void tzdbg_get_tz_version(void) static int tzdbg_get_tz_version(void) { u64 version; int ret = 0; ret = qcom_scm_get_tz_log_feat_id(&version); if (ret) if (ret) { pr_err("%s: scm_call to get tz version failed\n", __func__); else return ret; } tzdbg.tz_version = version; ret = qcom_scm_get_tz_feat_id_version(QCOM_SCM_FEAT_DIAG_ID, &version); if (ret) { pr_err("%s: scm_call to get tz diag version failed, ret = %d\n", __func__, ret); return ret; } pr_warn("tz diag version is %x\n", version); if ( (((version >> TZBSP_FVER_MAJOR_SHIFT) & TZBSP_FVER_MAJOR_MINOR_MASK) == TZBSP_DIAG_MAJOR_VERSION_V9) && (((version >> TZBSP_FVER_MINOR_SHIFT) & TZBSP_FVER_MAJOR_MINOR_MASK) == TZBSP_DIAG_MINOR_VERSION_V2)) tzdbg.is_enlarged_buf = true; else tzdbg.is_enlarged_buf = false; return ret; } static void tzdbg_query_encrypted_log(void) Loading @@ -1257,7 +1417,7 @@ static void tzdbg_query_encrypted_log(void) pr_err("scm_call QUERY_ENCR_LOG_FEATURE failed ret %d\n", ret); tzdbg.is_encrypted_log_enabled = false; } else { pr_info("encrypted qseelog enabled is %d\n", enabled); pr_warn("encrypted qseelog enabled is %d\n", enabled); tzdbg.is_encrypted_log_enabled = enabled; } } Loading @@ -1273,6 +1433,10 @@ static int tz_log_probe(struct platform_device *pdev) uint32_t *ptr = NULL; int ret = 0; ret = tzdbg_get_tz_version(); if (ret) return ret; /* * Get address that stores the physical location diagnostic data */ Loading Loading @@ -1346,19 +1510,10 @@ static int tz_log_probe(struct platform_device *pdev) tzdbg.diag_buf = (struct tzdbg_t *)ptr; } /* allocate display_buf */ display_buf_size = QSEE_LOG_BUF_SIZE * 4; tzdbg.disp_buf = dma_alloc_coherent(&pdev->dev, display_buf_size, &disp_buf_paddr, GFP_KERNEL); if (tzdbg.disp_buf == NULL) { ret = -ENOMEM; goto exit_free_diag_buf; } /* register unencrypted qsee log buffer */ ret = tzdbg_register_qsee_log_buf(pdev); if (ret) goto exit_free_disp_buf; goto exit_free_diag_buf; /* allocate encrypted qsee and tz log buffer */ ret = tzdbg_allocate_encrypted_log_buf(pdev); Loading @@ -1369,19 +1524,30 @@ static int tz_log_probe(struct platform_device *pdev) goto exit_free_qsee_log_buf; } tzdbg_get_tz_version(); /* allocate display_buf */ if (UINT_MAX/4 < qseelog_buf_size) { pr_err("display_buf_size integer overflow\n"); goto exit_free_qsee_log_buf; } display_buf_size = qseelog_buf_size * 4; tzdbg.disp_buf = dma_alloc_coherent(&pdev->dev, display_buf_size, &disp_buf_paddr, GFP_KERNEL); if (tzdbg.disp_buf == NULL) { ret = -ENOMEM; goto exit_free_encr_log_buf; } if (tzdbgfs_init(pdev)) goto exit_free_encr_log_buf; goto exit_free_disp_buf; return 0; exit_free_disp_buf: dma_free_coherent(&pdev->dev, display_buf_size, (void *)tzdbg.disp_buf, disp_buf_paddr); exit_free_encr_log_buf: tzdbg_free_encrypted_log_buf(pdev); exit_free_qsee_log_buf: tzdbg_free_qsee_log_buf(pdev); exit_free_disp_buf: dma_free_coherent(&pdev->dev, display_buf_size, (void *)tzdbg.disp_buf, disp_buf_paddr); exit_free_diag_buf: if (!tzdbg.is_encrypted_log_enabled) kfree(tzdbg.diag_buf); Loading drivers/firmware/qcom_scm.c +7 −0 Original line number Diff line number Diff line Loading @@ -913,6 +913,13 @@ int qcom_scm_get_tz_log_feat_id(u64 *version) } EXPORT_SYMBOL(qcom_scm_get_tz_log_feat_id); int qcom_scm_get_tz_feat_id_version(u64 feat_id, u64 *version) { return __qcom_scm_get_feat_version(__scm->dev, feat_id, version); } EXPORT_SYMBOL(qcom_scm_get_tz_feat_id_version); int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len) { return __qcom_scm_register_qsee_log_buf(__scm->dev, buf, len); Loading include/linux/qcom_scm.h +3 −0 Original line number Diff line number Diff line Loading @@ -183,6 +183,7 @@ extern int qcom_scm_camera_protect_phy_lanes(bool protect, u64 regmask); extern int qcom_scm_tsens_reinit(int *tsens_ret); extern int qcom_scm_ice_restore_cfg(void); extern int qcom_scm_get_tz_log_feat_id(u64 *version); extern int qcom_scm_get_tz_feat_id_version(u64 feat_id, u64 *version); extern int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len); extern int qcom_scm_query_encrypted_log_feature(u64 *enabled); extern int qcom_scm_request_encrypted_log(phys_addr_t buf, size_t len, Loading Loading @@ -346,6 +347,8 @@ static inline int qcom_scm_tsens_reinit(int *tsens_ret) static inline int qcom_scm_ice_restore_cfg(void) { return -ENODEV; } static inline int qcom_scm_get_tz_log_feat_id(u64 *version) { return -ENODEV; } static inline int qcom_scm_get_tz_feat_id_version(u64 feat_id, u64 *version) { return -ENODEV; } static inline int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len) { return -ENODEV; } static inline int qcom_scm_query_encrypted_log_feature(u64 *enabled) Loading Loading
drivers/firmware/qcom/tz_log.c +205 −39 Original line number Diff line number Diff line Loading @@ -23,11 +23,22 @@ /* QSEE_LOG_BUF_SIZE = 32K */ #define QSEE_LOG_BUF_SIZE 0x8000 /* MAX_ENCR_LOG_BUFF_SIZE = 36K (include header, and page align) */ #define MAX_ENCR_LOG_BUFF_SIZE (QSEE_LOG_BUF_SIZE + PAGE_SIZE) /* enlarged qsee log buf size is 128K by default */ #define QSEE_LOG_BUF_SIZE_V2 0x20000 /* TZ Diagnostic Area legacy version number */ #define TZBSP_DIAG_MAJOR_VERSION_LEGACY 2 /* TZ Diagnostic Area version number */ #define TZBSP_FVER_MAJOR_MINOR_MASK 0x3FF /* 10 bits */ #define TZBSP_FVER_MAJOR_SHIFT 22 #define TZBSP_FVER_MINOR_SHIFT 12 #define TZBSP_DIAG_MAJOR_VERSION_V9 9 #define TZBSP_DIAG_MINOR_VERSION_V2 2 /* TZ Diag Feature Version Id */ #define QCOM_SCM_FEAT_DIAG_ID 0x06 /* * Preprocessor Definitions and Constants */ Loading Loading @@ -160,6 +171,11 @@ struct tzdbg_log_pos_t { uint16_t offset; }; struct tzdbg_log_pos_v2_t { uint32_t wrap; uint32_t offset; }; /* * Log ring buffer */ Loading @@ -169,6 +185,12 @@ struct tzdbg_log_t { uint8_t log_buf[]; }; struct tzdbg_log_v2_t { struct tzdbg_log_pos_v2_t log_pos; /* open ended array to the end of the 4K IMEM buffer */ uint8_t log_buf[]; }; /* * Diagnostic Table * Note: This is the reference data structure for tz diagnostic table Loading Loading @@ -309,6 +331,7 @@ struct tzdbg { bool is_hyplog_enabled; uint32_t tz_version; bool is_encrypted_log_enabled; bool is_enlarged_buf; }; struct tzbsp_encr_log_t { Loading Loading @@ -350,9 +373,11 @@ static struct tzdbg tzdbg = { }; static struct tzdbg_log_t *g_qsee_log; static struct tzdbg_log_v2_t *g_qsee_log_v2; static dma_addr_t coh_pmem; static uint32_t debug_rw_buf_size; static uint32_t display_buf_size; static uint32_t qseelog_buf_size; static phys_addr_t disp_buf_paddr; static uint64_t qseelog_shmbridge_handle; Loading Loading @@ -634,6 +659,83 @@ static int _disp_log_stats(struct tzdbg_log_t *log, log_start->offset = (log->log_pos.offset + 1) % log_len; } pr_debug("diag_buf wrap = %u, offset = %u\n", log->log_pos.wrap, log->log_pos.offset); while (log_start->offset == log->log_pos.offset) { /* * No data in ring buffer, * so we'll hang around until something happens */ unsigned long t = msleep_interruptible(50); if (t != 0) { /* Some event woke us up, so let's quit */ return 0; } if (buf_idx == TZDBG_LOG) memcpy_fromio((void *)tzdbg.diag_buf, tzdbg.virt_iobase, debug_rw_buf_size); } max_len = (count > debug_rw_buf_size) ? debug_rw_buf_size : count; pr_debug("diag_buf wrap = %u, offset = %u\n", log->log_pos.wrap, log->log_pos.offset); /* * Read from ring buff while there is data and space in return buff */ while ((log_start->offset != log->log_pos.offset) && (len < max_len)) { tzdbg.disp_buf[i++] = log->log_buf[log_start->offset]; log_start->offset = (log_start->offset + 1) % log_len; if (log_start->offset == 0) ++log_start->wrap; ++len; } /* * return buffer to caller */ tzdbg.stat[buf_idx].data = tzdbg.disp_buf; return len; } static int _disp_log_stats_v2(struct tzdbg_log_v2_t *log, struct tzdbg_log_pos_v2_t *log_start, uint32_t log_len, size_t count, uint32_t buf_idx) { uint32_t wrap_start; uint32_t wrap_end; uint32_t wrap_cnt; int max_len; int len = 0; int i = 0; wrap_start = log_start->wrap; wrap_end = log->log_pos.wrap; /* Calculate difference in # of buffer wrap-arounds */ if (wrap_end >= wrap_start) wrap_cnt = wrap_end - wrap_start; else { /* wrap counter has wrapped around, invalidate start position */ wrap_cnt = 2; } if (wrap_cnt > 1) { /* end position has wrapped around more than once, */ /* current start no longer valid */ log_start->wrap = log->log_pos.wrap - 1; log_start->offset = (log->log_pos.offset + 1) % log_len; } else if ((wrap_cnt == 1) && (log->log_pos.offset > log_start->offset)) { /* end position has overwritten start */ log_start->offset = (log->log_pos.offset + 1) % log_len; } pr_debug("diag_buf wrap = %u, offset = %u\n", log->log_pos.wrap, log->log_pos.offset); while (log_start->offset == log->log_pos.offset) { /* * No data in ring buffer, Loading @@ -654,6 +756,9 @@ static int _disp_log_stats(struct tzdbg_log_t *log, max_len = (count > debug_rw_buf_size) ? debug_rw_buf_size : count; pr_debug("diag_buf wrap = %u, offset = %u\n", log->log_pos.wrap, log->log_pos.offset); /* * Read from ring buff while there is data and space in return buff */ Loading Loading @@ -827,15 +932,28 @@ static int _disp_encrpted_log_stats(struct encrypted_log_info *enc_log_info, static int _disp_tz_log_stats(size_t count) { if (!tzdbg.is_enlarged_buf) { static struct tzdbg_log_pos_t log_start = {0}; struct tzdbg_log_t *log_ptr; log_ptr = (struct tzdbg_log_t *)((unsigned char *)tzdbg.diag_buf + log_ptr = (struct tzdbg_log_t *)( (unsigned char *)tzdbg.diag_buf + tzdbg.diag_buf->ring_off - offsetof(struct tzdbg_log_t, log_buf)); return _disp_log_stats(log_ptr, &log_start, tzdbg.diag_buf->ring_len, count, TZDBG_LOG); } else { static struct tzdbg_log_pos_v2_t log_start_v2 = {0}; struct tzdbg_log_v2_t *log_v2_ptr; log_v2_ptr = (struct tzdbg_log_v2_t *)( (unsigned char *)tzdbg.diag_buf + tzdbg.diag_buf->ring_off - offsetof(struct tzdbg_log_v2_t, log_buf)); return _disp_log_stats_v2(log_v2_ptr, &log_start_v2, tzdbg.diag_buf->ring_len, count, TZDBG_LOG); } } static int _disp_hyp_log_stats(size_t count) Loading @@ -852,11 +970,19 @@ static int _disp_hyp_log_stats(size_t count) static int _disp_qsee_log_stats(size_t count) { if (!tzdbg.is_enlarged_buf) { static struct tzdbg_log_pos_t log_start = {0}; return _disp_log_stats(g_qsee_log, &log_start, QSEE_LOG_BUF_SIZE - sizeof(struct tzdbg_log_pos_t), count, TZDBG_QSEE_LOG); } else { static struct tzdbg_log_pos_v2_t log_start_v2 = {0}; return _disp_log_stats_v2(g_qsee_log_v2, &log_start_v2, QSEE_LOG_BUF_SIZE - sizeof(struct tzdbg_log_pos_v2_t), count, TZDBG_QSEE_LOG); } } static int _disp_hyp_general_stats(size_t count) Loading Loading @@ -903,7 +1029,8 @@ static ssize_t tzdbgfs_read_unencrypted(struct file *file, char __user *buf, if (tz_id == TZDBG_BOOT || tz_id == TZDBG_RESET || tz_id == TZDBG_INTERRUPT || tz_id == TZDBG_GENERAL || tz_id == TZDBG_VMID || tz_id == TZDBG_LOG) tz_id == TZDBG_VMID || tz_id == TZDBG_LOG || tz_id == TZDBG_QSEE_LOG) memcpy_fromio((void *)tzdbg.diag_buf, tzdbg.virt_iobase, debug_rw_buf_size); Loading Loading @@ -966,7 +1093,7 @@ static ssize_t tzdbgfs_read_encrypted(struct file *file, char __user *buf, int tz_id = *(int *)(file->private_data); struct tzdbg_stat *stat = &(tzdbg.stat[tz_id]); pr_debug("tz_id = %d\n", tz_id); pr_debug("%s: tz_id = %d\n", __func__, tz_id); if (tz_id >= TZDBG_STATS_MAX) { pr_err("invalid encrypted log id %d\n", tz_id); Loading Loading @@ -1023,20 +1150,31 @@ static const struct file_operations tzdbg_fops = { */ static int tzdbg_register_qsee_log_buf(struct platform_device *pdev) { size_t len = QSEE_LOG_BUF_SIZE; int ret = 0; void *buf = NULL; uint32_t ns_vmids[] = {VMID_HLOS}; uint32_t ns_vm_perms[] = {PERM_READ | PERM_WRITE}; uint32_t ns_vm_nums = 1; buf = dma_alloc_coherent(&pdev->dev, len, &coh_pmem, GFP_KERNEL); if (tzdbg.is_enlarged_buf) { if (of_property_read_u32((&pdev->dev)->of_node, "qseelog-buf-size-v2", &qseelog_buf_size)) { pr_debug("Enlarged qseelog buf size isn't defined\n"); qseelog_buf_size = QSEE_LOG_BUF_SIZE_V2; } } else { qseelog_buf_size = QSEE_LOG_BUF_SIZE; } pr_debug("qseelog buf size is 0x%x\n", qseelog_buf_size); buf = dma_alloc_coherent(&pdev->dev, qseelog_buf_size, &coh_pmem, GFP_KERNEL); if (buf == NULL) return -ENOMEM; if (!tzdbg.is_encrypted_log_enabled) { ret = qtee_shmbridge_register(coh_pmem, len, ns_vmids, ns_vm_perms, ns_vm_nums, qseelog_buf_size, ns_vmids, ns_vm_perms, ns_vm_nums, PERM_READ | PERM_WRITE, &qseelog_shmbridge_handle); if (ret) { Loading @@ -1048,7 +1186,10 @@ static int tzdbg_register_qsee_log_buf(struct platform_device *pdev) g_qsee_log = (struct tzdbg_log_t *)buf; g_qsee_log->log_pos.wrap = g_qsee_log->log_pos.offset = 0; ret = qcom_scm_register_qsee_log_buf(coh_pmem, len); g_qsee_log_v2 = (struct tzdbg_log_v2_t *)buf; g_qsee_log_v2->log_pos.wrap = g_qsee_log_v2->log_pos.offset = 0; ret = qcom_scm_register_qsee_log_buf(coh_pmem, qseelog_buf_size); if (ret != QSEOS_RESULT_SUCCESS) { pr_err( "%s: scm_call to register log buf failed, resp result =%lld\n", Loading @@ -1062,17 +1203,17 @@ static int tzdbg_register_qsee_log_buf(struct platform_device *pdev) if (!tzdbg.is_encrypted_log_enabled) qtee_shmbridge_deregister(qseelog_shmbridge_handle); exit_free_mem: dma_free_coherent(&pdev->dev, len, (void *)g_qsee_log, coh_pmem); dma_free_coherent(&pdev->dev, qseelog_buf_size, (void *)g_qsee_log, coh_pmem); return ret; } static void tzdbg_free_qsee_log_buf(struct platform_device *pdev) { size_t len = QSEE_LOG_BUF_SIZE; if (!tzdbg.is_encrypted_log_enabled) qtee_shmbridge_deregister(qseelog_shmbridge_handle); dma_free_coherent(&pdev->dev, len, (void *)g_qsee_log, coh_pmem); dma_free_coherent(&pdev->dev, qseelog_buf_size, (void *)g_qsee_log, coh_pmem); } static int tzdbg_allocate_encrypted_log_buf(struct platform_device *pdev) Loading @@ -1085,7 +1226,8 @@ static int tzdbg_allocate_encrypted_log_buf(struct platform_device *pdev) if (!tzdbg.is_encrypted_log_enabled) return 0; enc_qseelog_info.size = MAX_ENCR_LOG_BUFF_SIZE; /* max encrypted qsee log buf zize (include header, and page align) */ enc_qseelog_info.size = qseelog_buf_size + PAGE_SIZE; enc_qseelog_info.vaddr = dma_alloc_coherent(&pdev->dev, enc_qseelog_info.size, Loading Loading @@ -1233,18 +1375,36 @@ static int __update_hypdbg_base(struct platform_device *pdev, return 0; } static void tzdbg_get_tz_version(void) static int tzdbg_get_tz_version(void) { u64 version; int ret = 0; ret = qcom_scm_get_tz_log_feat_id(&version); if (ret) if (ret) { pr_err("%s: scm_call to get tz version failed\n", __func__); else return ret; } tzdbg.tz_version = version; ret = qcom_scm_get_tz_feat_id_version(QCOM_SCM_FEAT_DIAG_ID, &version); if (ret) { pr_err("%s: scm_call to get tz diag version failed, ret = %d\n", __func__, ret); return ret; } pr_warn("tz diag version is %x\n", version); if ( (((version >> TZBSP_FVER_MAJOR_SHIFT) & TZBSP_FVER_MAJOR_MINOR_MASK) == TZBSP_DIAG_MAJOR_VERSION_V9) && (((version >> TZBSP_FVER_MINOR_SHIFT) & TZBSP_FVER_MAJOR_MINOR_MASK) == TZBSP_DIAG_MINOR_VERSION_V2)) tzdbg.is_enlarged_buf = true; else tzdbg.is_enlarged_buf = false; return ret; } static void tzdbg_query_encrypted_log(void) Loading @@ -1257,7 +1417,7 @@ static void tzdbg_query_encrypted_log(void) pr_err("scm_call QUERY_ENCR_LOG_FEATURE failed ret %d\n", ret); tzdbg.is_encrypted_log_enabled = false; } else { pr_info("encrypted qseelog enabled is %d\n", enabled); pr_warn("encrypted qseelog enabled is %d\n", enabled); tzdbg.is_encrypted_log_enabled = enabled; } } Loading @@ -1273,6 +1433,10 @@ static int tz_log_probe(struct platform_device *pdev) uint32_t *ptr = NULL; int ret = 0; ret = tzdbg_get_tz_version(); if (ret) return ret; /* * Get address that stores the physical location diagnostic data */ Loading Loading @@ -1346,19 +1510,10 @@ static int tz_log_probe(struct platform_device *pdev) tzdbg.diag_buf = (struct tzdbg_t *)ptr; } /* allocate display_buf */ display_buf_size = QSEE_LOG_BUF_SIZE * 4; tzdbg.disp_buf = dma_alloc_coherent(&pdev->dev, display_buf_size, &disp_buf_paddr, GFP_KERNEL); if (tzdbg.disp_buf == NULL) { ret = -ENOMEM; goto exit_free_diag_buf; } /* register unencrypted qsee log buffer */ ret = tzdbg_register_qsee_log_buf(pdev); if (ret) goto exit_free_disp_buf; goto exit_free_diag_buf; /* allocate encrypted qsee and tz log buffer */ ret = tzdbg_allocate_encrypted_log_buf(pdev); Loading @@ -1369,19 +1524,30 @@ static int tz_log_probe(struct platform_device *pdev) goto exit_free_qsee_log_buf; } tzdbg_get_tz_version(); /* allocate display_buf */ if (UINT_MAX/4 < qseelog_buf_size) { pr_err("display_buf_size integer overflow\n"); goto exit_free_qsee_log_buf; } display_buf_size = qseelog_buf_size * 4; tzdbg.disp_buf = dma_alloc_coherent(&pdev->dev, display_buf_size, &disp_buf_paddr, GFP_KERNEL); if (tzdbg.disp_buf == NULL) { ret = -ENOMEM; goto exit_free_encr_log_buf; } if (tzdbgfs_init(pdev)) goto exit_free_encr_log_buf; goto exit_free_disp_buf; return 0; exit_free_disp_buf: dma_free_coherent(&pdev->dev, display_buf_size, (void *)tzdbg.disp_buf, disp_buf_paddr); exit_free_encr_log_buf: tzdbg_free_encrypted_log_buf(pdev); exit_free_qsee_log_buf: tzdbg_free_qsee_log_buf(pdev); exit_free_disp_buf: dma_free_coherent(&pdev->dev, display_buf_size, (void *)tzdbg.disp_buf, disp_buf_paddr); exit_free_diag_buf: if (!tzdbg.is_encrypted_log_enabled) kfree(tzdbg.diag_buf); Loading
drivers/firmware/qcom_scm.c +7 −0 Original line number Diff line number Diff line Loading @@ -913,6 +913,13 @@ int qcom_scm_get_tz_log_feat_id(u64 *version) } EXPORT_SYMBOL(qcom_scm_get_tz_log_feat_id); int qcom_scm_get_tz_feat_id_version(u64 feat_id, u64 *version) { return __qcom_scm_get_feat_version(__scm->dev, feat_id, version); } EXPORT_SYMBOL(qcom_scm_get_tz_feat_id_version); int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len) { return __qcom_scm_register_qsee_log_buf(__scm->dev, buf, len); Loading
include/linux/qcom_scm.h +3 −0 Original line number Diff line number Diff line Loading @@ -183,6 +183,7 @@ extern int qcom_scm_camera_protect_phy_lanes(bool protect, u64 regmask); extern int qcom_scm_tsens_reinit(int *tsens_ret); extern int qcom_scm_ice_restore_cfg(void); extern int qcom_scm_get_tz_log_feat_id(u64 *version); extern int qcom_scm_get_tz_feat_id_version(u64 feat_id, u64 *version); extern int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len); extern int qcom_scm_query_encrypted_log_feature(u64 *enabled); extern int qcom_scm_request_encrypted_log(phys_addr_t buf, size_t len, Loading Loading @@ -346,6 +347,8 @@ static inline int qcom_scm_tsens_reinit(int *tsens_ret) static inline int qcom_scm_ice_restore_cfg(void) { return -ENODEV; } static inline int qcom_scm_get_tz_log_feat_id(u64 *version) { return -ENODEV; } static inline int qcom_scm_get_tz_feat_id_version(u64 feat_id, u64 *version) { return -ENODEV; } static inline int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len) { return -ENODEV; } static inline int qcom_scm_query_encrypted_log_feature(u64 *enabled) Loading