Commit | Line | Data |
---|---|---|
6fa3eb70 S |
1 | #include <linux/slab.h> |
2 | ||
3 | #include "cmdq_sec.h" | |
4 | #include "cmdq_def.h" | |
5 | #include "cmdq_device.h" | |
6 | #include "cmdq_platform.h" | |
7 | ||
8 | static DEFINE_MUTEX(gCmdqSecExecLock); /* lock to protect atomic secure task execution */ | |
9 | static DEFINE_MUTEX(gCmdqSecProfileLock); /* ensure atomic enable/disable secure path profile */ | |
10 | static struct list_head gCmdqSecContextList; /* secure context list. note each porcess has its own sec context */ | |
11 | ||
12 | /* function declaretion */ | |
13 | cmdqSecContextHandle cmdq_sec_context_handle_create(uint32_t tgid); | |
14 | ||
15 | #if defined(CMDQ_SECURE_PATH_SUPPORT) | |
16 | ||
17 | /* mobicore driver interface */ | |
18 | #include "mobicore_driver_api.h" | |
19 | /* sectrace interface */ | |
20 | #ifdef CMDQ_SECTRACE_SUPPORT | |
21 | #include <linux/sectrace.h> | |
22 | #endif | |
23 | /* secure path header */ | |
24 | #include "cmdqSecTl_Api.h" | |
25 | ||
26 | #define CMDQ_DR_UUID { { 2, 0xb, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } | |
27 | #define CMDQ_TL_UUID { { 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } | |
28 | ||
29 | static cmdqSecContextHandle gCmdqSecContextHandle = NULL; /* secure context to cmdqSecTL */ | |
30 | /* sectrace */ | |
31 | struct mc_bulk_map gCmdqSectraceMappedInfo; /* sectrace log buffer, which mapped between NWd and SWd */ | |
32 | ||
33 | /* internal control */ | |
34 | ||
35 | /* Set 1 to open once for each process context, because of below reasons: | |
36 | * 1. mc_open_session is too slow (major) | |
37 | * 2. we entry secure world for config and trigger GCE, and wait in normal world | |
38 | */ | |
39 | #define CMDQ_OPEN_SESSION_ONCE (1) | |
40 | ||
41 | /******************************************************************************** | |
42 | * operator API | |
43 | *******************************************************************************/ | |
44 | int32_t cmdq_sec_open_mobicore_impl(uint32_t deviceId) | |
45 | { | |
46 | int32_t status = 0; | |
47 | enum mc_result mcRet = mc_open_device(deviceId); | |
48 | ||
49 | /* Currently, a process context limits to open mobicore device once, */ | |
50 | /* and mc_open_device dose not support reference cout */ | |
51 | /* so skip the false alarm error.... */ | |
52 | if (MC_DRV_ERR_INVALID_OPERATION == mcRet) { | |
53 | CMDQ_MSG("[SEC]_MOBICORE_OPEN: already opened, continue to execution\n"); | |
54 | status = -EEXIST; | |
55 | } else if (MC_DRV_OK != mcRet) { | |
56 | CMDQ_ERR("[SEC]_MOBICORE_OPEN: err[0x%x]\n", mcRet); | |
57 | status = -1; | |
58 | } | |
59 | ||
60 | CMDQ_MSG("[SEC]_MOBICORE_OPEN: status[%d], ret[0x%x]\n", status, mcRet); | |
61 | return status; | |
62 | } | |
63 | ||
64 | int32_t cmdq_sec_close_mobicore_impl(const uint32_t deviceId, const uint32_t openMobicoreByOther) | |
65 | { | |
66 | int32_t status = 0; | |
67 | enum mc_result mcRet = 0; | |
68 | ||
69 | if (1 == openMobicoreByOther) { | |
70 | /* do nothing */ | |
71 | /* let last user to close mobicore.... */ | |
72 | CMDQ_MSG("[SEC]_MOBICORE_CLOSE: opened by other, bypass device close\n"); | |
73 | } else { | |
74 | mcRet = mc_close_device(deviceId); | |
75 | CMDQ_MSG("[SEC]_MOBICORE_CLOSE: status[%d], ret[%0x], openMobicoreByOther[%d]\n", | |
76 | status, mcRet, openMobicoreByOther); | |
77 | if (MC_DRV_OK != mcRet) { | |
78 | CMDQ_ERR("[SEC]_MOBICORE_CLOSE: err[0x%x]\n", mcRet); | |
79 | status = -1; | |
80 | } | |
81 | } | |
82 | ||
83 | return status; | |
84 | } | |
85 | ||
86 | int32_t cmdq_sec_allocate_wsm_impl(uint32_t deviceId, uint8_t **ppWsm, uint32_t wsmSize) | |
87 | { | |
88 | int32_t status = 0; | |
89 | enum mc_result mcRet = MC_DRV_OK; | |
90 | ||
91 | do { | |
92 | if ((*ppWsm) != NULL) { | |
93 | status = -1; | |
94 | CMDQ_ERR("[SEC]_WSM_ALLOC: err[pWsm is not NULL]"); | |
95 | break; | |
96 | } | |
97 | ||
98 | /* because world shared mem(WSM) will ba managed by mobicore device, not linux kernel */ | |
99 | /* instead of vmalloc/kmalloc, call mc_malloc_wasm to alloc WSM to prvent error such as */ | |
100 | /* "can not resolve tci physicall address" etc */ | |
101 | mcRet = mc_malloc_wsm(deviceId, 0, wsmSize, ppWsm, 0); | |
102 | if (MC_DRV_OK != mcRet) { | |
103 | CMDQ_ERR("[SEC]_WSM_ALLOC: err[0x%x]\n", mcRet); | |
104 | status = -1; | |
105 | break; | |
106 | } | |
107 | ||
108 | CMDQ_MSG("[SEC]_WSM_ALLOC: status[%d], *ppWsm: 0x%p\n", status, (*ppWsm)); | |
109 | } while (0); | |
110 | ||
111 | return status; | |
112 | } | |
113 | ||
114 | int32_t cmdq_sec_free_wsm_impl(uint32_t deviceId, uint8_t **ppWsm) | |
115 | { | |
116 | int32_t status = 0; | |
117 | enum mc_result mcRet = mc_free_wsm(deviceId, (*ppWsm)); | |
118 | ||
119 | (*ppWsm) = (MC_DRV_OK == mcRet) ? (NULL) : (*ppWsm); | |
120 | CMDQ_VERBOSE("_WSM_FREE: ret[0x%x], *ppWsm[0x%p]\n", mcRet, (*ppWsm)); | |
121 | ||
122 | if (MC_DRV_OK != mcRet) { | |
123 | CMDQ_ERR("_WSM_FREE: err[0x%x]", mcRet); | |
124 | status = -1; | |
125 | } | |
126 | ||
127 | return status; | |
128 | } | |
129 | ||
130 | int32_t cmdq_sec_open_session_impl(uint32_t deviceId, | |
131 | const struct mc_uuid_t *uuid, | |
132 | uint8_t *pWsm, | |
133 | uint32_t wsmSize, | |
134 | struct mc_session_handle *pSessionHandle) | |
135 | { | |
136 | int32_t status = 0; | |
137 | enum mc_result mcRet = MC_DRV_OK; | |
138 | do { | |
139 | if (NULL == pWsm || NULL == pSessionHandle) { | |
140 | status = -1; | |
141 | CMDQ_ERR("[SEC]_SESSION_OPEN: invalid param, pWsm[0x%p], pSessionHandle[0x%p]\n", | |
142 | pWsm, pSessionHandle); | |
143 | break; | |
144 | } | |
145 | ||
146 | memset(pSessionHandle, 0, sizeof(*pSessionHandle)); | |
147 | pSessionHandle->device_id = deviceId; | |
148 | mcRet = mc_open_session(pSessionHandle, uuid, pWsm, wsmSize); | |
149 | if (MC_DRV_OK != mcRet) { | |
150 | CMDQ_ERR("[SEC]_SESSION_OPEN: err[0x%x]\n", mcRet); | |
151 | status = -1; | |
152 | break; | |
153 | } | |
154 | ||
155 | CMDQ_MSG("[SEC]_SESSION_OPEN: status[%d], mcRet[0x%x]\n", status, mcRet); | |
156 | } while (0); | |
157 | ||
158 | return status; | |
159 | } | |
160 | ||
161 | int32_t cmdq_sec_close_session_impl(struct mc_session_handle *pSessionHandle) | |
162 | { | |
163 | int32_t status = 0; | |
164 | enum mc_result mcRet = mc_close_session(pSessionHandle); | |
165 | ||
166 | if (MC_DRV_OK != mcRet) { | |
167 | CMDQ_ERR("_SESSION_CLOSE: err[0x%x]", mcRet); | |
168 | status = -1; | |
169 | } | |
170 | return status; | |
171 | } | |
172 | ||
173 | int32_t cmdq_sec_init_session_unlocked(const struct mc_uuid_t *uuid, | |
174 | uint8_t **ppWsm, | |
175 | uint32_t wsmSize, | |
176 | struct mc_session_handle *pSessionHandle, | |
177 | CMDQ_IWC_STATE_ENUM *pIwcState, | |
178 | uint32_t *openMobicoreByOther) | |
179 | { | |
180 | int32_t openRet = 0; | |
181 | int32_t status = 0; | |
182 | uint32_t deviceId = MC_DEVICE_ID_DEFAULT; | |
183 | ||
184 | CMDQ_MSG("[SEC]-->SESSION_INIT: iwcState[%d]\n", (*pIwcState)); | |
185 | ||
186 | do { | |
187 | #if CMDQ_OPEN_SESSION_ONCE | |
188 | if (IWC_SES_OPENED <= (*pIwcState)) { | |
189 | CMDQ_MSG("SESSION_INIT: already opened\n"); | |
190 | break; | |
191 | } else { | |
192 | CMDQ_MSG("[SEC]SESSION_INIT: open new session[%d]\n", (*pIwcState)); | |
193 | } | |
194 | #endif | |
195 | CMDQ_VERBOSE | |
196 | ("[SEC]SESSION_INIT: wsmSize[%d], pSessionHandle: 0x%p\n", | |
197 | wsmSize, pSessionHandle); | |
198 | ||
199 | CMDQ_PROF_START("CMDQ_SEC_INIT"); | |
200 | ||
201 | /* open mobicore device */ | |
202 | openRet = cmdq_sec_open_mobicore_impl(deviceId); | |
203 | if (-EEXIST == openRet) { | |
204 | /* mobicore has been opened in this process context */ | |
205 | /* it is a ok case, so continue to execute */ | |
206 | status = 0; | |
207 | (*openMobicoreByOther) = 1; | |
208 | } else if (0 > openRet) { | |
209 | status = -1; | |
210 | break; | |
211 | } | |
212 | (*pIwcState) = IWC_MOBICORE_OPENED; | |
213 | ||
214 | ||
215 | /* allocate world shared memory */ | |
216 | if (0 > cmdq_sec_allocate_wsm_impl(deviceId, ppWsm, wsmSize)) { | |
217 | status = -1; | |
218 | break; | |
219 | } | |
220 | (*pIwcState) = IWC_WSM_ALLOCATED; | |
221 | ||
222 | /* open a secure session */ | |
223 | if (0 > | |
224 | cmdq_sec_open_session_impl(deviceId, uuid, (*ppWsm), wsmSize, pSessionHandle)) { | |
225 | status = -1; | |
226 | break; | |
227 | } | |
228 | (*pIwcState) = IWC_SES_OPENED; | |
229 | ||
230 | CMDQ_PROF_END("CMDQ_SEC_INIT"); | |
231 | } while (0); | |
232 | ||
233 | CMDQ_MSG("[SEC]<--SESSION_INIT[%d]\n", status); | |
234 | return status; | |
235 | } | |
236 | ||
237 | int32_t cmdq_sec_fill_iwc_command_basic_unlocked(int32_t iwcCommand, void *_pTask, int32_t thread, void *_pIwc) | |
238 | { | |
239 | iwcCmdqMessage_t *pIwc; | |
240 | ||
241 | pIwc = (iwcCmdqMessage_t *)_pIwc; | |
242 | ||
243 | /* specify command id only, don't care other other */ | |
244 | memset(pIwc, 0x0, sizeof(iwcCmdqMessage_t)); | |
245 | pIwc->cmd = iwcCommand; | |
246 | ||
247 | /* medatada: debug config */ | |
248 | pIwc->debug.logLevel = (cmdq_core_should_print_msg()) ? (1) : (0); | |
249 | pIwc->debug.enableProfile = cmdq_core_profile_enabled(); | |
250 | ||
251 | return 0; | |
252 | } | |
253 | ||
254 | int32_t cmdq_sec_fill_iwc_command_msg_unlocked(int32_t iwcCommand, void *_pTask, int32_t thread, void *_pIwc) | |
255 | { | |
256 | int32_t status; | |
257 | const TaskStruct *pTask = (TaskStruct *)_pTask; | |
258 | iwcCmdqMessage_t *pIwc; | |
259 | /* cmdqSecDr will insert some instr*/ | |
260 | const uint32_t reservedCommandSize = 4 * CMDQ_INST_SIZE; | |
261 | ||
262 | status = 0; | |
263 | pIwc = (iwcCmdqMessage_t *)_pIwc; | |
264 | ||
265 | /* check command size first */ | |
266 | if (pTask && (CMDQ_TZ_CMD_BLOCK_SIZE < (pTask->commandSize + reservedCommandSize))) { | |
267 | CMDQ_ERR("[SEC]SESSION_MSG: pTask %p commandSize %d > %d\n", | |
268 | pTask, pTask->commandSize, CMDQ_TZ_CMD_BLOCK_SIZE); | |
269 | return -EFAULT; | |
270 | } | |
271 | ||
272 | CMDQ_MSG("[SEC]-->SESSION_MSG: cmdId[%d]\n", iwcCommand); | |
273 | ||
274 | /* fill message buffer for inter world communication */ | |
275 | memset(pIwc, 0x0, sizeof(iwcCmdqMessage_t)); | |
276 | pIwc->cmd = iwcCommand; | |
277 | ||
278 | /* metadata */ | |
279 | pIwc->command.metadata.enginesNeedDAPC = pTask->secData.enginesNeedDAPC; | |
280 | pIwc->command.metadata.enginesNeedPortSecurity = pTask->secData.enginesNeedPortSecurity; | |
281 | ||
282 | if (NULL != pTask && CMDQ_INVALID_THREAD != thread) { | |
283 | /* basic data */ | |
284 | pIwc->command.scenario = pTask->scenario; | |
285 | pIwc->command.thread = thread; | |
286 | pIwc->command.priority = pTask->priority; | |
287 | pIwc->command.engineFlag = pTask->engineFlag; | |
288 | pIwc->command.commandSize = pTask->commandSize; | |
289 | pIwc->command.hNormalTask = 0LL | ((unsigned long) pTask); | |
290 | memcpy((pIwc->command.pVABase), (pTask->pVABase), (pTask->commandSize)); | |
291 | ||
292 | /* cookie */ | |
293 | pIwc->command.waitCookie = pTask->secData.waitCookie; | |
294 | pIwc->command.resetExecCnt = pTask->secData.resetExecCnt; | |
295 | ||
296 | CMDQ_MSG("[SEC]SESSION_MSG: task 0x%p, thread: %d, size: %d, bufferSize: %d, scenario:%d, flag:0x%08llx ,hNormalTask:0x%llx\n", | |
297 | pTask, thread, pTask->commandSize, pTask->bufferSize, pTask->scenario, pTask->engineFlag, pIwc->command.hNormalTask); | |
298 | ||
299 | CMDQ_VERBOSE("[SEC]SESSION_MSG: addrList[%d][0x%p]\n", | |
300 | pTask->secData.addrMetadataCount,CMDQ_U32_PTR(pTask->secData.addrMetadatas)); | |
301 | if (0 < pTask->secData.addrMetadataCount) { | |
302 | pIwc->command.metadata.addrListLength = pTask->secData.addrMetadataCount; | |
303 | memcpy((pIwc->command.metadata.addrList), (pTask->secData.addrMetadatas), | |
304 | (pTask->secData.addrMetadataCount) * sizeof(iwcCmdqAddrMetadata_t)); | |
305 | } | |
306 | ||
307 | /* medatada: debug config */ | |
308 | pIwc->debug.logLevel = (cmdq_core_should_print_msg()) ? (1) : (0); | |
309 | pIwc->debug.enableProfile = cmdq_core_profile_enabled(); | |
310 | } else { | |
311 | /* relase resource, or debug function will go here */ | |
312 | CMDQ_VERBOSE("[SEC]-->SESSION_MSG: no task, cmdId[%d]\n", iwcCommand); | |
313 | pIwc->command.commandSize = 0; | |
314 | pIwc->command.metadata.addrListLength = 0; | |
315 | } | |
316 | ||
317 | CMDQ_MSG("[SEC]<--SESSION_MSG[%d]\n", status); | |
318 | return status; | |
319 | } | |
320 | ||
321 | // TODO: when do release secure command buffer | |
322 | int32_t cmdq_sec_fill_iwc_resource_msg_unlocked(int32_t iwcCommand, void *_pTask, int32_t thread, void *_pIwc) | |
323 | { | |
324 | iwcCmdqMessage_t *pIwc; | |
325 | cmdqSecSharedMemoryHandle pSharedMem; | |
326 | ||
327 | pSharedMem = cmdq_core_get_secure_shared_memory(); | |
328 | if (NULL == pSharedMem) { | |
329 | CMDQ_ERR("FILL:RES, NULL shared memory\n"); | |
330 | return -EFAULT; | |
331 | } | |
332 | ||
333 | if(pSharedMem && NULL == pSharedMem->pVABase) { | |
334 | CMDQ_ERR("FILL:RES, %p shared memory has not init\n", pSharedMem); | |
335 | return -EFAULT; | |
336 | } | |
337 | ||
338 | pIwc = (iwcCmdqMessage_t *)_pIwc; | |
339 | memset(pIwc, 0x0, sizeof(iwcCmdqMessage_t)); | |
340 | ||
341 | pIwc->cmd = iwcCommand; | |
342 | pIwc->pathResource.shareMemoyPA = 0LL | (pSharedMem->MVABase); | |
343 | pIwc->pathResource.size = pSharedMem->size; | |
344 | ||
345 | CMDQ_MSG("FILL:RES, shared memory:%pa(0x%llx), size:%d\n", | |
346 | &(pSharedMem->MVABase), pIwc->pathResource.shareMemoyPA, pSharedMem->size); | |
347 | ||
348 | /* medatada: debug config */ | |
349 | pIwc->debug.logLevel = (cmdq_core_should_print_msg()) ? (1) : (0); | |
350 | pIwc->debug.enableProfile = cmdq_core_profile_enabled(); | |
351 | ||
352 | return 0; | |
353 | } | |
354 | ||
355 | int32_t cmdq_sec_fill_iwc_cancel_msg_unlocked(int32_t iwcCommand, void *_pTask, int32_t thread, void *_pIwc) | |
356 | { | |
357 | const TaskStruct *pTask = (TaskStruct *)_pTask; | |
358 | iwcCmdqMessage_t *pIwc; | |
359 | ||
360 | pIwc = (iwcCmdqMessage_t *)_pIwc; | |
361 | memset(pIwc, 0x0, sizeof(iwcCmdqMessage_t)); | |
362 | ||
363 | pIwc->cmd = iwcCommand; | |
364 | pIwc->cancelTask.waitCookie = pTask->secData.waitCookie; | |
365 | pIwc->cancelTask.thread = thread; | |
366 | ||
367 | /* medatada: debug config */ | |
368 | pIwc->debug.logLevel = (cmdq_core_should_print_msg()) ? (1) : (0); | |
369 | pIwc->debug.enableProfile = cmdq_core_profile_enabled(); | |
370 | ||
371 | CMDQ_LOG("FILL:CANCEL_TASK: task: %p, thread:%d, cookie:%d\n", | |
372 | pTask, thread, pTask->secData.waitCookie); | |
373 | ||
374 | return 0; | |
375 | } | |
376 | ||
377 | int32_t cmdq_sec_execute_session_unlocked(struct mc_session_handle *pSessionHandle, | |
378 | CMDQ_IWC_STATE_ENUM *pIwcState, int32_t timeout_ms) | |
379 | { | |
380 | enum mc_result mcRet; | |
381 | int32_t status = 0; | |
382 | const int32_t secureWoldTimeout_ms = (0 < timeout_ms) ? | |
383 | (timeout_ms) : | |
384 | (MC_INFINITE_TIMEOUT); | |
385 | ||
386 | CMDQ_PROF_START("CMDQ_SEC_EXE"); | |
387 | ||
388 | do { | |
389 | /* notify to secure world */ | |
390 | mcRet = mc_notify(pSessionHandle); | |
391 | if (MC_DRV_OK != mcRet) { | |
392 | CMDQ_ERR("[SEC]EXEC: mc_notify err[0x%x]\n", mcRet); | |
393 | status = -1; | |
394 | break; | |
395 | } else { | |
396 | CMDQ_MSG("[SEC]EXEC: mc_notify ret[0x%x]\n", mcRet); | |
397 | } | |
398 | (*pIwcState) = IWC_SES_TRANSACTED; | |
399 | ||
400 | ||
401 | /* wait respond */ | |
402 | mcRet = mc_wait_notification(pSessionHandle, secureWoldTimeout_ms); | |
403 | if (MC_DRV_ERR_TIMEOUT == mcRet) { | |
404 | CMDQ_ERR | |
405 | ("[SEC]EXEC: mc_wait_notification timeout, err[0x%x], secureWoldTimeout_ms[%d]\n", | |
406 | mcRet, secureWoldTimeout_ms); | |
407 | status = -ETIMEDOUT; | |
408 | break; | |
409 | } | |
410 | ||
411 | if (MC_DRV_OK != mcRet) { | |
412 | CMDQ_ERR("[SEC]EXEC: mc_wait_notification err[0x%x]\n", mcRet); | |
413 | status = -1; | |
414 | break; | |
415 | } else { | |
416 | CMDQ_MSG("[SEC]EXEC: mc_wait_notification err[%d]\n", mcRet); | |
417 | } | |
418 | (*pIwcState) = IWC_SES_ON_TRANSACTED; | |
419 | } while (0); | |
420 | ||
421 | CMDQ_PROF_END("CMDQ_SEC_EXE"); | |
422 | ||
423 | return status; | |
424 | } | |
425 | ||
426 | void cmdq_sec_deinit_session_unlocked(uint8_t **ppWsm, | |
427 | struct mc_session_handle *pSessionHandle, | |
428 | const CMDQ_IWC_STATE_ENUM iwcState, | |
429 | const uint32_t openMobicoreByOther) | |
430 | { | |
431 | uint32_t deviceId = MC_DEVICE_ID_DEFAULT; | |
432 | ||
433 | CMDQ_MSG("[SEC]-->SESSION_DEINIT\n"); | |
434 | do { | |
435 | switch (iwcState) { | |
436 | case IWC_SES_ON_TRANSACTED: | |
437 | case IWC_SES_TRANSACTED: | |
438 | case IWC_SES_MSG_PACKAGED: | |
439 | /* continue next clean-up */ | |
440 | case IWC_SES_OPENED: | |
441 | cmdq_sec_close_session_impl(pSessionHandle); | |
442 | /* continue next clean-up */ | |
443 | case IWC_WSM_ALLOCATED: | |
444 | cmdq_sec_free_wsm_impl(deviceId, ppWsm); | |
445 | /* continue next clean-up */ | |
446 | case IWC_MOBICORE_OPENED: | |
447 | cmdq_sec_close_mobicore_impl(deviceId, openMobicoreByOther); | |
448 | /* continue next clean-up */ | |
449 | break; | |
450 | case IWC_INIT: | |
451 | /* CMDQ_ERR("open secure driver failed\n"); */ | |
452 | break; | |
453 | default: | |
454 | break; | |
455 | } | |
456 | ||
457 | } while (0); | |
458 | ||
459 | CMDQ_MSG("[SEC]<--SESSION_DEINIT\n"); | |
460 | } | |
461 | ||
462 | /******************************************************************************** | |
463 | * context handle | |
464 | *******************************************************************************/ | |
465 | int32_t cmdq_sec_setup_context_session(cmdqSecContextHandle handle) | |
466 | { | |
467 | int32_t status = 0; | |
468 | const struct mc_uuid_t uuid = CMDQ_TL_UUID; | |
469 | ||
470 | /* init iwc parameter */ | |
471 | if (IWC_INIT == handle->state) { | |
472 | handle->uuid = uuid; | |
473 | } | |
474 | /* init secure session */ | |
475 | status = cmdq_sec_init_session_unlocked(&(handle->uuid), | |
476 | (uint8_t **) (&(handle->iwcMessage)), | |
477 | sizeof(iwcCmdqMessage_t), | |
478 | &(handle->sessionHandle), | |
479 | &(handle->state), &(handle->openMobicoreByOther)); | |
480 | CMDQ_MSG("SEC_SETUP: status[%d], tgid[%d], mobicoreOpenByOther[%d]\n", | |
481 | status, handle->tgid, handle->openMobicoreByOther); | |
482 | return status; | |
483 | } | |
484 | ||
485 | int32_t cmdq_sec_handle_session_reply_unlocked(const iwcCmdqMessage_t *pIwc, | |
486 | const int32_t iwcCommand, TaskStruct *pTask, void *data) | |
487 | { | |
488 | int32_t status; | |
489 | int32_t iwcRsp; | |
490 | cmdqSecCancelTaskResultStruct *pCancelResult = NULL; | |
491 | ||
492 | /* get secure task execution result */ | |
493 | iwcRsp = (pIwc)->rsp; | |
494 | status = iwcRsp; | |
495 | ||
496 | if (CMD_CMDQ_TL_CANCEL_TASK == iwcCommand) { | |
497 | pCancelResult = (cmdqSecCancelTaskResultStruct *)data; | |
498 | if (pCancelResult) { | |
499 | pCancelResult->throwAEE = pIwc->cancelTask.throwAEE; | |
500 | pCancelResult->hasReset = pIwc->cancelTask.hasReset; | |
501 | pCancelResult->irqFlag = pIwc->cancelTask.irqFlag; | |
502 | pCancelResult->errInstr[0]= pIwc->cancelTask.errInstr[0]; /* argB */ | |
503 | pCancelResult->errInstr[1] = pIwc->cancelTask.errInstr[1]; /* argA */ | |
504 | pCancelResult->pc = pIwc->cancelTask.pc; | |
505 | } | |
506 | ||
507 | CMDQ_ERR("CANCEL_TASK: pTask %p, INST:(0x%08x, 0x%08x), throwAEE:%d, hasReset:%d, pc:0x%08x\n", | |
508 | pTask, pIwc->cancelTask.errInstr[1], pIwc->cancelTask.errInstr[0], | |
509 | pIwc->cancelTask.throwAEE, pIwc->cancelTask.hasReset, pIwc->cancelTask.pc); | |
510 | } else if (CMD_CMDQ_TL_PATH_RES_ALLOCATE == iwcCommand || CMD_CMDQ_TL_PATH_RES_RELEASE == iwcCommand ) { | |
511 | /* do nothing*/ | |
512 | } else { | |
513 | /* note we etnry SWd to config GCE, and wait execution result in NWd */ | |
514 | /* udpate taskState only if config failed*/ | |
515 | if (pTask && 0 > iwcRsp) { | |
516 | pTask->taskState= TASK_STATE_ERROR; | |
517 | } | |
518 | } | |
519 | ||
520 | /* log print */ | |
521 | if (0 < status) { | |
522 | CMDQ_ERR("SEC_SEND: status[%d], cmdId[%d], iwcRsp[%d]\n", | |
523 | status, iwcCommand, iwcRsp); | |
524 | } else { | |
525 | CMDQ_MSG("SEC_SEND: status[%d], cmdId[%d], iwcRsp[%d]\n", | |
526 | status, iwcCommand, iwcRsp); | |
527 | } | |
528 | ||
529 | return status; | |
530 | } | |
531 | ||
532 | ||
533 | CmdqSecFillIwcCB cmdq_sec_get_iwc_msg_fill_cb_by_iwc_command(uint32_t iwcCommand) | |
534 | { | |
535 | CmdqSecFillIwcCB cb = NULL; | |
536 | ||
537 | switch (iwcCommand) { | |
538 | case CMD_CMDQ_TL_CANCEL_TASK: | |
539 | cb = cmdq_sec_fill_iwc_cancel_msg_unlocked; | |
540 | break; | |
541 | case CMD_CMDQ_TL_PATH_RES_ALLOCATE: | |
542 | case CMD_CMDQ_TL_PATH_RES_RELEASE: | |
543 | cb = cmdq_sec_fill_iwc_resource_msg_unlocked; | |
544 | break; | |
545 | case CMD_CMDQ_TL_SUBMIT_TASK: | |
546 | cb = cmdq_sec_fill_iwc_command_msg_unlocked; | |
547 | break; | |
548 | case CMD_CMDQ_TL_TEST_HELLO_TL: | |
549 | case CMD_CMDQ_TL_TEST_DUMMY: | |
550 | default: | |
551 | cb = cmdq_sec_fill_iwc_command_basic_unlocked; | |
552 | break; | |
553 | }; | |
554 | ||
555 | return cb; | |
556 | } | |
557 | ||
558 | int32_t cmdq_sec_send_context_session_message(cmdqSecContextHandle handle, | |
559 | uint32_t iwcCommand, | |
560 | TaskStruct *pTask, | |
561 | int32_t thread, CmdqSecFillIwcCB cb, void *data) | |
562 | { | |
563 | int32_t status; | |
564 | const int32_t timeout_ms = (3 * 1000); | |
565 | const CmdqSecFillIwcCB iwcFillCB = (NULL == cb) ? | |
566 | cmdq_sec_get_iwc_msg_fill_cb_by_iwc_command(iwcCommand) : | |
567 | (cb); | |
568 | ||
569 | do { | |
570 | /* fill message bufer */ | |
571 | status = iwcFillCB(iwcCommand, pTask, thread, (void*)(handle->iwcMessage)); | |
572 | ||
573 | if (0 > status) { | |
574 | CMDQ_ERR("[SEC]fill msg buffer failed[%d], pid[%d:%d], cmdId[%d]\n", | |
575 | status, current->tgid, current->pid, iwcCommand); | |
576 | break; | |
577 | } | |
578 | ||
579 | /* send message */ | |
580 | status = cmdq_sec_execute_session_unlocked( | |
581 | &(handle->sessionHandle), | |
582 | &(handle->state), | |
583 | timeout_ms); | |
584 | if (0 > status) { | |
585 | CMDQ_ERR("[SEC]cmdq_sec_execute_session_unlocked failed[%d], pid[%d:%d]\n", | |
586 | status, current->tgid, current->pid); | |
587 | break; | |
588 | } | |
589 | ||
590 | status = cmdq_sec_handle_session_reply_unlocked(handle->iwcMessage, iwcCommand, pTask, data); | |
591 | } while (0); | |
592 | ||
593 | #if 0 | |
594 | cmdq_sec_insert_secure_systrace(handle); | |
595 | #endif | |
596 | ||
597 | return status; | |
598 | } | |
599 | ||
600 | int32_t cmdq_sec_teardown_context_session(cmdqSecContextHandle handle) | |
601 | { | |
602 | int32_t status = 0; | |
603 | if (handle) { | |
604 | CMDQ_MSG("[SEC]SEC_TEARDOWN: state: %d, iwcMessage:0x%p\n", | |
605 | handle->state, handle->iwcMessage); | |
606 | ||
607 | cmdq_sec_deinit_session_unlocked( | |
608 | (uint8_t **) (&(handle->iwcMessage)), | |
609 | &(handle->sessionHandle), | |
610 | handle->state, | |
611 | handle->openMobicoreByOther); | |
612 | ||
613 | /* clrean up handle's attritubes */ | |
614 | handle->state = IWC_INIT; | |
615 | ||
616 | } else { | |
617 | CMDQ_ERR("[SEC]SEC_TEARDOWN: null secCtxHandle\n"); | |
618 | status = -1; | |
619 | } | |
620 | return status; | |
621 | } | |
622 | ||
623 | void cmdq_sec_track_task_record(const uint32_t iwcCommand, | |
624 | TaskStruct *pTask, CMDQ_TIME *pEntrySec, CMDQ_TIME *pExitSec) | |
625 | { | |
626 | if (NULL == pTask) { | |
627 | return; | |
628 | } | |
629 | ||
630 | if(CMD_CMDQ_TL_SUBMIT_TASK != iwcCommand) { | |
631 | return; | |
632 | } | |
633 | ||
634 | /* record profile data */ | |
635 | /* tbase timer/time support is not enough currently, */ | |
636 | /* so we treats entry/exit timing to secure world as the trigger timing */ | |
637 | pTask->entrySec = *pEntrySec; | |
638 | pTask->exitSec = *pExitSec; | |
639 | pTask->trigger = *pEntrySec; | |
640 | } | |
641 | ||
642 | int32_t cmdq_sec_submit_to_secure_world_async_unlocked(uint32_t iwcCommand, | |
643 | TaskStruct *pTask, int32_t thread, CmdqSecFillIwcCB iwcFillCB, void *data) | |
644 | { | |
645 | const int32_t tgid = current->tgid; | |
646 | const int32_t pid = current->pid; | |
647 | cmdqSecContextHandle handle = NULL; | |
648 | int32_t status = 0; | |
649 | int32_t duration = 0; | |
650 | ||
651 | CMDQ_TIME tEntrySec; | |
652 | CMDQ_TIME tExitSec; | |
653 | ||
654 | CMDQ_MSG("[SEC]-->SEC_SUBMIT: tgid[%d:%d]\n", tgid, pid); | |
655 | do { | |
656 | /* find handle first */ | |
657 | ||
658 | /* Unlike tBase user space API, | |
659 | * tBase kernel API maintains a GLOBAL table to control mobicore device reference count. | |
660 | * For kernel spece user, mc_open_device and session_handle don't depend on the process context. | |
661 | * Therefore we use global secssion handle to inter-world commumication. */ | |
662 | if(NULL == gCmdqSecContextHandle) { | |
663 | gCmdqSecContextHandle = cmdq_sec_context_handle_create(current->tgid); | |
664 | } | |
665 | handle = gCmdqSecContextHandle; | |
666 | ||
667 | if (NULL == handle) { | |
668 | CMDQ_ERR("SEC_SUBMIT: tgid %d err[NULL secCtxHandle]\n", tgid); | |
669 | status = -(CMDQ_ERR_NULL_SEC_CTX_HANDLE); | |
670 | break; | |
671 | } | |
672 | ||
673 | if (0 > cmdq_sec_setup_context_session(handle)) { | |
674 | status = -(CMDQ_ERR_SEC_CTX_SETUP); | |
675 | break; | |
676 | } | |
677 | ||
678 | tEntrySec = sched_clock(); | |
679 | ||
680 | status = cmdq_sec_send_context_session_message( | |
681 | handle, iwcCommand, pTask, thread, iwcFillCB, data); | |
682 | ||
683 | tExitSec = sched_clock(); | |
684 | CMDQ_GET_TIME_IN_US_PART(tEntrySec, tExitSec, duration); | |
685 | cmdq_sec_track_task_record(iwcCommand, pTask, &tEntrySec, &tExitSec); | |
686 | ||
687 | /* release resource */ | |
688 | #if !(CMDQ_OPEN_SESSION_ONCE) | |
689 | cmdq_sec_teardown_context_session(handle) | |
690 | #endif | |
691 | ||
692 | /* Note we entry secure for config only and wait result in normal world. */ | |
693 | /* No need reset module HW for config failed case*/ | |
694 | } while (0); | |
695 | ||
696 | ||
697 | if (-ETIMEDOUT == status) { | |
698 | /* t-base strange issue, mc_wait_notification false timeout when secure world has done */ | |
699 | /* becuase retry may failed, give up retry method */ | |
700 | CMDQ_ERR("[SEC]<--SEC_SUBMIT: err[%d][mc_wait_notification timeout], pTask[0x%p], THR[%d], tgid[%d:%d], config_duration_ms[%d], cmdId[%d]\n", | |
701 | status, pTask, thread, tgid, pid, duration, iwcCommand); | |
702 | ||
703 | } else if (0 > status) { | |
704 | /* throw AEE */ | |
705 | CMDQ_AEE("CMDQ", | |
706 | "[SEC]<--SEC_SUBMIT: err[%d], pTask[0x%p], THR[%d], tgid[%d:%d], config_duration_ms[%d], cmdId[%d]\n", | |
707 | status, pTask, thread, tgid, pid, duration, iwcCommand); | |
708 | } else { | |
709 | CMDQ_LOG | |
710 | ("[SEC]<--SEC_SUBMIT: err[%d], pTask[0x%p], THR[%d], tgid[%d:%d], config_duration_ms[%d], cmdId[%d]\n", | |
711 | status, pTask, thread, tgid, pid, duration, iwcCommand); | |
712 | } | |
713 | return status; | |
714 | } | |
715 | ||
716 | /******************************************************************************** | |
717 | * sectrace | |
718 | *******************************************************************************/ | |
719 | ||
720 | int32_t cmdq_sec_fill_iwc_command_sectrace_unlocked(int32_t iwcCommand, void *_pTask, int32_t thread, void *_pIwc) | |
721 | { | |
722 | iwcCmdqMessage_t *pIwc; | |
723 | ||
724 | pIwc = (iwcCmdqMessage_t *)_pIwc; | |
725 | ||
726 | /* specify command id only, don't care other other */ | |
727 | memset(pIwc, 0x0, sizeof(iwcCmdqMessage_t)); | |
728 | pIwc->cmd = iwcCommand; | |
729 | ||
730 | switch (iwcCommand){ | |
731 | case CMD_CMDQ_TL_SECTRACE_MAP: | |
732 | pIwc->sectracBuffer.addr = (uint32_t)(gCmdqSectraceMappedInfo.secure_virt_addr); | |
733 | pIwc->sectracBuffer.size = (gCmdqSectraceMappedInfo.secure_virt_len); | |
734 | break; | |
735 | case CMD_CMDQ_TL_SECTRACE_UNMAP: | |
736 | case CMD_CMDQ_TL_SECTRACE_TRANSACT: | |
737 | default: | |
738 | pIwc->sectracBuffer.addr = 0; | |
739 | pIwc->sectracBuffer.size = 0; | |
740 | break; | |
741 | } | |
742 | ||
743 | /* medatada: debug config */ | |
744 | pIwc->debug.logLevel = (cmdq_core_should_print_msg()) ? (1) : (0); | |
745 | pIwc->debug.enableProfile = cmdq_core_profile_enabled(); | |
746 | ||
747 | CMDQ_LOG("[sectrace]SESSION_MSG: iwcCommand:%d, msg(sectraceBuffer, addr:0x%x, size:%d)\n", | |
748 | iwcCommand, pIwc->sectracBuffer.addr, pIwc->sectracBuffer.size); | |
749 | ||
750 | return 0; | |
751 | } | |
752 | ||
753 | static int cmdq_sec_sectrace_map(void *va, size_t size) | |
754 | { | |
755 | int status; | |
756 | enum mc_result mcRet; | |
757 | ||
758 | CMDQ_LOG("[sectrace]-->map: start, va:%p, size:%d\n", va, (int)size); | |
759 | ||
760 | status = 0; | |
761 | cmdq_sec_lock_secure_path(); | |
762 | do { | |
763 | /* HACK: submit a dummy message to ensure secure path init done */ | |
764 | status = cmdq_sec_submit_to_secure_world_async_unlocked( | |
765 | CMD_CMDQ_TL_TEST_HELLO_TL, NULL, CMDQ_INVALID_THREAD, NULL, NULL); | |
766 | ||
767 | /* map log buffer in NWd */ | |
768 | mcRet = mc_map(&(gCmdqSecContextHandle->sessionHandle), | |
769 | va, | |
770 | (uint32_t)size, | |
771 | &gCmdqSectraceMappedInfo); | |
772 | if (MC_DRV_OK != mcRet) { | |
773 | CMDQ_ERR("[sectrace]map: failed in NWd, mc_map err: 0x%x\n", mcRet); | |
774 | status = -EFAULT; | |
775 | break; | |
776 | } | |
777 | ||
778 | CMDQ_LOG("[sectrace]map: mc_map sectrace buffer done, gCmdqSectraceMappedInfo(va:0x%08x, size:%d)\n", | |
779 | gCmdqSectraceMappedInfo.secure_virt_addr, gCmdqSectraceMappedInfo.secure_virt_len); | |
780 | ||
781 | /* ask secure CMDQ to map sectrace log buffer */ | |
782 | status = cmdq_sec_submit_to_secure_world_async_unlocked( | |
783 | CMD_CMDQ_TL_SECTRACE_MAP, | |
784 | NULL, CMDQ_INVALID_THREAD, | |
785 | cmdq_sec_fill_iwc_command_sectrace_unlocked, | |
786 | NULL); | |
787 | if(0 > status) { | |
788 | CMDQ_ERR("[sectrace]map: failed in SWd: %d\n", status); | |
789 | mc_unmap(&(gCmdqSecContextHandle->sessionHandle), va, &gCmdqSectraceMappedInfo); | |
790 | status = -EFAULT; | |
791 | break; | |
792 | } | |
793 | } while(0); | |
794 | ||
795 | cmdq_sec_unlock_secure_path(); | |
796 | ||
797 | CMDQ_LOG("[sectrace]<--map: status: %d\n", status); | |
798 | ||
799 | return status; | |
800 | } | |
801 | ||
802 | static int cmdq_sec_sectrace_unmap(void *va, size_t size) | |
803 | { | |
804 | int status; | |
805 | enum mc_result mcRet; | |
806 | ||
807 | status = 0; | |
808 | cmdq_sec_lock_secure_path(); | |
809 | do { | |
810 | if(NULL == gCmdqSecContextHandle) { | |
811 | status = -EFAULT; | |
812 | break; | |
813 | } | |
814 | ||
815 | /* ask secure CMDQ to unmap sectrace log buffer */ | |
816 | status = cmdq_sec_submit_to_secure_world_async_unlocked( | |
817 | CMD_CMDQ_TL_SECTRACE_UNMAP, | |
818 | NULL, CMDQ_INVALID_THREAD, | |
819 | cmdq_sec_fill_iwc_command_sectrace_unlocked, | |
820 | NULL); | |
821 | if(0 > status) { | |
822 | CMDQ_ERR("[sectrace]unmap: failed in SWd: %d\n", status); | |
823 | mc_unmap(&(gCmdqSecContextHandle->sessionHandle), va, &gCmdqSectraceMappedInfo); | |
824 | status = -EFAULT; | |
825 | break; | |
826 | } | |
827 | ||
828 | mcRet = mc_unmap(&(gCmdqSecContextHandle->sessionHandle), va, &gCmdqSectraceMappedInfo); | |
829 | ||
830 | } while(0); | |
831 | ||
832 | cmdq_sec_unlock_secure_path(); | |
833 | ||
834 | CMDQ_LOG("[sectrace]unmap: status: %d\n", status); | |
835 | ||
836 | return status; | |
837 | } | |
838 | ||
839 | static int cmdq_sec_sectrace_transact(void) | |
840 | { | |
841 | int status; | |
842 | ||
843 | CMDQ_LOG("[sectrace]-->transact\n"); | |
844 | ||
845 | status = cmdq_sec_submit_to_secure_world_async_unlocked( | |
846 | CMD_CMDQ_TL_SECTRACE_TRANSACT, | |
847 | NULL, CMDQ_INVALID_THREAD, | |
848 | cmdq_sec_fill_iwc_command_sectrace_unlocked, NULL); | |
849 | ||
850 | CMDQ_LOG("[sectrace]<--transact: status: %d\n", status); | |
851 | ||
852 | return status; | |
853 | } | |
854 | ||
855 | int32_t cmdq_sec_sectrace_init(void) | |
856 | { | |
857 | #ifdef CMDQ_SECTRACE_SUPPORT | |
858 | int32_t status; | |
859 | const uint32_t CMDQ_SECTRACE_BUFFER_SIZE_KB = 64; | |
860 | union callback_func sectraceCB; | |
861 | ||
862 | /* use callback_tl_function becuase CMDQ use "TCI" for inter-world communication */ | |
863 | sectraceCB.tl.map = cmdq_sec_sectrace_map; | |
864 | sectraceCB.tl.unmap = cmdq_sec_sectrace_unmap; | |
865 | sectraceCB.tl.transact = cmdq_sec_sectrace_transact; | |
866 | ||
867 | /* create sectrace entry in debug FS */ | |
868 | status = init_sectrace("CMDQ_SEC", | |
869 | if_tci, /* use TCI for inter world communication */ | |
870 | usage_tl_dr, /* print sectrace log for tl and driver */ | |
871 | CMDQ_SECTRACE_BUFFER_SIZE_KB, | |
872 | §raceCB); | |
873 | ||
874 | CMDQ_LOG("cmdq_sec_trace_init, status:%d\n", status); | |
875 | return 0; | |
876 | #else | |
877 | return 0; | |
878 | #endif | |
879 | } | |
880 | ||
881 | int32_t cmdq_sec_sectrace_deinit(void) | |
882 | { | |
883 | #ifdef CMDQ_SECTRACE_SUPPORT | |
884 | /* destroy sectrace entry in debug FS */ | |
885 | deinit_sectrace("CMDQ_SEC"); | |
886 | return 0; | |
887 | #else | |
888 | return 0; | |
889 | #endif | |
890 | } | |
891 | #endif /* CMDQ_SECURE_PATH_SUPPORT */ | |
892 | ||
893 | /******************************************************************************** | |
894 | * common part: for general projects | |
895 | *******************************************************************************/ | |
896 | int32_t cmdq_sec_create_shared_memory(cmdqSecSharedMemoryHandle *pHandle, const uint32_t size) | |
897 | { | |
898 | cmdqSecSharedMemoryHandle handle = NULL; | |
899 | void *pVA = NULL; | |
900 | dma_addr_t PA = 0; | |
901 | ||
902 | handle = kzalloc(sizeof(uint8_t *) * sizeof(cmdqSecSharedMemoryStruct), GFP_KERNEL); | |
903 | if (NULL == handle) { | |
904 | return -ENOMEM; | |
905 | } | |
906 | ||
907 | CMDQ_LOG("%s\n", __func__); | |
908 | ||
909 | /* allocate non-cachable memory */ | |
910 | pVA = cmdq_core_alloc_hw_buffer( | |
911 | cmdq_dev_get(), size, &PA, GFP_KERNEL); | |
912 | ||
913 | CMDQ_MSG("%s, MVA:%pa, pVA:%p, size:%d\n", __func__, &PA, pVA, size); | |
914 | ||
915 | if(NULL == pVA) { | |
916 | kfree(handle); | |
917 | return -ENOMEM; | |
918 | } | |
919 | ||
920 | /* update memory information */ | |
921 | handle->size = size; | |
922 | handle->pVABase = pVA; | |
923 | handle->MVABase = PA; | |
924 | ||
925 | *pHandle = handle; | |
926 | ||
927 | return 0; | |
928 | } | |
929 | ||
930 | int32_t cmdq_sec_destroy_shared_memory(cmdqSecSharedMemoryHandle handle){ | |
931 | ||
932 | if(handle && handle->pVABase) { | |
933 | cmdq_core_free_hw_buffer( | |
934 | cmdq_dev_get(), handle->size, handle->pVABase, handle->MVABase); | |
935 | } | |
936 | ||
937 | if(handle) { | |
938 | kfree(handle); | |
939 | } | |
940 | ||
941 | return 0; | |
942 | } | |
943 | ||
944 | int32_t cmdq_sec_exec_task_async_unlocked(TaskStruct *pTask, int32_t thread) | |
945 | { | |
946 | #ifdef CMDQ_SECURE_PATH_SUPPORT | |
947 | int32_t status = 0; | |
948 | ||
949 | status = cmdq_sec_submit_to_secure_world_async_unlocked( | |
950 | CMD_CMDQ_TL_SUBMIT_TASK, pTask, thread, NULL, NULL); | |
951 | if (0 > status) { | |
952 | CMDQ_ERR("%s[%d]\n", __func__, status); | |
953 | } | |
954 | ||
955 | return status; | |
956 | ||
957 | #else | |
958 | CMDQ_ERR("secure path not support\n"); | |
959 | return -EFAULT; | |
960 | #endif | |
961 | } | |
962 | ||
963 | int32_t cmdq_sec_cancel_error_task_unlocked(TaskStruct *pTask, int32_t thread, cmdqSecCancelTaskResultStruct *pResult) | |
964 | { | |
965 | #ifdef CMDQ_SECURE_PATH_SUPPORT | |
966 | int32_t status = 0; | |
967 | ||
968 | if ((NULL == pTask) || | |
969 | (false == cmdq_core_is_a_secure_thread(thread)) || | |
970 | (NULL == pResult)) { | |
971 | ||
972 | CMDQ_ERR("%s invalid param, pTask:%p, thread:%d, pResult:%p\n", | |
973 | __func__, pTask, thread, pResult); | |
974 | return -EFAULT; | |
975 | } | |
976 | ||
977 | status = cmdq_sec_submit_to_secure_world_async_unlocked(CMD_CMDQ_TL_CANCEL_TASK, | |
978 | pTask, thread, NULL ,(void*)pResult); | |
979 | return status; | |
980 | #else | |
981 | CMDQ_ERR("secure path not support\n"); | |
982 | return -EFAULT; | |
983 | #endif | |
984 | } | |
985 | ||
986 | static atomic_t gCmdqSecPathResource = ATOMIC_INIT(0); | |
987 | ||
988 | int32_t cmdq_sec_allocate_path_resource_unlocked(void) | |
989 | { | |
990 | #ifdef CMDQ_SECURE_PATH_SUPPORT | |
991 | int32_t status = 0; | |
992 | ||
993 | if(1 == atomic_read(&gCmdqSecPathResource)) { | |
994 | /* has allocated successfully */ | |
995 | return status; | |
996 | } | |
997 | ||
998 | status = cmdq_sec_submit_to_secure_world_async_unlocked( | |
999 | CMD_CMDQ_TL_PATH_RES_ALLOCATE, NULL, CMDQ_INVALID_THREAD, NULL, NULL); | |
1000 | if (0 > status) { | |
1001 | CMDQ_ERR("%s[%d]\n", __func__, status); | |
1002 | } else { | |
1003 | atomic_set(&gCmdqSecPathResource, 1); | |
1004 | } | |
1005 | ||
1006 | return status; | |
1007 | ||
1008 | #else | |
1009 | CMDQ_ERR("secure path not support\n"); | |
1010 | return -EFAULT; | |
1011 | #endif | |
1012 | } | |
1013 | ||
1014 | /******************************************************************************** | |
1015 | * common part: SecContextHandle handle | |
1016 | *******************************************************************************/ | |
1017 | cmdqSecContextHandle cmdq_sec_context_handle_create(uint32_t tgid) | |
1018 | { | |
1019 | cmdqSecContextHandle handle = NULL; | |
1020 | handle = kmalloc(sizeof(uint8_t *) * sizeof(cmdqSecContextStruct), GFP_ATOMIC); | |
1021 | if (handle) { | |
1022 | handle->state = IWC_INIT; | |
1023 | handle->iwcMessage = NULL; | |
1024 | ||
1025 | handle->tgid = tgid; | |
1026 | handle->referCount = 0; | |
1027 | handle->openMobicoreByOther = 0; | |
1028 | } else { | |
1029 | CMDQ_ERR("SecCtxHandle_CREATE: err[LOW_MEM], tgid[%d]\n", tgid); | |
1030 | } | |
1031 | ||
1032 | CMDQ_MSG("SecCtxHandle_CREATE: create new, H[0x%p], tgid[%d]\n", handle, tgid); | |
1033 | return handle; | |
1034 | } | |
1035 | ||
1036 | /******************************************************************************** | |
1037 | * common part: init, deinit, path | |
1038 | *******************************************************************************/ | |
1039 | void cmdq_sec_lock_secure_path(void) | |
1040 | { | |
1041 | mutex_lock(&gCmdqSecExecLock); | |
1042 | smp_mb(); | |
1043 | } | |
1044 | ||
1045 | void cmdq_sec_unlock_secure_path(void) | |
1046 | { | |
1047 | mutex_unlock(&gCmdqSecExecLock); | |
1048 | } | |
1049 | ||
1050 | void cmdqSecDeInitialize(void) | |
1051 | { | |
1052 | } | |
1053 | ||
1054 | void cmdqSecInitialize(void) | |
1055 | { | |
1056 | INIT_LIST_HEAD(&gCmdqSecContextList); | |
1057 | } | |
1058 | ||
1059 | void cmdqSecEnableProfile(const bool enable) | |
1060 | { | |
1061 | #ifdef CMDQ_SECURE_PATH_SUPPORT | |
1062 | CMDQ_LOG("[sectrace]enable profile %d\n", enable) | |
1063 | ||
1064 | mutex_lock(&gCmdqSecProfileLock); | |
1065 | ||
1066 | if (enable) { | |
1067 | cmdq_sec_sectrace_init(); | |
1068 | } else { | |
1069 | cmdq_sec_sectrace_deinit(); | |
1070 | } | |
1071 | ||
1072 | mutex_unlock(&gCmdqSecProfileLock); | |
1073 | #endif | |
1074 | ||
1075 | return 0; | |
1076 | } |