From 6dcdadd65d7e4aa8e5399458bfc6b16f24fe7b99 Mon Sep 17 00:00:00 2001 From: "Isaac J. Manjarres" Date: Wed, 8 May 2019 17:20:00 -0700 Subject: [PATCH 1/2] trace: secure_buffer: Introduce trace events for secure buffer These trace events will show the caller of hyp_assign_table() as well as information about the region(s) of memory that are affected by the changes in ownership (e.g. source/destination VMIDs and permissions). The trace events also provide information about the time spent in the higher execution layers when the memory is being assigned. Also, expose the mem_prot_info and dest_vm_and_perm_info data structures in the secure_buffer header file, so that they are visible to the trace events header file. Change-Id: I19a8561327e953e1bc593217293642f1cbd6ce36 Signed-off-by: Isaac J. Manjarres Signed-off-by: Chris Goldsworthy --- drivers/soc/qcom/secure_buffer.c | 12 --- drivers/soc/qcom/trace_secure_buffer.h | 140 +++++++++++++++++++++++++ include/soc/qcom/secure_buffer.h | 12 +++ 3 files changed, 152 insertions(+), 12 deletions(-) create mode 100644 drivers/soc/qcom/trace_secure_buffer.h diff --git a/drivers/soc/qcom/secure_buffer.c b/drivers/soc/qcom/secure_buffer.c index b0ae8bb3c974..9762fe8d0208 100644 --- a/drivers/soc/qcom/secure_buffer.c +++ b/drivers/soc/qcom/secure_buffer.c @@ -20,18 +20,6 @@ #define BATCH_MAX_SIZE SZ_2M #define BATCH_MAX_SECTIONS 32 -struct dest_vm_and_perm_info { - u32 vm; - u32 perm; - u64 ctx; - u32 ctx_size; -}; - -struct mem_prot_info { - phys_addr_t addr; - u64 size; -}; - static struct device *qcom_secure_buffer_dev; static struct dest_vm_and_perm_info * diff --git a/drivers/soc/qcom/trace_secure_buffer.h b/drivers/soc/qcom/trace_secure_buffer.h new file mode 100644 index 000000000000..f0655c8fa270 --- /dev/null +++ b/drivers/soc/qcom/trace_secure_buffer.h @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019 The Linux Foundation. All rights reserved. + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM secure_buffer + +#if !defined(_TRACE_SECURE_BUFFER_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_SECURE_BUFFER_H +#include +#include +#include + +TRACE_EVENT(hyp_assign_info, + + TP_PROTO(u32 *source_vm_list, + int source_nelems, int *dest_vmids, int *dest_perms, + int dest_nelems), + + TP_ARGS(source_vm_list, source_nelems, dest_vmids, + dest_perms, dest_nelems), + + TP_STRUCT__entry( + __field(int, source_nelems) + __field(int, dest_nelems) + __dynamic_array(u32, source_vm_list, source_nelems) + __dynamic_array(int, dest_vmids, dest_nelems) + __dynamic_array(int, dest_perms, dest_nelems) + ), + + TP_fast_assign( + __entry->source_nelems = source_nelems; + __entry->dest_nelems = dest_nelems; + memcpy(__get_dynamic_array(source_vm_list), source_vm_list, + source_nelems * sizeof(*source_vm_list)); + memcpy(__get_dynamic_array(dest_vmids), dest_vmids, + dest_nelems * sizeof(*dest_vmids)); + memcpy(__get_dynamic_array(dest_perms), dest_perms, + dest_nelems * sizeof(*dest_perms)); + ), + + TP_printk("srcVMIDs: %s dstVMIDs: %s dstPerms: %s", + __print_array(__get_dynamic_array(source_vm_list), + __entry->source_nelems, sizeof(u32)), + __print_array(__get_dynamic_array(dest_vmids), + __entry->dest_nelems, sizeof(int)), + __print_array(__get_dynamic_array(dest_perms), + __entry->dest_nelems, sizeof(int)) + ) +); + +TRACE_EVENT(hyp_assign_batch_start, + + TP_PROTO(struct mem_prot_info *info, int info_nelems), + + TP_ARGS(info, info_nelems), + + TP_STRUCT__entry( + __field(int, info_nelems) + __field(u64, batch_size) + __dynamic_array(phys_addr_t, addrs, info_nelems) + __dynamic_array(u64, sizes, info_nelems) + ), + + TP_fast_assign( + unsigned int i; + phys_addr_t *addr_arr_ptr = __get_dynamic_array(addrs); + u64 *sizes_arr_ptr = __get_dynamic_array(sizes); + + __entry->info_nelems = info_nelems; + __entry->batch_size = 0; + + for (i = 0; i < info_nelems; i++) { + addr_arr_ptr[i] = info[i].addr; + sizes_arr_ptr[i] = info[i].size; + __entry->batch_size += info[i].size; + } + ), + + TP_printk("num entries: %d batch size: %llu phys addrs: %s sizes: %s", + __entry->info_nelems, __entry->batch_size, + __print_array(__get_dynamic_array(addrs), + __entry->info_nelems, sizeof(phys_addr_t)), + __print_array(__get_dynamic_array(sizes), + __entry->info_nelems, sizeof(u64)) + ) +); + +TRACE_EVENT(hyp_assign_batch_end, + + TP_PROTO(int ret, u64 delta), + + TP_ARGS(ret, delta), + + TP_STRUCT__entry( + __field(int, ret) + __field(u64, delta) + ), + + TP_fast_assign( + __entry->ret = ret; + __entry->delta = delta; + ), + + TP_printk("ret: %d time delta: %lld us", + __entry->ret, __entry->delta + ) +); + +TRACE_EVENT(hyp_assign_end, + + TP_PROTO(u64 tot_delta, u64 avg_delta), + + TP_ARGS(tot_delta, avg_delta), + + TP_STRUCT__entry( + __field(u64, tot_delta) + __field(u64, avg_delta) + ), + + TP_fast_assign( + __entry->tot_delta = tot_delta; + __entry->avg_delta = avg_delta; + ), + + TP_printk("total time delta: %lld us avg batch delta: %lld us", + __entry->tot_delta, __entry->avg_delta + ) +); +#endif /* _TRACE_SECURE_BUFFER_H */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH ../../drivers/soc/qcom/ + +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace_secure_buffer + +/* This part must be outside protection */ +#include diff --git a/include/soc/qcom/secure_buffer.h b/include/soc/qcom/secure_buffer.h index 584a0b8814d8..0e43db3c96ac 100644 --- a/include/soc/qcom/secure_buffer.h +++ b/include/soc/qcom/secure_buffer.h @@ -41,6 +41,18 @@ enum vmid { #define PERM_WRITE 0x2 #define PERM_EXEC 0x1 +struct dest_vm_and_perm_info { + u32 vm; + u32 perm; + u64 ctx; + u32 ctx_size; +}; + +struct mem_prot_info { + phys_addr_t addr; + u64 size; +}; + #if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER) int hyp_assign_table(struct sg_table *table, u32 *source_vm_list, int source_nelems, From 0302b97aac06bda73c2686c70c936bd46a25cafb Mon Sep 17 00:00:00 2001 From: Sudarshan Rajagopalan Date: Wed, 5 Dec 2018 18:52:52 -0800 Subject: [PATCH 2/2] soc: qcom: secure_buffer: Trace hyp_assign calls Add trace events to log the caller for hyp_assign_table(), as well as other relevant information, such as source/destination VMIDs, permissions, and the sizes and physical bases of the regions affected by the call to hyp_assign(). Change-Id: Iea37d539e2409465889ad244e74ab4a9e3344e35 Signed-off-by: Sudarshan Rajagopalan Signed-off-by: Chris Goldsworthy --- drivers/soc/qcom/secure_buffer.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/secure_buffer.c b/drivers/soc/qcom/secure_buffer.c index 9762fe8d0208..8f738026ce4d 100644 --- a/drivers/soc/qcom/secure_buffer.c +++ b/drivers/soc/qcom/secure_buffer.c @@ -16,6 +16,9 @@ #include #include +#define CREATE_TRACE_POINTS +#include "trace_secure_buffer.h" + #define MEM_PROT_ASSIGN_ID 0x16 #define BATCH_MAX_SIZE SZ_2M #define BATCH_MAX_SECTIONS 32 @@ -77,9 +80,13 @@ static int batched_hyp_assign(struct sg_table *table, struct scm_desc *desc) unsigned int entries_size; unsigned int batch_start = 0; unsigned int batches_processed; + unsigned int i = 0; + u64 total_delta; struct scatterlist *curr_sgl = table->sgl; struct scatterlist *next_sgl; int ret = 0; + ktime_t batch_assign_start_ts; + ktime_t first_assign_ts; struct mem_prot_info *sg_table_copy = kcalloc(BATCH_MAX_SECTIONS, sizeof(*sg_table_copy), GFP_KERNEL); @@ -88,6 +95,7 @@ static int batched_hyp_assign(struct sg_table *table, struct scm_desc *desc) if (!sg_table_copy) return -ENOMEM; + first_assign_ts = ktime_get(); while (batch_start < table->nents) { batches_processed = get_batches_from_sgl(sg_table_copy, curr_sgl, &next_sgl); @@ -104,10 +112,15 @@ static int batched_hyp_assign(struct sg_table *table, struct scm_desc *desc) desc->args[0] = entries_dma_addr; desc->args[1] = entries_size; + trace_hyp_assign_batch_start(sg_table_copy, batches_processed); + batch_assign_start_ts = ktime_get(); ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, MEM_PROT_ASSIGN_ID), desc); - dma_unmap_single(qcom_secure_buffer_dev, entries_dma_addr, - entries_size, DMA_TO_DEVICE); + + trace_hyp_assign_batch_end(ret, ktime_us_delta(ktime_get(), + batch_assign_start_ts)); + i++; + if (ret) { pr_info("%s: Failed to assign memory protection, ret = %d\n", __func__, ret); @@ -121,7 +134,8 @@ static int batched_hyp_assign(struct sg_table *table, struct scm_desc *desc) batch_start += batches_processed; } - + total_delta = ktime_us_delta(ktime_get(), first_assign_ts); + trace_hyp_assign_end(total_delta, total_delta / i); kfree(sg_table_copy); return ret; } @@ -147,7 +161,7 @@ int hyp_assign_table(struct sg_table *table, return -EPROBE_DEFER; if (!table || !table->sgl || !source_vm_list || !source_nelems || - !dest_vmids || !dest_perms || !dest_nelems) + !dest_vmids || !dest_perms || !dest_nelems || !table->nents) return -EINVAL; /* @@ -191,6 +205,9 @@ int hyp_assign_table(struct sg_table *table, desc.arginfo = SCM_ARGS(7, SCM_RO, SCM_VAL, SCM_RO, SCM_VAL, SCM_RO, SCM_VAL, SCM_VAL); + trace_hyp_assign_info(source_vm_list, source_nelems, dest_vmids, + dest_perms, dest_nelems); + ret = batched_hyp_assign(table, &desc); dma_unmap_single(qcom_secure_buffer_dev, dest_dma_addr,