• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3  * Licensed under the Mulan PSL v2.
4  * You can use this software according to the terms and conditions of the Mulan PSL v2.
5  * You may obtain a copy of Mulan PSL v2 at:
6  *     http://license.coscl.org.cn/MulanPSL2
7  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8  * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9  * PURPOSE.
10  * See the Mulan PSL v2 for more details.
11  */
12 #include "drv_thread.h"
13 #include <errno.h>
14 #include <securec.h>
15 #include <ipclib.h>
16 #include <tee_log.h>
17 #include <mem_page_ops.h>
18 #include <tee_drv_internal.h>
19 #include <ipclib_hal.h>
20 #include <semaphore.h>
21 #include "cs.h"
22 
23 #define IPC_CHANNEL_NUM 2
24 static pthread_mutex_t g_drv_caller_info_mutex = PTHREAD_MUTEX_INITIALIZER;
25 static struct syscaller_info *g_syscaller_info = NULL;
26 static uint32_t g_thread_num = 1; /* one for main thread */
27 static sem_t g_thread_sem;
28 
thread_syscaller_init(uint32_t thread_num)29 static int32_t thread_syscaller_init(uint32_t thread_num)
30 {
31     g_thread_num += thread_num;
32     uint32_t size = g_thread_num * sizeof(struct syscaller_info);
33 
34     g_syscaller_info = malloc(size);
35     if (g_syscaller_info == NULL) {
36         tloge("cannot alloc for syscaller thread_num:%u\n", g_thread_num);
37         return -1;
38     }
39 
40     if (memset_s(g_syscaller_info, size, 0, size) != 0) {
41         free(g_syscaller_info);
42         g_syscaller_info = NULL;
43         return -1;
44     }
45 
46     uint32_t i;
47     for (i = 0; i < g_thread_num; i++)
48         g_syscaller_info[i].current_thread = INVALID_CALLER_PID;
49 
50     return 0;
51 }
52 
get_callerpid_and_job_handler_by_tid(tid_t tid,pid_t * caller_pid,uint64_t * job_handler)53 int32_t get_callerpid_and_job_handler_by_tid(tid_t tid, pid_t *caller_pid, uint64_t *job_handler)
54 {
55     if (caller_pid == NULL || job_handler == NULL) {
56         printf("invalid parameter\n");
57         return DRV_CALL_ERROR;
58     }
59 
60     for (uint32_t i = 0; i < g_thread_num; i++) {
61         if (g_syscaller_info[i].current_thread == tid) {
62             *caller_pid = g_syscaller_info[i].caller_pid;
63             *job_handler = g_syscaller_info[i].job_handler;
64             return DRV_CALL_OK;
65         }
66     }
67 
68     tloge("get caller pid and job_handler failed\n");
69 
70     return DRV_CALL_ERROR;
71 }
72 
get_callerpid_by_tid(tid_t tid,pid_t * caller_pid)73 int32_t get_callerpid_by_tid(tid_t tid, pid_t *caller_pid)
74 {
75     uint64_t job_handler;
76     int32_t ret = get_callerpid_and_job_handler_by_tid(tid, caller_pid, &job_handler);
77     return ret;
78 }
79 
update_callerpid_by_tid(tid_t tid,pid_t caller_pid)80 void update_callerpid_by_tid(tid_t tid, pid_t caller_pid)
81 {
82     uint32_t i;
83     if (pthread_mutex_lock(&g_drv_caller_info_mutex) != 0) {
84         tloge("mutex lock failed\n");
85         return;
86     }
87 
88     for (i = 0; i < g_thread_num; i++) {
89         if (g_syscaller_info[i].current_thread == tid) {
90             g_syscaller_info[i].caller_pid = caller_pid;
91             if (pthread_mutex_unlock(&g_drv_caller_info_mutex) != 0)
92                 tloge("mutex unlock failed\n");
93             return;
94         }
95     }
96 
97     for (i = 0; i < g_thread_num; i++) {
98         if (g_syscaller_info[i].current_thread == INVALID_CALLER_PID) {
99             g_syscaller_info[i].current_thread = tid;
100             g_syscaller_info[i].caller_pid = caller_pid;
101             if (pthread_mutex_unlock(&g_drv_caller_info_mutex) != 0)
102                 tloge("mutex unlock failed\n");
103             return;
104         }
105     }
106 
107     if (pthread_mutex_unlock(&g_drv_caller_info_mutex) != 0)
108         tloge("mutex unlock failed\n");
109 }
110 
update_caller_info_by_tid(tid_t tid,pid_t caller_pid,uint64_t job_handler)111 void update_caller_info_by_tid(tid_t tid, pid_t caller_pid, uint64_t job_handler)
112 {
113     uint32_t i;
114     if (pthread_mutex_lock(&g_drv_caller_info_mutex) != 0) {
115         tloge("get mutex lock failed\n");
116         return;
117     }
118 
119     for (i = 0; i < g_thread_num; i++) {
120         if (g_syscaller_info[i].current_thread == tid) {
121             g_syscaller_info[i].caller_pid = caller_pid;
122             g_syscaller_info[i].job_handler = job_handler;
123             if (pthread_mutex_unlock(&g_drv_caller_info_mutex) != 0)
124                 tloge("mutex unlock failed\n");
125             return;
126         }
127     }
128 
129     for (i = 0; i < g_thread_num; i++) {
130         if (g_syscaller_info[i].current_thread == INVALID_CALLER_PID) {
131             g_syscaller_info[i].current_thread = tid;
132             g_syscaller_info[i].caller_pid = caller_pid;
133             g_syscaller_info[i].job_handler = job_handler;
134             if (pthread_mutex_unlock(&g_drv_caller_info_mutex) != 0)
135                 tloge("mutex unlock failed\n");
136             return;
137         }
138     }
139 
140     if (pthread_mutex_unlock(&g_drv_caller_info_mutex) != 0)
141         tloge("mutex unlock failed\n");
142 }
143 
tee_driver_thread(void * args)144 static void *tee_driver_thread(void *args)
145 {
146     struct thread_init_info *pthread_info = (struct thread_init_info *)args;
147     struct reg_items_st reg_items = { true, false, false };
148 
149     cref_t channel = pthread_info->channel;
150     dispatch_fn_t dispatch_fns_thread[] = {
151         [0] = driver_dispatch,
152     };
153 
154     int32_t ret = ipc_create_channel(NULL, IPC_CHANNEL_NUM, NULL, reg_items);
155     if (ret != 0) {
156         tloge("fail to create channel ret: 0x%x\n", ret);
157         return NULL;
158     }
159 
160     sem_post(pthread_info->thread_sem);
161 
162     cs_server_loop(channel, dispatch_fns_thread, ARRAY_SIZE(dispatch_fns_thread), NULL, pthread_info);
163 
164     return NULL;
165 }
166 
init_pthread_info(struct thread_init_info * pthread_info,cref_t channel,size_t stack_size,uint32_t thread_limit)167 static int32_t init_pthread_info(struct thread_init_info *pthread_info, cref_t channel,
168     size_t stack_size, uint32_t thread_limit)
169 {
170     pthread_info->channel = channel;
171     pthread_info->func = tee_driver_thread;
172     pthread_info->max_thread = thread_limit;
173     pthread_info->thread_sem = &g_thread_sem;
174     pthread_info->stack_size = stack_size;
175     return DRV_CALL_OK;
176 }
177 
creat_server_thread(cref_t channel,size_t stack_size,uint32_t thread_limit)178 static void creat_server_thread(cref_t channel, size_t stack_size, uint32_t thread_limit)
179 {
180     pthread_attr_t attr;
181     struct thread_init_info *info = NULL;
182     int32_t ret;
183     pthread_t thread_id;
184 
185     /* create thread, thread0 is common thread. */
186     info = malloc(sizeof(*info));
187     if (info == NULL)
188         tee_abort("malloc thread info mem error\n");
189 
190     ret = pthread_attr_init(&attr);
191     if (ret != 0) {
192         free(info);
193         tee_abort("init pthread attr failed\n");
194     }
195 
196     if (stack_size != 0) {
197         ret = pthread_attr_setstacksize(&attr, stack_size);
198         if (ret != 0) {
199             free(info);
200             (void)pthread_attr_destroy(&attr);
201             tee_abort("set attr stack size fail\n");
202         }
203     }
204 
205     ret = init_pthread_info(info, channel, stack_size, thread_limit);
206     if (ret != DRV_CALL_OK) {
207         free(info);
208         tee_abort("init thread info error\n");
209     }
210 
211     ret = pthread_create(&thread_id, &attr, tee_driver_thread, info);
212     if (ret != 0) {
213         free(info);
214         tee_abort("create pthread failed\n");
215     }
216     (void)pthread_attr_destroy(&attr);
217 }
218 
thread_init_param_check(uint32_t thread_limit,uint32_t * stack_size)219 static int32_t thread_init_param_check(uint32_t thread_limit, uint32_t *stack_size)
220 {
221     /* thread_limit is 0 means only have main thread */
222     if (thread_limit > DRV_THREAD_MAX) {
223         tloge("thread limit:%u invalid\n", thread_limit);
224         return -1;
225     }
226 
227     uint32_t stack = *stack_size;
228     uint32_t temp_stack = PAGE_ALIGN_UP(stack);
229     if (temp_stack < stack) {
230         tloge("invalid stack size:0x%x\n", stack);
231         return -1;
232     }
233 
234     *stack_size = temp_stack;
235 
236     return 0;
237 }
238 
drv_thread_init(const char * thread_name,uint32_t stack_size,uint32_t thread_limit)239 int32_t drv_thread_init(const char *thread_name, uint32_t stack_size, uint32_t thread_limit)
240 {
241     cref_t channel;
242 
243     if ((thread_name == NULL) || (strnlen(thread_name, DRV_NAME_MAX_LEN) == 0) ||
244         (strnlen(thread_name, DRV_NAME_MAX_LEN) >= DRV_NAME_MAX_LEN)) {
245         tloge("thread init invalid name\n");
246         return -1;
247     }
248 
249     int32_t ret = ipc_create_channel_native(thread_name, &channel);
250     if (ret != 0)
251         tee_abort("%s: failed to create channel :%d\n", thread_name, ret);
252 
253     return multi_drv_framwork_init(thread_limit, stack_size, channel);
254 }
255 
multi_drv_framwork_init(uint32_t thread_limit,uint32_t stack_size,cref_t channel)256 int32_t multi_drv_framwork_init(uint32_t thread_limit, uint32_t stack_size, cref_t channel)
257 {
258     uint32_t stack = stack_size;
259     if (thread_init_param_check(thread_limit, &stack) != 0)
260         return -1;
261 
262     if (g_syscaller_info != NULL)
263         return 0;
264 
265     tlogd("thread_limit:%u stack_size:0x%x\n", thread_limit, stack_size);
266 
267     int32_t ret = thread_syscaller_init(thread_limit);
268     if (ret != 0)
269         return -1;
270 
271     if (thread_limit > 0) {
272         (void)sem_init(&g_thread_sem, 0, 0);
273         creat_server_thread(channel, stack, thread_limit);
274         if (sem_wait(&g_thread_sem) != 0)
275             tee_abort("sem wait failed\n");
276     }
277 
278     return 0;
279 }
280