|
@@ -3,6 +3,9 @@
|
|
|
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
|
|
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
|
*/
|
|
|
+
|
|
|
+#define pr_fmt(fmt) "%s:[%s][%d]: " fmt, KBUILD_MODNAME, __func__, __LINE__
|
|
|
+
|
|
|
#include <linux/debugfs.h>
|
|
|
#include <linux/errno.h>
|
|
|
#include <linux/delay.h>
|
|
@@ -21,6 +24,10 @@
|
|
|
#include <linux/qtee_shmbridge.h>
|
|
|
#include <linux/proc_fs.h>
|
|
|
#include <linux/version.h>
|
|
|
+#if IS_ENABLED(CONFIG_MSM_TMECOM_QMP)
|
|
|
+#include <linux/tmelog.h>
|
|
|
+#endif
|
|
|
+
|
|
|
#include "misc/qseecomi.h"
|
|
|
|
|
|
/* QSEE_LOG_BUF_SIZE = 32K */
|
|
@@ -29,6 +36,9 @@
|
|
|
/* enlarged qsee log buf size is 128K by default */
|
|
|
#define QSEE_LOG_BUF_SIZE_V2 0x20000
|
|
|
|
|
|
+/* Tme log buffer size 20K */
|
|
|
+#define TME_LOG_BUF_SIZE 0x5000
|
|
|
+
|
|
|
/* TZ Diagnostic Area legacy version number */
|
|
|
#define TZBSP_DIAG_MAJOR_VERSION_LEGACY 2
|
|
|
|
|
@@ -376,6 +386,11 @@ struct hypdbg_t {
|
|
|
uint8_t log_buf_p[];
|
|
|
};
|
|
|
|
|
|
+struct tme_log_pos {
|
|
|
+ uint32_t offset;
|
|
|
+ size_t size;
|
|
|
+};
|
|
|
+
|
|
|
/*
|
|
|
* Enumeration order for VMID's
|
|
|
*/
|
|
@@ -390,6 +405,7 @@ enum tzdbg_stats_type {
|
|
|
TZDBG_HYP_GENERAL,
|
|
|
TZDBG_HYP_LOG,
|
|
|
TZDBG_RM_LOG,
|
|
|
+ TZDBG_TME_LOG,
|
|
|
TZDBG_STATS_MAX
|
|
|
};
|
|
|
|
|
@@ -404,9 +420,11 @@ struct tzdbg {
|
|
|
void __iomem *virt_iobase;
|
|
|
void __iomem *hyp_virt_iobase;
|
|
|
void __iomem *rmlog_virt_iobase;
|
|
|
+ void __iomem *tmelog_virt_iobase;
|
|
|
struct tzdbg_t *diag_buf;
|
|
|
struct hypdbg_t *hyp_diag_buf;
|
|
|
uint8_t *rm_diag_buf;
|
|
|
+ uint8_t *tme_buf;
|
|
|
char *disp_buf;
|
|
|
int debug_tz[TZDBG_STATS_MAX];
|
|
|
struct tzdbg_stat stat[TZDBG_STATS_MAX];
|
|
@@ -459,6 +477,7 @@ static struct tzdbg tzdbg = {
|
|
|
.stat[TZDBG_HYP_GENERAL].name = "hyp_general",
|
|
|
.stat[TZDBG_HYP_LOG].name = "hyp_log",
|
|
|
.stat[TZDBG_RM_LOG].name = "rm_log",
|
|
|
+ .stat[TZDBG_TME_LOG].name = "tme_log",
|
|
|
};
|
|
|
|
|
|
static struct tzdbg_log_t *g_qsee_log;
|
|
@@ -468,6 +487,7 @@ 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 uint32_t tmecrashdump_address_offset;
|
|
|
|
|
|
static uint64_t qseelog_shmbridge_handle;
|
|
|
static struct encrypted_log_info enc_qseelog_info;
|
|
@@ -1176,6 +1196,65 @@ static int _disp_hyp_general_stats(size_t count)
|
|
|
return len;
|
|
|
}
|
|
|
|
|
|
+#if IS_ENABLED(CONFIG_MSM_TMECOM_QMP)
|
|
|
+static int _disp_tme_log_stats(size_t count)
|
|
|
+{
|
|
|
+ static struct tme_log_pos log_start = { 0 };
|
|
|
+ static bool wrap_around = { false };
|
|
|
+ uint32_t buf_size;
|
|
|
+ uint8_t *log_ptr = NULL;
|
|
|
+ uint32_t log_len = 0;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ /* Return 0 to close file in case some error in initialising step. */
|
|
|
+ if (!tzdbg.tmelog_virt_iobase || !tmecrashdump_address_offset)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* Return 0 to close the display file */
|
|
|
+ if ((log_start.size == 0x0) && wrap_around) {
|
|
|
+ wrap_around = false;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Copy TME log data to tzdbg diag buffer for the first time */
|
|
|
+ if (!wrap_around) {
|
|
|
+ if (tmelog_process_request(tmecrashdump_address_offset,
|
|
|
+ TME_LOG_BUF_SIZE, &buf_size)) {
|
|
|
+ pr_err("Read tme log failed, ret=%d, buf_size: %#x\n", ret, buf_size);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ log_start.offset = 0x0;
|
|
|
+ log_start.size = buf_size;
|
|
|
+ }
|
|
|
+
|
|
|
+ log_ptr = tzdbg.tmelog_virt_iobase;
|
|
|
+ log_len = log_start.size;
|
|
|
+ log_ptr += log_start.offset;
|
|
|
+
|
|
|
+ /* Check if we exceed the max length provided by user space */
|
|
|
+ log_len = min(min((uint32_t)count, log_len), display_buf_size);
|
|
|
+
|
|
|
+ log_start.size -= log_len;
|
|
|
+ log_start.offset += log_len;
|
|
|
+ pr_debug("log_len: %d, log_start.offset: %#x, log_start.size: %#x\n",
|
|
|
+ log_len, log_start.offset, log_start.size);
|
|
|
+
|
|
|
+ if (log_start.size)
|
|
|
+ wrap_around = true;
|
|
|
+
|
|
|
+ /* Copy TME log data to display buffer */
|
|
|
+ memcpy_fromio(tzdbg.disp_buf, log_ptr, log_len);
|
|
|
+
|
|
|
+ tzdbg.stat[TZDBG_TME_LOG].data = tzdbg.disp_buf;
|
|
|
+ return log_len;
|
|
|
+}
|
|
|
+#else
|
|
|
+static int _disp_tme_log_stats(size_t count)
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
static ssize_t tzdbg_fs_read_unencrypted(int tz_id, char __user *buf,
|
|
|
size_t count, loff_t *offp)
|
|
|
{
|
|
@@ -1232,6 +1311,10 @@ static ssize_t tzdbg_fs_read_unencrypted(int tz_id, char __user *buf,
|
|
|
len = _disp_rm_log_stats(count);
|
|
|
*offp = 0;
|
|
|
break;
|
|
|
+ case TZDBG_TME_LOG:
|
|
|
+ len = _disp_tme_log_stats(count);
|
|
|
+ *offp = 0;
|
|
|
+ break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
@@ -1298,7 +1381,7 @@ static ssize_t tzdbg_fs_read(struct file *file, char __user *buf,
|
|
|
|
|
|
if (!tzdbg.is_encrypted_log_enabled ||
|
|
|
(tz_id == TZDBG_HYP_GENERAL || tz_id == TZDBG_HYP_LOG)
|
|
|
- || tz_id == TZDBG_RM_LOG)
|
|
|
+ || tz_id == TZDBG_RM_LOG || tz_id == TZDBG_TME_LOG)
|
|
|
return tzdbg_fs_read_unencrypted(tz_id, buf, count, offp);
|
|
|
else
|
|
|
return tzdbg_fs_read_encrypted(tz_id, buf, count, offp);
|
|
@@ -1327,6 +1410,31 @@ struct proc_ops tzdbg_fops = {
|
|
|
.proc_release = tzdbg_procfs_release,
|
|
|
};
|
|
|
|
|
|
+static int tzdbg_init_tme_log(struct platform_device *pdev, void __iomem *virt_iobase)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * Tme logs are dumped in tme log ddr region but that region is not
|
|
|
+ * accessible to hlos. Instead, collect logs at tme crashdump ddr
|
|
|
+ * region with tmecom interface and then display logs reading from
|
|
|
+ * crashdump region.
|
|
|
+ */
|
|
|
+ if (of_property_read_u32((&pdev->dev)->of_node, "tmecrashdump-address-offset",
|
|
|
+ &tmecrashdump_address_offset)) {
|
|
|
+ pr_err("Tme Crashdump address offset need to be defined!\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ tzdbg.tmelog_virt_iobase =
|
|
|
+ devm_ioremap(&pdev->dev, tmecrashdump_address_offset, TME_LOG_BUF_SIZE);
|
|
|
+ if (!tzdbg.tmelog_virt_iobase) {
|
|
|
+ pr_err("ERROR: Could not ioremap: start=%#x, len=%u\n",
|
|
|
+ tmecrashdump_address_offset, TME_LOG_BUF_SIZE);
|
|
|
+ return -ENXIO;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Allocates log buffer from ION, registers the buffer at TZ
|
|
|
*/
|
|
@@ -1785,6 +1893,11 @@ static int tz_log_probe(struct platform_device *pdev)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /* Init for tme log */
|
|
|
+ ret = tzdbg_init_tme_log(pdev, virt_iobase);
|
|
|
+ if (ret < 0)
|
|
|
+ pr_warn("Tme log initialization failed!\n");
|
|
|
+
|
|
|
/* register unencrypted qsee log buffer */
|
|
|
ret = tzdbg_register_qsee_log_buf(pdev);
|
|
|
if (ret)
|