Merge "firmware: qcom: add enlarged qsee log support"

This commit is contained in:
qctecmdr 2020-05-12 17:25:49 -07:00 • committed by Gerrit - the friendly Code Review server
commit c3d79e3dda
3 changed files with 215 additions and 39 deletions

View file

@ -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
*/
@ -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
*/
@ -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
@ -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 {
@ -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;
@ -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,
@ -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
*/
@ -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)
{
static struct tzdbg_log_pos_t log_start = {0};
struct tzdbg_log_t *log_ptr;
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,
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)
@ -852,11 +970,19 @@ static int _disp_hyp_log_stats(size_t count)
static int _disp_qsee_log_stats(size_t count)
{
static struct tzdbg_log_pos_t log_start = {0};
if (!tzdbg.is_enlarged_buf) {
static struct tzdbg_log_pos_t log_start = {0};
return _disp_log_stats(g_qsee_log, &log_start,
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)
@ -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);
@ -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);
@ -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) {
@ -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",
@ -1062,17 +1203,17 @@ exit_dereg_bridge:
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)
@ -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,
@ -1119,7 +1261,7 @@ static int tzdbg_allocate_encrypted_log_buf(struct platform_device *pdev)
goto exit_free_tzlog;
}
pr_debug("Alloc memory for encr_tz_log, size %zu\n",
enc_qseelog_info.size);
enc_qseelog_info.size);
return 0;
@ -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__);
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.tz_version = version;
tzdbg.is_enlarged_buf = false;
return ret;
}
static void tzdbg_query_encrypted_log(void)
@ -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;
}
}
@ -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
*/
@ -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);
@ -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);

View file

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

View file

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