Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

firmware: qcom: tzmem: export shm_bridge create/delete

Anyone with access to contiguous physical memory should be able to
share memory with QTEE using shm_bridge.

Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
Tested-by: Harshal Dev <quic_hdev@quicinc.com>
Reviewed-by: Kuldeep Singh <quic_kuldsing@quicinc.com>
Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20250911-qcom-tee-using-tee-ss-without-mem-obj-v12-1-17f07a942b8d@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>

authored by

Amirreza Zarrabi and committed by
Bjorn Andersson
8aa1e3a6 8f5ae30d

+67 -11
+52 -11
drivers/firmware/qcom/qcom_tzmem.c
··· 109 109 return 0; 110 110 } 111 111 112 - static int qcom_tzmem_init_area(struct qcom_tzmem_area *area) 112 + /** 113 + * qcom_tzmem_shm_bridge_create() - Create a SHM bridge. 114 + * @paddr: Physical address of the memory to share. 115 + * @size: Size of the memory to share. 116 + * @handle: Handle to the SHM bridge. 117 + * 118 + * On platforms that support SHM bridge, this function creates a SHM bridge 119 + * for the given memory region with QTEE. The handle returned by this function 120 + * must be passed to qcom_tzmem_shm_bridge_delete() to free the SHM bridge. 121 + * 122 + * Return: On success, returns 0; on failure, returns < 0. 123 + */ 124 + int qcom_tzmem_shm_bridge_create(phys_addr_t paddr, size_t size, u64 *handle) 113 125 { 114 126 u64 pfn_and_ns_perm, ipfn_and_s_perm, size_and_flags; 115 127 int ret; ··· 129 117 if (!qcom_tzmem_using_shm_bridge) 130 118 return 0; 131 119 132 - pfn_and_ns_perm = (u64)area->paddr | QCOM_SCM_PERM_RW; 133 - ipfn_and_s_perm = (u64)area->paddr | QCOM_SCM_PERM_RW; 134 - size_and_flags = area->size | (1 << QCOM_SHM_BRIDGE_NUM_VM_SHIFT); 120 + pfn_and_ns_perm = paddr | QCOM_SCM_PERM_RW; 121 + ipfn_and_s_perm = paddr | QCOM_SCM_PERM_RW; 122 + size_and_flags = size | (1 << QCOM_SHM_BRIDGE_NUM_VM_SHIFT); 123 + 124 + ret = qcom_scm_shm_bridge_create(pfn_and_ns_perm, ipfn_and_s_perm, 125 + size_and_flags, QCOM_SCM_VMID_HLOS, 126 + handle); 127 + if (ret) { 128 + dev_err(qcom_tzmem_dev, 129 + "SHM Bridge failed: ret %d paddr 0x%pa, size %zu\n", 130 + ret, &paddr, size); 131 + 132 + return ret; 133 + } 134 + 135 + return 0; 136 + } 137 + EXPORT_SYMBOL_GPL(qcom_tzmem_shm_bridge_create); 138 + 139 + /** 140 + * qcom_tzmem_shm_bridge_delete() - Delete a SHM bridge. 141 + * @handle: Handle to the SHM bridge. 142 + * 143 + * On platforms that support SHM bridge, this function deletes the SHM bridge 144 + * for the given memory region. The handle must be the same as the one 145 + * returned by qcom_tzmem_shm_bridge_create(). 146 + */ 147 + void qcom_tzmem_shm_bridge_delete(u64 handle) 148 + { 149 + if (qcom_tzmem_using_shm_bridge) 150 + qcom_scm_shm_bridge_delete(handle); 151 + } 152 + EXPORT_SYMBOL_GPL(qcom_tzmem_shm_bridge_delete); 153 + 154 + static int qcom_tzmem_init_area(struct qcom_tzmem_area *area) 155 + { 156 + int ret; 135 157 136 158 u64 *handle __free(kfree) = kzalloc(sizeof(*handle), GFP_KERNEL); 137 159 if (!handle) 138 160 return -ENOMEM; 139 161 140 - ret = qcom_scm_shm_bridge_create(pfn_and_ns_perm, ipfn_and_s_perm, 141 - size_and_flags, QCOM_SCM_VMID_HLOS, 142 - handle); 162 + ret = qcom_tzmem_shm_bridge_create(area->paddr, area->size, handle); 143 163 if (ret) 144 164 return ret; 145 165 ··· 184 140 { 185 141 u64 *handle = area->priv; 186 142 187 - if (!qcom_tzmem_using_shm_bridge) 188 - return; 189 - 190 - qcom_scm_shm_bridge_delete(*handle); 143 + qcom_tzmem_shm_bridge_delete(*handle); 191 144 kfree(handle); 192 145 } 193 146
+15
include/linux/firmware/qcom/qcom_tzmem.h
··· 53 53 54 54 phys_addr_t qcom_tzmem_to_phys(void *ptr); 55 55 56 + #if IS_ENABLED(CONFIG_QCOM_TZMEM_MODE_SHMBRIDGE) 57 + int qcom_tzmem_shm_bridge_create(phys_addr_t paddr, size_t size, u64 *handle); 58 + void qcom_tzmem_shm_bridge_delete(u64 handle); 59 + #else 60 + static inline int qcom_tzmem_shm_bridge_create(phys_addr_t paddr, 61 + size_t size, u64 *handle) 62 + { 63 + return 0; 64 + } 65 + 66 + static inline void qcom_tzmem_shm_bridge_delete(u64 handle) 67 + { 68 + } 69 + #endif 70 + 56 71 #endif /* __QCOM_TZMEM */