Loading drivers/soc/qcom/qtee_shmbridge.c +36 −24 Original line number Diff line number Diff line Loading @@ -13,7 +13,6 @@ #include <soc/qcom/scm.h> #include <soc/qcom/qseecomi.h> #include <soc/qcom/qtee_shmbridge.h> #include <soc/qcom/secure_buffer.h> #define DEFAULT_BRIDGE_SIZE SZ_4M /*4M*/ /* Loading Loading @@ -52,19 +51,26 @@ TZ_SYSCALL_CREATE_PARAM_ID_1( \ TZ_SYSCALL_PARAM_TYPE_VAL) #define MAXSHMVMS 4 #define PERM_BITS 3 #define VM_BITS 16 #define SELF_OWNER_BIT 1 #define SHM_NUM_VM_SHIFT 9 #define SHM_VM_MASK 0xFFFF #define SHM_PERM_MASK 0x7 #define VM_PERM_R PERM_READ #define VM_PERM_W PERM_WRITE /* ns_vmids = ns_vmid as destination number is only 1 */ #define UPDATE_NS_VMIDS(ns_vmid) ((uint64_t)(ns_vmid)) /* ns_vmids */ #define UPDATE_NS_VMIDS(ns_vmids, id) \ (((uint64_t)(ns_vmids) << VM_BITS) \ | ((uint64_t)(id) & SHM_VM_MASK)) /* ns_perms = ns_vm_perm as destination number is only 1 */ #define UPDATE_NS_PERMS(ns_vm_perm) ((uint64_t)(ns_vm_perm)) /* ns_perms */ #define UPDATE_NS_PERMS(ns_perms, perm) \ (((uint64_t)(ns_perms) << PERM_BITS) \ | ((uint64_t)(perm) & SHM_PERM_MASK)) /* pfn_and_ns_perm_flags = paddr | ns_perms */ #define UPDATE_PFN_AND_NS_PERM_FLAGS(paddr, ns_perms) \ Loading Loading @@ -106,7 +112,7 @@ static int32_t qtee_shmbridge_enable(bool enable) desc.arginfo = TZ_SHM_BRIDGE_ENABLE_PARAM_ID; ret = scm_call2(TZ_SHM_BRIDGE_ENABLE, &desc); if (ret) { pr_err("Failed to enable shmbridge, rsp = %d, ret = %d\n", pr_err("Failed to enable shmbridge, rsp = %lld, ret = %d\n", desc.ret[0], ret); return -EINVAL; } Loading @@ -126,40 +132,44 @@ EXPORT_SYMBOL(qtee_shmbridge_is_enabled); int32_t qtee_shmbridge_register( phys_addr_t paddr, size_t size, uint32_t ns_vmid, uint32_t ns_vm_perm, uint32_t *ns_vmid_list, uint32_t *ns_vm_perm_list, uint32_t ns_vmid_num, uint32_t tz_perm, uint64_t *handle) { int32_t ret = 0; uint64_t ns_perms = 0; uint64_t destnum = 1; uint64_t ns_vmids = 0; struct scm_desc desc = {0}; int i = 0; if (!handle) { pr_err("shmb handle pointer is NULL\n"); if (!handle || !ns_vmid_list || !ns_vm_perm_list || ns_vmid_num > MAXSHMVMS) { pr_err("invalid input parameters\n"); return -EINVAL; } pr_debug("%s: paddr %lx, size %zu, ns_vmid %x, ns_vm_perm %x, ns_perms %s, tz_perm %x\n", __func__, (uint64_t)paddr, size, ns_vmid, ns_vm_perm, ns_perms, tz_perm); ns_perms = UPDATE_NS_PERMS(ns_vm_perm); for (i = 0; i < ns_vmid_num; i++) { ns_perms = UPDATE_NS_PERMS(ns_perms, ns_vm_perm_list[i]); ns_vmids = UPDATE_NS_VMIDS(ns_vmids, ns_vmid_list[i]); } desc.arginfo = TZ_SHM_BRIDGE_CREATE_PARAM_ID; desc.args[0] = UPDATE_PFN_AND_NS_PERM_FLAGS(paddr, ns_perms); desc.args[1] = UPDATE_IPFN_AND_S_PERM_FLAGS(paddr, tz_perm); desc.args[2] = UPDATE_SIZE_AND_FLAGS(size, destnum); desc.args[3] = UPDATE_NS_VMIDS(ns_vmid); desc.args[2] = UPDATE_SIZE_AND_FLAGS(size, ns_vmid_num); desc.args[3] = ns_vmids; pr_debug("%s: arginfo %lx, desc.args[0] %lx, args[1] %lx, args[2] %lx, args[3] %lx\n", pr_debug("%s: arginfo %x, desc.args[0] %llx, args[1] %llx, args[2] %llx, args[3] %llx\n", __func__, desc.arginfo, desc.args[0], desc.args[1], desc.args[2], desc.args[3]); ret = scm_call2(TZ_SHM_BRIDGE_CREATE, &desc); if (ret || desc.ret[0]) { pr_err("create shmbridge failed, ret = %d, status = %x\n", pr_err("create shmbridge failed, ret = %d, status = %llx\n", ret, desc.ret[0]); return ret; return -EINVAL; } *handle = desc.ret[1]; return 0; Loading Loading @@ -191,7 +201,7 @@ int32_t qtee_shmbridge_allocate_shm(size_t size, struct qtee_shm *shm) unsigned long va; if (size > DEFAULT_BRIDGE_SIZE) { pr_err("requestd size %zu is larger than bridge size %zu\n", pr_err("requestd size %zu is larger than bridge size %d\n", size, DEFAULT_BRIDGE_SIZE); ret = -EINVAL; goto exit; Loading @@ -216,7 +226,7 @@ int32_t qtee_shmbridge_allocate_shm(size_t size, struct qtee_shm *shm) shm->paddr = gen_pool_virt_to_phys(default_bridge.genpool, va); shm->size = size; pr_debug("%s: shm->paddr %lx, size %zu\n", pr_debug("%s: shm->paddr %llx, size %zu\n", __func__, (uint64_t)shm->paddr, shm->size); exit: Loading @@ -242,6 +252,8 @@ EXPORT_SYMBOL(qtee_shmbridge_free_shm); static int __init qtee_shmbridge_init(void) { int ret = 0; uint32_t ns_vm_ids[] = {VMID_HLOS}; uint32_t ns_vm_perms[] = {VM_PERM_R|VM_PERM_W}; if (default_bridge.vaddr) { pr_warn("qtee shmbridge is already initialized\n"); Loading @@ -264,8 +276,8 @@ static int __init qtee_shmbridge_init(void) /*register default bridge*/ ret = qtee_shmbridge_register(default_bridge.paddr, default_bridge.size, VMID_HLOS, VM_PERM_R|VM_PERM_W, VM_PERM_R|VM_PERM_W, default_bridge.size, ns_vm_ids, ns_vm_perms, 1, VM_PERM_R|VM_PERM_W, &default_bridge.handle); if (ret) { pr_err("Failed to register default bridge, size %zu\n", Loading include/soc/qcom/qtee_shmbridge.h +17 −12 Original line number Diff line number Diff line Loading @@ -6,6 +6,9 @@ #ifndef __QTEE_SHMBRIDGE_H__ #define __QTEE_SHMBRIDGE_H__ /* VMID and permission definitions */ #include <soc/qcom/secure_buffer.h> /** * struct qtee_shm - info of shared memory allocated from the default bridge * @ paddr: physical address of the shm allocated from the default bridge Loading @@ -28,27 +31,29 @@ bool qtee_shmbridge_is_enabled(void); /** * Register paddr & size as a bridge, get bridge handle * * @ paddr: paddr of buffer to be turned into bridge * @ size: size of the bridge * @ ns_vmid: non-secure vmid, like VMID_HLOS * @ ns_vm_perm: NS VM permission, like PERM_READ, PERM_WRITE * @ tz_perm: TZ permission * @ *handle: output shmbridge handle * @ [IN] addr: paddr of buffer to be turned into bridge * @ [IN] size: size of the bridge * @ [IN] ns_vmid_list: non-secure vmids array * @ [IN] ns_vm_perm_list: NS VM permission array * @ [IN] ns_vmid_num: number of NS VMIDs (at most 4) * @ [IN] tz_perm: TZ permission * @ [OUT] *handle: output shmbridge handle * * return success or error */ int32_t qtee_shmbridge_register( phys_addr_t paddr, size_t size, uint32_t ns_vmid, uint32_t ns_vm_perm, uint32_t *ns_vmid_list, uint32_t *ns_vm_perm_list, uint32_t ns_vmid_num, uint32_t tz_perm, uint64_t *handle); /** * Deregister bridge * * @ handle: shmbridge handle * @ [IN] handle: shmbridge handle * * return success or error */ Loading @@ -57,8 +62,8 @@ int32_t qtee_shmbridge_deregister(uint64_t handle); /** * Sub-allocate from default kernel bridge created by shmb driver * * @ size: size of the buffer to be sub-allocated from the bridge * @ *shm: output qtee_shm structure with buffer paddr, vaddr and * @ [IN] size: size of the buffer to be sub-allocated from the bridge * @ [OUT] *shm: output qtee_shm structure with buffer paddr, vaddr and * size; returns ERR_PTR or NULL otherwise * * return success or error Loading @@ -68,7 +73,7 @@ int32_t qtee_shmbridge_allocate_shm(size_t size, struct qtee_shm *shm); /* * Free buffer that is sub-allocated from default kernel bridge * * @ shm: qtee_shm structure to be freed * @ [IN] shm: qtee_shm structure to be freed * */ void qtee_shmbridge_free_shm(struct qtee_shm *shm); Loading Loading
drivers/soc/qcom/qtee_shmbridge.c +36 −24 Original line number Diff line number Diff line Loading @@ -13,7 +13,6 @@ #include <soc/qcom/scm.h> #include <soc/qcom/qseecomi.h> #include <soc/qcom/qtee_shmbridge.h> #include <soc/qcom/secure_buffer.h> #define DEFAULT_BRIDGE_SIZE SZ_4M /*4M*/ /* Loading Loading @@ -52,19 +51,26 @@ TZ_SYSCALL_CREATE_PARAM_ID_1( \ TZ_SYSCALL_PARAM_TYPE_VAL) #define MAXSHMVMS 4 #define PERM_BITS 3 #define VM_BITS 16 #define SELF_OWNER_BIT 1 #define SHM_NUM_VM_SHIFT 9 #define SHM_VM_MASK 0xFFFF #define SHM_PERM_MASK 0x7 #define VM_PERM_R PERM_READ #define VM_PERM_W PERM_WRITE /* ns_vmids = ns_vmid as destination number is only 1 */ #define UPDATE_NS_VMIDS(ns_vmid) ((uint64_t)(ns_vmid)) /* ns_vmids */ #define UPDATE_NS_VMIDS(ns_vmids, id) \ (((uint64_t)(ns_vmids) << VM_BITS) \ | ((uint64_t)(id) & SHM_VM_MASK)) /* ns_perms = ns_vm_perm as destination number is only 1 */ #define UPDATE_NS_PERMS(ns_vm_perm) ((uint64_t)(ns_vm_perm)) /* ns_perms */ #define UPDATE_NS_PERMS(ns_perms, perm) \ (((uint64_t)(ns_perms) << PERM_BITS) \ | ((uint64_t)(perm) & SHM_PERM_MASK)) /* pfn_and_ns_perm_flags = paddr | ns_perms */ #define UPDATE_PFN_AND_NS_PERM_FLAGS(paddr, ns_perms) \ Loading Loading @@ -106,7 +112,7 @@ static int32_t qtee_shmbridge_enable(bool enable) desc.arginfo = TZ_SHM_BRIDGE_ENABLE_PARAM_ID; ret = scm_call2(TZ_SHM_BRIDGE_ENABLE, &desc); if (ret) { pr_err("Failed to enable shmbridge, rsp = %d, ret = %d\n", pr_err("Failed to enable shmbridge, rsp = %lld, ret = %d\n", desc.ret[0], ret); return -EINVAL; } Loading @@ -126,40 +132,44 @@ EXPORT_SYMBOL(qtee_shmbridge_is_enabled); int32_t qtee_shmbridge_register( phys_addr_t paddr, size_t size, uint32_t ns_vmid, uint32_t ns_vm_perm, uint32_t *ns_vmid_list, uint32_t *ns_vm_perm_list, uint32_t ns_vmid_num, uint32_t tz_perm, uint64_t *handle) { int32_t ret = 0; uint64_t ns_perms = 0; uint64_t destnum = 1; uint64_t ns_vmids = 0; struct scm_desc desc = {0}; int i = 0; if (!handle) { pr_err("shmb handle pointer is NULL\n"); if (!handle || !ns_vmid_list || !ns_vm_perm_list || ns_vmid_num > MAXSHMVMS) { pr_err("invalid input parameters\n"); return -EINVAL; } pr_debug("%s: paddr %lx, size %zu, ns_vmid %x, ns_vm_perm %x, ns_perms %s, tz_perm %x\n", __func__, (uint64_t)paddr, size, ns_vmid, ns_vm_perm, ns_perms, tz_perm); ns_perms = UPDATE_NS_PERMS(ns_vm_perm); for (i = 0; i < ns_vmid_num; i++) { ns_perms = UPDATE_NS_PERMS(ns_perms, ns_vm_perm_list[i]); ns_vmids = UPDATE_NS_VMIDS(ns_vmids, ns_vmid_list[i]); } desc.arginfo = TZ_SHM_BRIDGE_CREATE_PARAM_ID; desc.args[0] = UPDATE_PFN_AND_NS_PERM_FLAGS(paddr, ns_perms); desc.args[1] = UPDATE_IPFN_AND_S_PERM_FLAGS(paddr, tz_perm); desc.args[2] = UPDATE_SIZE_AND_FLAGS(size, destnum); desc.args[3] = UPDATE_NS_VMIDS(ns_vmid); desc.args[2] = UPDATE_SIZE_AND_FLAGS(size, ns_vmid_num); desc.args[3] = ns_vmids; pr_debug("%s: arginfo %lx, desc.args[0] %lx, args[1] %lx, args[2] %lx, args[3] %lx\n", pr_debug("%s: arginfo %x, desc.args[0] %llx, args[1] %llx, args[2] %llx, args[3] %llx\n", __func__, desc.arginfo, desc.args[0], desc.args[1], desc.args[2], desc.args[3]); ret = scm_call2(TZ_SHM_BRIDGE_CREATE, &desc); if (ret || desc.ret[0]) { pr_err("create shmbridge failed, ret = %d, status = %x\n", pr_err("create shmbridge failed, ret = %d, status = %llx\n", ret, desc.ret[0]); return ret; return -EINVAL; } *handle = desc.ret[1]; return 0; Loading Loading @@ -191,7 +201,7 @@ int32_t qtee_shmbridge_allocate_shm(size_t size, struct qtee_shm *shm) unsigned long va; if (size > DEFAULT_BRIDGE_SIZE) { pr_err("requestd size %zu is larger than bridge size %zu\n", pr_err("requestd size %zu is larger than bridge size %d\n", size, DEFAULT_BRIDGE_SIZE); ret = -EINVAL; goto exit; Loading @@ -216,7 +226,7 @@ int32_t qtee_shmbridge_allocate_shm(size_t size, struct qtee_shm *shm) shm->paddr = gen_pool_virt_to_phys(default_bridge.genpool, va); shm->size = size; pr_debug("%s: shm->paddr %lx, size %zu\n", pr_debug("%s: shm->paddr %llx, size %zu\n", __func__, (uint64_t)shm->paddr, shm->size); exit: Loading @@ -242,6 +252,8 @@ EXPORT_SYMBOL(qtee_shmbridge_free_shm); static int __init qtee_shmbridge_init(void) { int ret = 0; uint32_t ns_vm_ids[] = {VMID_HLOS}; uint32_t ns_vm_perms[] = {VM_PERM_R|VM_PERM_W}; if (default_bridge.vaddr) { pr_warn("qtee shmbridge is already initialized\n"); Loading @@ -264,8 +276,8 @@ static int __init qtee_shmbridge_init(void) /*register default bridge*/ ret = qtee_shmbridge_register(default_bridge.paddr, default_bridge.size, VMID_HLOS, VM_PERM_R|VM_PERM_W, VM_PERM_R|VM_PERM_W, default_bridge.size, ns_vm_ids, ns_vm_perms, 1, VM_PERM_R|VM_PERM_W, &default_bridge.handle); if (ret) { pr_err("Failed to register default bridge, size %zu\n", Loading
include/soc/qcom/qtee_shmbridge.h +17 −12 Original line number Diff line number Diff line Loading @@ -6,6 +6,9 @@ #ifndef __QTEE_SHMBRIDGE_H__ #define __QTEE_SHMBRIDGE_H__ /* VMID and permission definitions */ #include <soc/qcom/secure_buffer.h> /** * struct qtee_shm - info of shared memory allocated from the default bridge * @ paddr: physical address of the shm allocated from the default bridge Loading @@ -28,27 +31,29 @@ bool qtee_shmbridge_is_enabled(void); /** * Register paddr & size as a bridge, get bridge handle * * @ paddr: paddr of buffer to be turned into bridge * @ size: size of the bridge * @ ns_vmid: non-secure vmid, like VMID_HLOS * @ ns_vm_perm: NS VM permission, like PERM_READ, PERM_WRITE * @ tz_perm: TZ permission * @ *handle: output shmbridge handle * @ [IN] addr: paddr of buffer to be turned into bridge * @ [IN] size: size of the bridge * @ [IN] ns_vmid_list: non-secure vmids array * @ [IN] ns_vm_perm_list: NS VM permission array * @ [IN] ns_vmid_num: number of NS VMIDs (at most 4) * @ [IN] tz_perm: TZ permission * @ [OUT] *handle: output shmbridge handle * * return success or error */ int32_t qtee_shmbridge_register( phys_addr_t paddr, size_t size, uint32_t ns_vmid, uint32_t ns_vm_perm, uint32_t *ns_vmid_list, uint32_t *ns_vm_perm_list, uint32_t ns_vmid_num, uint32_t tz_perm, uint64_t *handle); /** * Deregister bridge * * @ handle: shmbridge handle * @ [IN] handle: shmbridge handle * * return success or error */ Loading @@ -57,8 +62,8 @@ int32_t qtee_shmbridge_deregister(uint64_t handle); /** * Sub-allocate from default kernel bridge created by shmb driver * * @ size: size of the buffer to be sub-allocated from the bridge * @ *shm: output qtee_shm structure with buffer paddr, vaddr and * @ [IN] size: size of the buffer to be sub-allocated from the bridge * @ [OUT] *shm: output qtee_shm structure with buffer paddr, vaddr and * size; returns ERR_PTR or NULL otherwise * * return success or error Loading @@ -68,7 +73,7 @@ int32_t qtee_shmbridge_allocate_shm(size_t size, struct qtee_shm *shm); /* * Free buffer that is sub-allocated from default kernel bridge * * @ shm: qtee_shm structure to be freed * @ [IN] shm: qtee_shm structure to be freed * */ void qtee_shmbridge_free_shm(struct qtee_shm *shm); Loading