• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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