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.

firmware: qcom: scm: add support for object invocation

Qualcomm TEE (QTEE) hosts Trusted Applications (TAs) and services in
the secure world, accessed via objects. A QTEE client can invoke these
objects to request services. Similarly, QTEE can request services from
the nonsecure world using objects exported to the secure world.

Add low-level primitives to facilitate the invocation of objects hosted
in QTEE, as well as those hosted in the nonsecure world.

If support for object invocation is available, the qcom_scm allocates
a dedicated child platform device. The driver for this device communicates
with QTEE using low-level primitives.

Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
Tested-by: Harshal Dev <quic_hdev@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-2-17f07a942b8d@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>

authored by

Amirreza Zarrabi and committed by
Bjorn Andersson
4b700098 8aa1e3a6

+132
+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
+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