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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch '20250911-qcom-tee-using-tee-ss-without-mem-obj-v12-2-17f07a942b8d@oss.qualcomm.com' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux

firmware: qcom: tzmem: export shm_bridge create/delete
firmware: qcom: scm: add support for object invocation

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>

+199 -11
+119
drivers/firmware/qcom/qcom_scm.c
··· 2094 2094 #endif /* CONFIG_QCOM_QSEECOM */ 2095 2095 2096 2096 /** 2097 + * qcom_scm_qtee_invoke_smc() - Invoke a QTEE object. 2098 + * @inbuf: start address of memory area used for inbound buffer. 2099 + * @inbuf_size: size of the memory area used for inbound buffer. 2100 + * @outbuf: start address of memory area used for outbound buffer. 2101 + * @outbuf_size: size of the memory area used for outbound buffer. 2102 + * @result: result of QTEE object invocation. 2103 + * @response_type: response type returned by QTEE. 2104 + * 2105 + * @response_type determines how the contents of @inbuf and @outbuf 2106 + * should be processed. 2107 + * 2108 + * Return: On success, return 0 or <0 on failure. 2109 + */ 2110 + int qcom_scm_qtee_invoke_smc(phys_addr_t inbuf, size_t inbuf_size, 2111 + phys_addr_t outbuf, size_t outbuf_size, 2112 + u64 *result, u64 *response_type) 2113 + { 2114 + struct qcom_scm_desc desc = { 2115 + .svc = QCOM_SCM_SVC_SMCINVOKE, 2116 + .cmd = QCOM_SCM_SMCINVOKE_INVOKE, 2117 + .owner = ARM_SMCCC_OWNER_TRUSTED_OS, 2118 + .args[0] = inbuf, 2119 + .args[1] = inbuf_size, 2120 + .args[2] = outbuf, 2121 + .args[3] = outbuf_size, 2122 + .arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RW, QCOM_SCM_VAL, 2123 + QCOM_SCM_RW, QCOM_SCM_VAL), 2124 + }; 2125 + struct qcom_scm_res res; 2126 + int ret; 2127 + 2128 + ret = qcom_scm_call(__scm->dev, &desc, &res); 2129 + if (ret) 2130 + return ret; 2131 + 2132 + if (response_type) 2133 + *response_type = res.result[0]; 2134 + 2135 + if (result) 2136 + *result = res.result[1]; 2137 + 2138 + return 0; 2139 + } 2140 + EXPORT_SYMBOL(qcom_scm_qtee_invoke_smc); 2141 + 2142 + /** 2143 + * qcom_scm_qtee_callback_response() - Submit response for callback request. 2144 + * @buf: start address of memory area used for outbound buffer. 2145 + * @buf_size: size of the memory area used for outbound buffer. 2146 + * @result: Result of QTEE object invocation. 2147 + * @response_type: Response type returned by QTEE. 2148 + * 2149 + * @response_type determines how the contents of @buf should be processed. 2150 + * 2151 + * Return: On success, return 0 or <0 on failure. 2152 + */ 2153 + int qcom_scm_qtee_callback_response(phys_addr_t buf, size_t buf_size, 2154 + u64 *result, u64 *response_type) 2155 + { 2156 + struct qcom_scm_desc desc = { 2157 + .svc = QCOM_SCM_SVC_SMCINVOKE, 2158 + .cmd = QCOM_SCM_SMCINVOKE_CB_RSP, 2159 + .owner = ARM_SMCCC_OWNER_TRUSTED_OS, 2160 + .args[0] = buf, 2161 + .args[1] = buf_size, 2162 + .arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW, QCOM_SCM_VAL), 2163 + }; 2164 + struct qcom_scm_res res; 2165 + int ret; 2166 + 2167 + ret = qcom_scm_call(__scm->dev, &desc, &res); 2168 + if (ret) 2169 + return ret; 2170 + 2171 + if (response_type) 2172 + *response_type = res.result[0]; 2173 + 2174 + if (result) 2175 + *result = res.result[1]; 2176 + 2177 + return 0; 2178 + } 2179 + EXPORT_SYMBOL(qcom_scm_qtee_callback_response); 2180 + 2181 + static void qcom_scm_qtee_free(void *data) 2182 + { 2183 + struct platform_device *qtee_dev = data; 2184 + 2185 + platform_device_unregister(qtee_dev); 2186 + } 2187 + 2188 + static void qcom_scm_qtee_init(struct qcom_scm *scm) 2189 + { 2190 + struct platform_device *qtee_dev; 2191 + u64 result, response_type; 2192 + int ret; 2193 + 2194 + /* 2195 + * Probe for smcinvoke support. This will fail due to invalid buffers, 2196 + * but first, it checks whether the call is supported in QTEE syscall 2197 + * handler. If it is not supported, -EIO is returned. 2198 + */ 2199 + ret = qcom_scm_qtee_invoke_smc(0, 0, 0, 0, &result, &response_type); 2200 + if (ret == -EIO) 2201 + return; 2202 + 2203 + /* Setup QTEE interface device. */ 2204 + qtee_dev = platform_device_register_data(scm->dev, "qcomtee", 2205 + PLATFORM_DEVID_NONE, NULL, 0); 2206 + if (IS_ERR(qtee_dev)) 2207 + return; 2208 + 2209 + devm_add_action_or_reset(scm->dev, qcom_scm_qtee_free, qtee_dev); 2210 + } 2211 + 2212 + /** 2097 2213 * qcom_scm_is_available() - Checks if SCM is available 2098 2214 */ 2099 2215 bool qcom_scm_is_available(void) ··· 2440 2324 */ 2441 2325 ret = qcom_scm_qseecom_init(scm); 2442 2326 WARN(ret < 0, "failed to initialize qseecom: %d\n", ret); 2327 + 2328 + /* Initialize the QTEE object interface. */ 2329 + qcom_scm_qtee_init(scm); 2443 2330 2444 2331 return 0; 2445 2332 }
+7
drivers/firmware/qcom/qcom_scm.h
··· 156 156 #define QCOM_SCM_SVC_GPU 0x28 157 157 #define QCOM_SCM_SVC_GPU_INIT_REGS 0x01 158 158 159 + /* ARM_SMCCC_OWNER_TRUSTED_OS calls */ 160 + 161 + #define QCOM_SCM_SVC_SMCINVOKE 0x06 162 + #define QCOM_SCM_SMCINVOKE_INVOKE_LEGACY 0x00 163 + #define QCOM_SCM_SMCINVOKE_CB_RSP 0x01 164 + #define QCOM_SCM_SMCINVOKE_INVOKE 0x02 165 + 159 166 /* common error codes */ 160 167 #define QCOM_SCM_V2_EBUSY -12 161 168 #define QCOM_SCM_ENOMEM -5
+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
+6
include/linux/firmware/qcom/qcom_scm.h
··· 175 175 176 176 #endif /* CONFIG_QCOM_QSEECOM */ 177 177 178 + int qcom_scm_qtee_invoke_smc(phys_addr_t inbuf, size_t inbuf_size, 179 + phys_addr_t outbuf, size_t outbuf_size, 180 + u64 *result, u64 *response_type); 181 + int qcom_scm_qtee_callback_response(phys_addr_t buf, size_t buf_size, 182 + u64 *result, u64 *response_type); 183 + 178 184 #endif
+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 */