Эх сурвалжийг харах

Merge "tz_log: Add tme logs support via tmecom interface"

qctecmdr 1 жил өмнө
parent
commit
9b5284a7ec
1 өөрчлөгдсөн 114 нэмэгдсэн , 1 устгасан
  1. 114 1
      tz_log/tz_log.c

+ 114 - 1
tz_log/tz_log.c

@@ -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)