1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 
25 #include <trusty/arm_ffa.h>
26 #include <trusty/sm_err.h>
27 #include <trusty/smc.h>
28 #include <trusty/smcall.h>
29 #include <trusty/trusty_dev.h>
30 #include <trusty/trusty_mem.h>
31 #include <trusty/util.h>
32 
33 struct trusty_dev;
34 
35 #define LOCAL_LOG 0
36 
37 /*
38  * Select RXTX map smc variant based on register size. Note that the FF-A spec
39  * does not support passing a 64 bit paddr from a 32 bit client, so the
40  * allocated buffer has to be below 4G if this is called from 32 bit code.
41  */
42 #define SMC_FCZ_FFA_RXTX_MAP \
43     ((sizeof(unsigned long) <= 4) ? SMC_FC_FFA_RXTX_MAP : SMC_FC64_FFA_RXTX_MAP)
44 
trusty_fast_call32(struct trusty_dev * dev,uint32_t smcnr,uint32_t a0,uint32_t a1,uint32_t a2)45 static int32_t trusty_fast_call32(struct trusty_dev* dev,
46                                   uint32_t smcnr,
47                                   uint32_t a0,
48                                   uint32_t a1,
49                                   uint32_t a2) {
50     trusty_assert(dev);
51     trusty_assert(SMC_IS_FASTCALL(smcnr));
52 
53     return smc(smcnr, a0, a1, a2);
54 }
55 
trusty_std_call_inner(struct trusty_dev * dev,unsigned long smcnr,unsigned long a0,unsigned long a1,unsigned long a2)56 static unsigned long trusty_std_call_inner(struct trusty_dev* dev,
57                                            unsigned long smcnr,
58                                            unsigned long a0,
59                                            unsigned long a1,
60                                            unsigned long a2) {
61     unsigned long ret;
62     int retry = 5;
63 
64     trusty_debug("%s(0x%lx 0x%lx 0x%lx 0x%lx)\n", __func__, smcnr, a0, a1, a2);
65 
66     while (true) {
67         ret = smc(smcnr, a0, a1, a2);
68         while ((int32_t)ret == SM_ERR_FIQ_INTERRUPTED)
69             ret = smc(SMC_SC_RESTART_FIQ, 0, 0, 0);
70         if ((int)ret != SM_ERR_BUSY || !retry)
71             break;
72 
73         trusty_debug("%s(0x%lx 0x%lx 0x%lx 0x%lx) returned busy, retry\n",
74                      __func__, smcnr, a0, a1, a2);
75 
76         retry--;
77     }
78 
79     return ret;
80 }
81 
trusty_std_call_helper(struct trusty_dev * dev,unsigned long smcnr,unsigned long a0,unsigned long a1,unsigned long a2)82 static unsigned long trusty_std_call_helper(struct trusty_dev* dev,
83                                             unsigned long smcnr,
84                                             unsigned long a0,
85                                             unsigned long a1,
86                                             unsigned long a2) {
87     unsigned long ret;
88     unsigned long irq_state;
89 
90     while (true) {
91         trusty_local_irq_disable(&irq_state);
92         ret = trusty_std_call_inner(dev, smcnr, a0, a1, a2);
93         trusty_local_irq_restore(&irq_state);
94 
95         if ((int)ret != SM_ERR_BUSY)
96             break;
97 
98         trusty_idle(dev, false);
99     }
100 
101     return ret;
102 }
103 
trusty_std_call32(struct trusty_dev * dev,uint32_t smcnr,uint32_t a0,uint32_t a1,uint32_t a2)104 static int32_t trusty_std_call32(struct trusty_dev* dev,
105                                  uint32_t smcnr,
106                                  uint32_t a0,
107                                  uint32_t a1,
108                                  uint32_t a2) {
109     int ret;
110 
111     trusty_assert(dev);
112     trusty_assert(!SMC_IS_FASTCALL(smcnr));
113 
114     if (smcnr != SMC_SC_NOP) {
115         trusty_lock(dev);
116     }
117 
118     trusty_debug("%s(0x%x 0x%x 0x%x 0x%x) started\n", __func__, smcnr, a0, a1,
119                  a2);
120 
121     ret = trusty_std_call_helper(dev, smcnr, a0, a1, a2);
122     while (ret == SM_ERR_INTERRUPTED || ret == SM_ERR_CPU_IDLE) {
123         trusty_debug("%s(0x%x 0x%x 0x%x 0x%x) interrupted\n", __func__, smcnr,
124                      a0, a1, a2);
125         if (ret == SM_ERR_CPU_IDLE) {
126             trusty_idle(dev, false);
127         }
128         ret = trusty_std_call_helper(dev, SMC_SC_RESTART_LAST, 0, 0, 0);
129     }
130 
131     trusty_debug("%s(0x%x 0x%x 0x%x 0x%x) returned 0x%x\n", __func__, smcnr, a0,
132                  a1, a2, ret);
133 
134     if (smcnr != SMC_SC_NOP) {
135         trusty_unlock(dev);
136     }
137 
138     return ret;
139 }
140 
trusty_call32_mem_buf_id(struct trusty_dev * dev,uint32_t smcnr,trusty_shared_mem_id_t buf_id,uint32_t size)141 static int trusty_call32_mem_buf_id(struct trusty_dev* dev,
142                                     uint32_t smcnr,
143                                     trusty_shared_mem_id_t buf_id,
144                                     uint32_t size) {
145     trusty_assert(dev);
146 
147     if (SMC_IS_FASTCALL(smcnr)) {
148         return trusty_fast_call32(dev, smcnr, (uint32_t)buf_id,
149                                   (uint32_t)(buf_id >> 32), size);
150     } else {
151         return trusty_std_call32(dev, smcnr, (uint32_t)buf_id,
152                                  (uint32_t)(buf_id >> 32), size);
153     }
154 }
155 
trusty_dev_init_ipc(struct trusty_dev * dev,trusty_shared_mem_id_t buf_id,uint32_t buf_size)156 int trusty_dev_init_ipc(struct trusty_dev* dev,
157                         trusty_shared_mem_id_t buf_id,
158                         uint32_t buf_size) {
159     return trusty_call32_mem_buf_id(dev, SMC_SC_TRUSTY_IPC_CREATE_QL_DEV,
160                                     buf_id, buf_size);
161 }
162 
trusty_dev_exec_ipc(struct trusty_dev * dev,trusty_shared_mem_id_t buf_id,uint32_t buf_size)163 int trusty_dev_exec_ipc(struct trusty_dev* dev,
164                         trusty_shared_mem_id_t buf_id,
165                         uint32_t buf_size) {
166     return trusty_call32_mem_buf_id(dev, SMC_SC_TRUSTY_IPC_HANDLE_QL_DEV_CMD,
167                                     buf_id, buf_size);
168 }
169 
trusty_dev_exec_fc_ipc(struct trusty_dev * dev,trusty_shared_mem_id_t buf_id,uint32_t buf_size)170 int trusty_dev_exec_fc_ipc(struct trusty_dev* dev,
171                            trusty_shared_mem_id_t buf_id,
172                            uint32_t buf_size) {
173     return trusty_call32_mem_buf_id(dev, SMC_FC_HANDLE_QL_TIPC_DEV_CMD, buf_id,
174                                     buf_size);
175 }
176 
trusty_dev_shutdown_ipc(struct trusty_dev * dev,trusty_shared_mem_id_t buf_id,uint32_t buf_size)177 int trusty_dev_shutdown_ipc(struct trusty_dev* dev,
178                             trusty_shared_mem_id_t buf_id,
179                             uint32_t buf_size) {
180     return trusty_call32_mem_buf_id(dev, SMC_SC_TRUSTY_IPC_SHUTDOWN_QL_DEV,
181                                     buf_id, buf_size);
182 }
183 
trusty_init_api_version(struct trusty_dev * dev)184 static int trusty_init_api_version(struct trusty_dev* dev) {
185     uint32_t api_version;
186 
187     api_version = trusty_fast_call32(dev, SMC_FC_API_VERSION,
188                                      TRUSTY_API_VERSION_CURRENT, 0, 0);
189     if (api_version == SM_ERR_UNDEFINED_SMC)
190         api_version = 0;
191 
192     if (api_version > TRUSTY_API_VERSION_CURRENT) {
193         trusty_error("unsupported trusty api version %u > %u\n", api_version,
194                      TRUSTY_API_VERSION_CURRENT);
195         return -1;
196     }
197 
198     trusty_info("selected trusty api version: %u (requested %u)\n", api_version,
199                 TRUSTY_API_VERSION_CURRENT);
200 
201     dev->api_version = api_version;
202 
203     return 0;
204 }
205 
trusty_dev_init(struct trusty_dev * dev,void * priv_data)206 int trusty_dev_init(struct trusty_dev* dev, void* priv_data) {
207     int ret;
208     struct smc_ret8 smc_ret;
209     struct ns_mem_page_info tx_pinfo;
210     struct ns_mem_page_info rx_pinfo;
211     const size_t rxtx_page_count = 1;
212     trusty_assert(dev);
213 
214     dev->priv_data = priv_data;
215     dev->ffa_tx = NULL;
216     ret = trusty_init_api_version(dev);
217     if (ret) {
218         return ret;
219     }
220     if (dev->api_version < TRUSTY_API_VERSION_MEM_OBJ) {
221         return 0;
222     }
223 
224     /* Get supported FF-A version and check if it is compatible */
225     smc_ret = smc8(SMC_FC_FFA_VERSION, FFA_CURRENT_VERSION, 0, 0, 0, 0, 0, 0);
226     if (FFA_VERSION_TO_MAJOR(smc_ret.r0) != FFA_CURRENT_VERSION_MAJOR) {
227         /* TODO: support more than one (minor) version. */
228         trusty_error("%s: unsupported FF-A version 0x%lx, expected 0x%x\n",
229                      __func__, smc_ret.r0, FFA_CURRENT_VERSION);
230         goto err_version;
231     }
232 
233     /* Check that SMC_FC_FFA_MEM_SHARE is implemented */
234     smc_ret = smc8(SMC_FC_FFA_FEATURES, SMC_FC_FFA_MEM_SHARE, 0, 0, 0, 0, 0, 0);
235     if (smc_ret.r0 != SMC_FC_FFA_SUCCESS) {
236         trusty_error(
237                 "%s: SMC_FC_FFA_FEATURES(SMC_FC_FFA_MEM_SHARE) failed 0x%lx 0x%lx 0x%lx\n",
238                 __func__, smc_ret.r0, smc_ret.r1, smc_ret.r2);
239         goto err_features;
240     }
241 
242     /*
243      * Set FF-A endpoint IDs.
244      *
245      * Hardcode 0x8000 for the secure os.
246      * TODO: Use FFA call or device tree to configure this dynamically
247      */
248     smc_ret = smc8(SMC_FC_FFA_ID_GET, 0, 0, 0, 0, 0, 0, 0);
249     if (smc_ret.r0 != SMC_FC_FFA_SUCCESS) {
250         trusty_error("%s: SMC_FC_FFA_ID_GET failed 0x%lx 0x%lx 0x%lx\n",
251                      __func__, smc_ret.r0, smc_ret.r1, smc_ret.r2);
252         goto err_id_get;
253     }
254     dev->ffa_local_id = smc_ret.r2;
255     dev->ffa_remote_id = 0x8000;
256 
257     dev->ffa_tx = trusty_alloc_pages(rxtx_page_count);
258     if (!dev->ffa_tx) {
259         goto err_alloc_ffa_tx;
260     }
261     dev->ffa_rx = trusty_alloc_pages(rxtx_page_count);
262     if (!dev->ffa_rx) {
263         goto err_alloc_ffa_rx;
264     }
265     ret = trusty_encode_page_info(&tx_pinfo, dev->ffa_tx);
266     if (ret) {
267         goto err_encode_page_info;
268     }
269     ret = trusty_encode_page_info(&rx_pinfo, dev->ffa_rx);
270     if (ret) {
271         goto err_encode_page_info;
272     }
273 
274     /*
275      * TODO: check or pass memory attributes. The FF-A spec says the buffer has
276      * to be cached, but we currently have callers that don't match this.
277      */
278 
279     smc_ret = smc8(SMC_FCZ_FFA_RXTX_MAP, tx_pinfo.paddr, rx_pinfo.paddr,
280                    rxtx_page_count, 0, 0, 0, 0);
281     if (smc_ret.r0 != SMC_FC_FFA_SUCCESS) {
282         trusty_error("%s: FFA_RXTX_MAP failed 0x%lx 0x%lx 0x%lx\n", __func__,
283                      smc_ret.r0, smc_ret.r1, smc_ret.r2);
284         goto err_rxtx_map;
285     }
286 
287     if (ret) {
288         goto err_setup_msg_buf;
289     }
290     return 0;
291 
292 err_setup_msg_buf:
293 err_rxtx_map:
294 err_encode_page_info:
295 err_alloc_ffa_rx:
296 err_alloc_ffa_tx:
297 err_id_get:
298 err_features:
299 err_version:
300     trusty_fatal("%s: init failed\n", __func__, ret);
301 }
302 
trusty_dev_shutdown(struct trusty_dev * dev)303 int trusty_dev_shutdown(struct trusty_dev* dev) {
304     trusty_assert(dev);
305 
306     if (dev->ffa_tx) {
307         smc(SMC_FC_FFA_RXTX_UNMAP, 0, 0, 0);
308     }
309     dev->priv_data = NULL;
310     return 0;
311 }
312 
trusty_dev_nop(struct trusty_dev * dev)313 int trusty_dev_nop(struct trusty_dev* dev) {
314     int ret = trusty_std_call32(dev, SMC_SC_NOP, 0, 0, 0);
315     return ret == SM_ERR_NOP_DONE ? 0 : ret == SM_ERR_NOP_INTERRUPTED ? 1 : -1;
316 }
317 
trusty_dev_share_memory(struct trusty_dev * dev,trusty_shared_mem_id_t * idp,struct ns_mem_page_info * pinfo,size_t page_count)318 int trusty_dev_share_memory(struct trusty_dev* dev,
319                             trusty_shared_mem_id_t* idp,
320                             struct ns_mem_page_info* pinfo,
321                             size_t page_count) {
322     struct smc_ret8 smc_ret;
323     struct ffa_mtd* mtd = dev->ffa_tx;
324     size_t comp_mrd_offset = offsetof(struct ffa_mtd, emad[1]);
325     struct ffa_comp_mrd* comp_mrd = dev->ffa_tx + comp_mrd_offset;
326     struct ffa_cons_mrd* cons_mrd = comp_mrd->address_range_array;
327     size_t tx_size = ((void*)cons_mrd - dev->ffa_tx) + sizeof(*cons_mrd);
328 
329     if (!dev->ffa_tx) {
330         /*
331          * If the trusty api version is before TRUSTY_API_VERSION_MEM_OBJ, fall
332          * back to old api of passing the 64 bit paddr/attr value directly.
333          */
334         *idp = pinfo->attr;
335         return 0;
336     }
337 
338     trusty_memset(mtd, 0, tx_size);
339     mtd->sender_id = dev->ffa_local_id;
340     mtd->memory_region_attributes = pinfo->ffa_mem_attr;
341     mtd->emad_count = 1;
342     mtd->emad[0].mapd.endpoint_id = dev->ffa_remote_id;
343     mtd->emad[0].mapd.memory_access_permissions = pinfo->ffa_mem_perm;
344     mtd->emad[0].comp_mrd_offset = comp_mrd_offset;
345     comp_mrd->total_page_count = page_count;
346     comp_mrd->address_range_count = 1;
347     cons_mrd->address = pinfo->paddr;
348     cons_mrd->page_count = page_count;
349 
350     /*
351      * Tell the SPM/Hypervisor to share the memory.
352      */
353     smc_ret = smc8(SMC_FC_FFA_MEM_SHARE, tx_size, tx_size, 0, 0, 0, 0, 0);
354     if ((unsigned int)smc_ret.r0 != SMC_FC_FFA_SUCCESS) {
355         trusty_error("%s: SMC_FC_FFA_MEM_SHARE failed 0x%lx 0x%lx 0x%lx\n",
356                      __func__, smc_ret.r0, smc_ret.r1, smc_ret.r2);
357         return -1;
358     }
359 
360     *idp = smc_ret.r2;
361 
362     return 0;
363 }
364 
trusty_dev_reclaim_memory(struct trusty_dev * dev,trusty_shared_mem_id_t id)365 int trusty_dev_reclaim_memory(struct trusty_dev* dev,
366                               trusty_shared_mem_id_t id) {
367     struct smc_ret8 smc_ret;
368 
369     if (!dev->ffa_tx) {
370         /*
371          * If the trusty api version is before TRUSTY_API_VERSION_MEM_OBJ, fall
372          * back to old api.
373          */
374         return 0;
375     }
376 
377     /*
378      * Tell the SPM/Hypervisor to reclaim the memory. If the memory is still in
379      * use this will fail.
380      */
381     smc_ret =
382             smc8(SMC_FC_FFA_MEM_RECLAIM, (uint32_t)id, id >> 32, 0, 0, 0, 0, 0);
383     if ((unsigned int)smc_ret.r0 != SMC_FC_FFA_SUCCESS) {
384         trusty_error("%s: SMC_FC_FFA_MEM_RECLAIM failed 0x%lx 0x%lx 0x%lx\n",
385                      __func__, smc_ret.r0, smc_ret.r1, smc_ret.r2);
386         return -1;
387     }
388 
389     return 0;
390 }
391