1 /*
2 * Copyright (c) 2023 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
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 "chcore/defs.h"
13 #include "chcore/memory.h"
14 #include "chcore/type.h"
15 #include <chcore/ipc.h>
16 #include <chcore/proc.h>
17 #include <chcore/syscall.h>
18 #include <chcore-internal/procmgr_defs.h>
19 #include <string.h>
20 #include <malloc.h>
21
22 #include "proc_node.h"
23 #include "procmgr_dbg.h"
24 #include "srvmgr.h"
25 #include "libchcoreelf.h"
26 #include "liblaunch.h"
27 #include "loader.h"
28
29 /*
30 * Note: This is not an isolated server. It is still a part of procmgr and
31 * resides in the same address space. We just take the code related to server
32 * management apart from procmgr.c and put it here. Code related to server
33 * management like booting a configurable server or get some info about a server
34 * should be put in this file from now on.
35 */
36
37 static int nr_caps = 0;
38
39 /*
40 * NOTE: We do not initialize the data structure in procmgr to prevent procmgr
41 * from registering client of itself. Otherwise, it will lead to memory leak
42 * when procmgr calls printf. If put() do not send IPC msg, it can be optimized.
43 */
44 cap_t __procmgr_server_cap;
45
46 static pthread_mutex_t read_elf_lock;
47
48 /* Array of the caps of the system servers */
49 static cap_t sys_servers[CONFIG_SERVER_MAX];
50 /* To launch system server atomically */
51 static pthread_mutex_t sys_server_locks[CONFIG_SERVER_MAX];
52
53 /* For booting system servers. */
boot_server(char * srv_name,char * srv_path,cap_t * srv_cap_p,int proc_type)54 static int boot_server(char *srv_name, char *srv_path, cap_t *srv_cap_p,
55 int proc_type)
56 {
57 char *input_argv[PROC_REQ_ARGC_MAX];
58 struct proc_node *proc_node;
59 input_argv[0] = srv_path;
60 proc_node = procmgr_launch_process(
61 1, input_argv, srv_name, false, 0, NULL, proc_type);
62 if (proc_node == NULL) {
63 return -1;
64 }
65 *srv_cap_p = proc_node->proc_mt_cap;
66 return 0;
67 }
68
set_tmpfs_cap(cap_t cap)69 void set_tmpfs_cap(cap_t cap)
70 {
71 sys_servers[SERVER_TMPFS] = cap;
72 }
73
set_chanmgr_cap(cap_t cap)74 void set_chanmgr_cap(cap_t cap)
75 {
76 sys_servers[SERVER_CHANMGR] = cap;
77 }
78
79 /* Return proc_node of new process */
80 static struct proc_node *
do_launch_process(int argc,char ** argv,char * name,bool if_has_parent,badge_t parent_badge,struct user_elf * user_elf,struct loader * loader,struct new_process_args * np_args,int proc_type)81 do_launch_process(int argc, char **argv, char *name, bool if_has_parent,
82 badge_t parent_badge, struct user_elf *user_elf,
83 struct loader *loader, struct new_process_args *np_args,
84 int proc_type)
85 {
86 struct proc_node *parent_proc_node;
87 struct proc_node *proc_node;
88 cap_t caps[3];
89 int ret;
90 cap_t new_proc_cap;
91 cap_t new_proc_mt_cap;
92 struct launch_process_args lp_args;
93
94 /* Get parent_proc_node */
95 if (if_has_parent) {
96 parent_proc_node = get_proc_node(parent_badge);
97 assert(parent_proc_node);
98 } else {
99 parent_proc_node = NULL;
100 }
101
102 debug("client: %p, cmd: %s\n", parent_proc_node, argv[1]);
103 debug("fsm ipc_struct conn_cap=%d server_type=%d\n",
104 fsm_ipc_struct->conn_cap,
105 fsm_ipc_struct->server_id);
106 printf("[procmgr] Launching %s...\n", name);
107
108 /* Init caps */
109 caps[0] = __procmgr_server_cap;
110 caps[1] = fsm_server_cap;
111 caps[2] = lwip_server_cap;
112
113 for (; nr_caps < 3; nr_caps++) {
114 if (caps[nr_caps] == 0)
115 break;
116 }
117
118 /* Create proc_node to get pid */
119 proc_node = new_proc_node(parent_proc_node, name, proc_type);
120 assert(proc_node);
121
122 if (np_args == NULL) {
123 lp_args.stack_size = MAIN_THREAD_STACK_SIZE;
124 lp_args.envp_argc = 0;
125 lp_args.envp_argv = NULL;
126 #ifdef CHCORE_OH_TEE
127 lp_args.puuid = NULL;
128 lp_args.heap_size = (unsigned long)-1;
129 #endif /* CHCORE_OH_TEE */
130 } else {
131 lp_args.stack_size = np_args->stack_size;
132 lp_args.envp_argc = np_args->envp_argc;
133 lp_args.envp_argv = np_args->envp_argv;
134 #ifdef CHCORE_OH_TEE
135 lp_args.puuid = &np_args->puuid;
136 lp_args.heap_size = np_args->heap_size;
137 #endif /* CHCORE_OH_TEE */
138 }
139 /* Init launch_process_args */
140 lp_args.user_elf = user_elf;
141 lp_args.child_process_cap = &new_proc_cap;
142 lp_args.child_main_thread_cap = &new_proc_mt_cap;
143 lp_args.pmo_map_reqs = NULL;
144 lp_args.nr_pmo_map_reqs = 0;
145 lp_args.caps = caps;
146 lp_args.nr_caps = nr_caps;
147 lp_args.cpuid = 0;
148 lp_args.argc = argc;
149 lp_args.argv = argv;
150 lp_args.badge = proc_node->badge;
151 lp_args.pid = proc_node->pid;
152 lp_args.pcid = proc_node->pcid;
153 lp_args.process_name = argv[0];
154 if (!strcmp(argv[0], "/tarunner.elf")) {
155 lp_args.process_name = name;
156 }
157 lp_args.load_offset = 0;
158
159 #ifdef CHCORE_OH_TEE
160 if (lp_args.puuid != NULL) {
161 memcpy(&proc_node->puuid, lp_args.puuid, sizeof(spawn_uuid_t));
162 } else {
163 memset(&proc_node->puuid, 0, sizeof(spawn_uuid_t));
164 }
165 #endif /* CHCORE_OH_TEE */
166 proc_node->stack_size = lp_args.stack_size;
167
168 /* Launch process */
169 if (loader) {
170 ret = launch_process_using_loader(loader, &lp_args);
171 } else {
172 ret = launch_process_with_pmos_caps(&lp_args);
173 }
174
175 if (ret != 0) {
176 error("launch process failed\n");
177 return NULL;
178 }
179
180 /* Set proc_node properties */
181 proc_node->state = PROC_STATE_RUNNING;
182 proc_node->proc_cap = new_proc_cap;
183 proc_node->proc_mt_cap = new_proc_mt_cap;
184
185 debug("new_proc_node: pid=%d cmd=%s parent_pid=%d\n",
186 proc_node->pid,
187 proc_node->name,
188 proc_node->parent ? proc_node->parent->pid : -1);
189
190 return proc_node;
191 }
192
procmgr_launch_process(int argc,char ** argv,char * name,bool if_has_parent,badge_t parent_badge,struct new_process_args * np_args,int proc_type)193 struct proc_node *procmgr_launch_process(int argc, char **argv, char *name,
194 bool if_has_parent,
195 badge_t parent_badge,
196 struct new_process_args *np_args,
197 int proc_type)
198 {
199 int ret;
200 struct elf_header *elf_header;
201 struct user_elf *user_elf = NULL;
202 struct proc_node *node = NULL;
203 struct loader *loader = NULL;
204
205 /**
206 * Read ELF header first to detect dynamically linked programs.
207 */
208 ret = load_elf_header_from_fs(argv[0], &elf_header);
209 if (ret < 0) {
210 error("load_elf_header_from_fs failed, argv[0]=%s\n", argv[0]);
211 goto out;
212 }
213
214 /**
215 * For dynamically linked programs, launch it using CHCORE_LOADER,
216 * otherwise load remaining ELF content and launch it directly.
217 */
218 if (elf_header->e_type == ET_DYN) {
219 ret = find_loader(CHCORE_LOADER, &loader);
220 } else {
221 ret = load_elf_by_header_from_fs(argv[0], elf_header, &user_elf);
222 }
223
224 if (ret < 0) {
225 error("Error when launching: %s, ret = %d\n", argv[0], ret);
226 goto out_free;
227 }
228
229 node = do_launch_process(argc,
230 argv,
231 name,
232 if_has_parent,
233 parent_badge,
234 user_elf,
235 loader,
236 np_args,
237 proc_type);
238 out_free:
239 if (user_elf) {
240 free_user_elf(user_elf);
241 }
242 free(elf_header);
243 out:
244 return node;
245 }
246
procmgr_launch_basic_server(int input_argc,char ** input_argv,char * name,bool if_has_parent,badge_t parent_badge)247 struct proc_node *procmgr_launch_basic_server(int input_argc, char **input_argv,
248 char *name, bool if_has_parent,
249 badge_t parent_badge)
250 {
251 int ret;
252 struct proc_node *node;
253 struct user_elf *user_elf;
254
255 if (strcmp(input_argv[0], "/tmpfs.srv") == 0) {
256 pthread_mutex_lock(&read_elf_lock);
257 ret = load_elf_from_mem(&__binary_tmpfs_elf_start, &user_elf);
258 if (ret == 0) {
259 strncpy(user_elf->path, "/tmpfs.srv", ELF_PATH_LEN);
260 }
261 pthread_mutex_unlock(&read_elf_lock);
262 } else if (strcmp(input_argv[0], "/fsm.srv") == 0) {
263 pthread_mutex_lock(&read_elf_lock);
264 ret = load_elf_from_mem(&__binary_fsm_elf_start, &user_elf);
265 if (ret == 0) {
266 strncpy(user_elf->path, "/fsm.srv", ELF_PATH_LEN);
267 }
268 pthread_mutex_unlock(&read_elf_lock);
269 } else {
270 ret = -1;
271 }
272 if (ret < 0) {
273 debug("Error args or parsing elf error!\n");
274 return NULL;
275 }
276 node = do_launch_process(input_argc,
277 input_argv,
278 name,
279 if_has_parent,
280 parent_badge,
281 user_elf,
282 NULL,
283 NULL,
284 SYSTEM_SERVER);
285 free_user_elf(user_elf);
286 return node;
287 }
288
handle_get_server_cap(ipc_msg_t * ipc_msg,struct proc_request * pr)289 void handle_get_server_cap(ipc_msg_t *ipc_msg, struct proc_request *pr)
290 {
291 cap_t server_cap;
292 int ret = 0;
293
294 /* Check if server_id is valid */
295 if (pr->get_server_cap.server_id < 0
296 || pr->get_server_cap.server_id >= CONFIG_SERVER_MAX) {
297 ipc_return(ipc_msg, -EINVAL);
298 }
299
300 pthread_mutex_lock(&sys_server_locks[pr->get_server_cap.server_id]);
301
302 server_cap = sys_servers[pr->get_server_cap.server_id];
303
304 if (server_cap != -1) {
305 /* Server already booted */
306 ipc_msg->cap_slot_number = 1;
307 ipc_set_msg_cap(ipc_msg, 0, server_cap);
308 goto out;
309 } else {
310 /* Server not booted */
311 switch (pr->get_server_cap.server_id) {
312 case SERVER_TMPFS:
313 printf("Tmpfs does not start up now.\n");
314 BUG_ON(1);
315 goto out;
316 case SERVER_CHANMGR:
317 #ifdef CHCORE_OH_TEE
318 ret = boot_server("chanmgr",
319 "/chanmgr.srv",
320 sys_servers + SERVER_CHANMGR,
321 SYSTEM_SERVER);
322 if (ret == -1) {
323 goto out;
324 }
325 ipc_msg->cap_slot_number = 1;
326 ipc_set_msg_cap(ipc_msg, 0, sys_servers[SERVER_CHANMGR]);
327 #else
328 error("chanmgr NOT enabled!\n");
329 ret = -1;
330 #endif /* CHCORE_OH_TEE */
331 goto out;
332 default:
333 error("unvalid server id: %x\n", pr->get_server_cap.server_id);
334 goto out;
335 }
336 }
337
338 out:
339 pthread_mutex_unlock(&sys_server_locks[pr->get_server_cap.server_id]);
340 if (ret == 0) {
341 ipc_return_with_cap(ipc_msg, 0);
342 } else {
343 ipc_return(ipc_msg, ret);
344 }
345 }
346
boot_secondary_servers(void)347 void boot_secondary_servers(void)
348 {
349 }
350
init_srvmgr(void)351 void init_srvmgr(void)
352 {
353 /* Init read_elf_lock */
354 pthread_mutex_init(&read_elf_lock, NULL);
355 /* Init server array */
356 for (int i = 0; i < CONFIG_SERVER_MAX; ++i) {
357 sys_servers[i] = -1;
358 pthread_mutex_init(&sys_server_locks[i], NULL);
359 }
360 }
361