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
13 #define _GNU_SOURCE
14 #include <assert.h>
15 #include <bits/alltypes.h>
16 #include <bits/syscall.h>
17 #include <dirent.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <limits.h>
21 #include <sched.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <time.h>
26 #include <sys/mman.h>
27 #include <sys/socket.h>
28 #include <sys/stat.h>
29 #include <sys/statfs.h>
30 #include <sys/auxv.h>
31 #include <sys/uio.h>
32 #include <sys/resource.h>
33 #include <raw_syscall.h>
34 #include <syscall_arch.h>
35 #include <termios.h>
36 #include <stdlib.h>
37 #include <pthread.h>
38 #include <unistd.h>
39 #include <sys/utsname.h>
40
41 /* ChCore Port header */
42 #include "fd.h"
43 #include "poll.h"
44 #include <chcore/bug.h>
45 #include <chcore/defs.h>
46 #include <chcore-internal/fs_defs.h>
47 #include <chcore/ipc.h>
48 #include <chcore-internal/procmgr_defs.h>
49 #include "futex.h"
50 #include "eventfd.h"
51 #include "pipe.h"
52 #include "timerfd.h"
53 #include "file.h"
54 #include "fs_client_defs.h"
55 #include "chcore_mman.h"
56 #include <chcore-internal/fs_debug.h>
57 #include <chcore/memory.h>
58 #include "chcore_kill.h"
59
60 #define debug(fmt, ...) printf("[DEBUG] " fmt, ##__VA_ARGS__)
61 #define warn(fmt, ...) printf("[WARN] " fmt, ##__VA_ARGS__)
62 #define warn_once(fmt, ...) \
63 do { \
64 static int __warned = 0; \
65 if (__warned) \
66 break; \
67 __warned = 1; \
68 warn(fmt, ##__VA_ARGS__); \
69 } while (0)
70
71 // #define TRACE_SYSCALL
72 #ifdef TRACE_SYSCALL
73 #define syscall_trace(n) \
74 printf("[dispatcher] %s: syscall_num %ld\n", __func__, n)
75 #else
76 #define syscall_trace(n) \
77 do { \
78 } while (0)
79 #endif
80
81 #define MAX(x, y) ((x) < (y) ? (y) : (x))
82 #ifndef MIN
83 #define MIN(x, y) ((x) < (y) ? (x) : (y))
84 #endif
85
86 #define _SYSCALL_LL_REV(a, b) \
87 ((union { \
88 long long ll; \
89 long l[2]; \
90 }){.l = {(a), (b)}}) \
91 .ll
92
93 /*
94 * Used to issue ipc to user-space services
95 * Register to server before executing the program
96 */
97 cap_t fsm_server_cap = 0;
98 cap_t lwip_server_cap = 0;
99
100 cap_t procmgr_server_cap = 0;
101
102 int chcore_pid = 0;
103
104 /*
105 * Helper function.
106 */
107 extern int __xstatxx(int req, int fd, const char *path, int flags,
108 void *statbuf, size_t bufsize);
109 void dead(long n);
110
111 typedef struct {
112 unsigned long a_type;
113 union {
114 unsigned long a_val;
115 char *a_ptr;
116 };
117 } elf_auxv_t;
118
__libc_connect_services(elf_auxv_t * auxv)119 void __libc_connect_services(elf_auxv_t *auxv)
120 {
121 size_t i;
122 unsigned long nr_caps;
123
124 fsm_ipc_struct->conn_cap = 0;
125 fsm_ipc_struct->server_id = FS_MANAGER;
126 lwip_ipc_struct->conn_cap = 0;
127 lwip_ipc_struct->server_id = NET_MANAGER;
128 procmgr_ipc_struct->conn_cap = 0;
129 procmgr_ipc_struct->server_id = PROC_MANAGER;
130
131 for (i = 0; auxv[i].a_type != AT_CHCORE_CAP_CNT; i++)
132 ;
133
134 nr_caps = auxv[i].a_val;
135 if (nr_caps == ENVP_NONE_CAPS) {
136 // printf("%s: connect to zero system services.\n", __func__);
137 return;
138 }
139
140 procmgr_server_cap = (cap_t)(auxv[i + 1].a_val);
141
142 /* Connect to FS only */
143 if ((--nr_caps) == 0)
144 return;
145
146 fsm_server_cap = (cap_t)(auxv[i + 2].a_val);
147
148 /* Connect to FS and NET */
149 if ((--nr_caps) == 0)
150 return;
151
152 lwip_server_cap = (cap_t)(auxv[i + 3].a_val);
153
154 /* Connect to FS, NET, and PROCMGR */
155 // printf("%s: connect FS, NET and PROCMGR\n", __func__);
156 }
157 weak_alias(__libc_connect_services, libc_connect_services);
158
159 /*
160 * This function is local to libc and it will
161 * only be executed once during the libc init time.
162 *
163 * It will be executed in the dynamic loader (for dynamic-apps) or
164 * just before calling user main (for static-apps).
165 * Nevertheless, when loading a dynamic application, it will be invoked twice.
166 * This is why the variable `initialized` is required.
167 */
__libc_chcore_init(void)168 __attribute__((constructor)) void __libc_chcore_init(void)
169 {
170 static int initialized = 0;
171 int fd0, fd1, fd2;
172 struct termios *ts;
173 char *pidstr;
174 size_t i;
175 elf_auxv_t *auxv;
176
177 if (initialized == 1)
178 return;
179 initialized = 1;
180
181 /* Initialize libfs_client */
182 init_fs_client_side();
183
184 /* Open stdin/stdout/stderr */
185 /* STDIN */
186 fd0 = alloc_fd();
187 assert(fd0 == STDIN_FILENO);
188 fd_dic[fd0]->type = FD_TYPE_STDIN;
189 // BUG: this fd0 is a file descriptor, but fd_dic[fd0]->fd should be an
190 // "fid" in fsm.srv
191 fd_dic[fd0]->fd = fd0;
192 fd_dic[fd0]->fd_op = &stdin_ops;
193 /* Set default stdin termios flags */
194 ts = &fd_dic[fd0]->termios;
195 ts->c_iflag = INLCR | ICRNL;
196 ts->c_oflag = OPOST | ONLCR;
197 ts->c_cflag = CS8;
198 ts->c_lflag = ISIG | ICANON | ECHO | ECHOE | NOFLSH;
199 ts->c_cc[VMIN] = 1;
200 ts->c_cc[VTIME] = 0;
201
202 /* STDOUT */
203 fd1 = alloc_fd();
204 assert(fd1 == STDOUT_FILENO);
205 fd_dic[fd1]->type = FD_TYPE_STDOUT;
206 fd_dic[fd1]->fd = fd1;
207 fd_dic[fd1]->fd_op = &stdout_ops;
208
209 /* STDERR */
210 fd2 = alloc_fd();
211 assert(fd2 == STDERR_FILENO);
212 fd_dic[fd2]->type = FD_TYPE_STDERR;
213 fd_dic[fd2]->fd = fd2;
214 fd_dic[fd2]->fd_op = &stderr_ops;
215
216 /* ProcMgr passes PID through env variable */
217 pidstr = getenv("PID");
218 if (pidstr)
219 chcore_pid = atoi(pidstr);
220
221 for (i = 0; __environ[i]; i++)
222 ;
223
224 auxv = (elf_auxv_t *)(__environ + i + 1);
225
226 libc_connect_services(auxv);
227 }
228
chcore_dup2(int a,int b)229 int chcore_dup2(int a, int b)
230 {
231 int ret;
232 ret = 0;
233 if (a == b)
234 return a;
235 if (b >= 0 && b < MAX_FD) {
236 if (fd_dic[b]) {
237 ret = close(b);
238 if (ret != 0) {
239 return -1;
240 }
241 }
242 } else
243 return -1;
244 return chcore_fcntl(a, F_DUPFD, b);
245 }
246
247 /*
248 * LibC may invoke syscall directly through assembly code like:
249 * src/thread/x86_64/__set_thread_area.s
250 *
251 * So, we also need to rewrite those function.
252 */
253
__syscall0(long n)254 long __syscall0(long n)
255 {
256 if (n != SYS_sched_yield)
257 syscall_trace(n);
258
259 switch (n) {
260 case SYS_getppid:
261 warn_once("faked ppid\n");
262 return chcore_pid;
263 case SYS_getpid:
264 return chcore_pid;
265 case SYS_geteuid:
266 warn_once("faked euid\n");
267 return 0; /* root. */
268 case SYS_getuid:
269 warn_once("faked uid\n");
270 return 0; /* root */
271 case SYS_getgid:
272 warn_once("faked gid\n");
273 return 0; /* root */
274 case SYS_sched_yield:
275 chcore_syscall0(CHCORE_SYS_yield);
276 return 0;
277 case SYS_getegid:
278 warn_once("fake egid\n");
279 return 0;
280 case SYS_sync:
281 return chcore_sync();
282 default:
283 dead(n);
284 return chcore_syscall0(n);
285 }
286 }
287
__syscall1(long n,long a)288 long __syscall1(long n, long a)
289 {
290 syscall_trace(n);
291
292 switch (n) {
293 #ifdef SYS_unlink
294 case SYS_unlink:
295 return __syscall3(SYS_unlinkat, AT_FDCWD, a, 0);
296 #endif
297 #ifdef SYS_rmdir
298 case SYS_rmdir:
299 return __syscall3(SYS_unlinkat, AT_FDCWD, a, AT_REMOVEDIR);
300 #endif
301
302 case SYS_close:
303 return chcore_close(a);
304 case SYS_umask:
305 debug("ignore SYS_umask\n");
306 return 0;
307 case SYS_uname: {
308 struct utsname *buf = (struct utsname *)a;
309 strcpy(buf->sysname, "ChCore");
310 strcpy(buf->nodename, "");
311 strcpy(buf->release, "0.0.0");
312 strcpy(buf->version, "0.0.0");
313 strcpy(buf->machine, "");
314 strcpy(buf->domainname, "");
315 return 0;
316 }
317 case SYS_exit:
318 /* Thread exit: a is exitcode */
319 chcore_syscall1(CHCORE_SYS_thread_exit, a);
320 printf("[libc] error: thread_exit should never return.\n");
321 return 0;
322 case SYS_exit_group:
323 /* Group exit: a is exitcode */
324 chcore_syscall1(CHCORE_SYS_exit_group, a);
325 printf("[libc] error: process_exit should never return.\n");
326 return 0;
327 case SYS_set_tid_address: {
328 return usys_get_thread_id(0);
329 }
330 case SYS_brk:
331 return chcore_syscall2(CHCORE_SYS_handle_brk, a, HEAP_START);
332 case SYS_chdir: {
333 return chcore_chdir((const char *)a);
334 }
335 case SYS_fchdir: {
336 return chcore_fchdir(a);
337 } break;
338 case SYS_fsync: {
339 return chcore_fsync(a);
340 }
341 case SYS_fdatasync: {
342 return chcore_fdatasync(a);
343 }
344 case SYS_dup: {
345 return __syscall3(SYS_fcntl, a, F_DUPFD, 0);
346 }
347 case SYS_sysinfo: {
348 warn_once("SYS_sysinfo is not implemented.\n");
349 return -1;
350 }
351 case SYS_epoll_create1:
352 return chcore_epoll_create1(a);
353 #ifdef SYS_pipe
354 case SYS_pipe:
355 return __syscall2(SYS_pipe2, a, 0);
356 #endif
357 default:
358 dead(n);
359 return chcore_syscall1(n, a);
360 }
361 }
362
__syscall2(long n,long a,long b)363 long __syscall2(long n, long a, long b)
364 {
365 int ret;
366 syscall_trace(n);
367
368 switch (n) {
369 #ifdef SYS_stat
370 case SYS_stat:
371 return __syscall4(SYS_newfstatat, AT_FDCWD, a, b, 0);
372 #endif
373 #ifdef SYS_lstat
374 case SYS_lstat:
375 return __syscall4(SYS_newfstatat, AT_FDCWD, a, b, AT_SYMLINK_NOFOLLOW);
376 #endif
377 #ifdef SYS_access
378 case SYS_access:
379 return __syscall4(SYS_faccessat, AT_FDCWD, a, b, 0);
380 #endif
381 #ifdef SYS_rename
382 case SYS_rename:
383 return __syscall4(SYS_renameat, AT_FDCWD, a, AT_FDCWD, b);
384 #endif
385 #ifdef SYS_symlink
386 case SYS_symlink:
387 return __syscall3(SYS_symlinkat, a, AT_FDCWD, b);
388 #endif
389 #ifdef SYS_mkdir
390 case SYS_mkdir:
391 return __syscall3(SYS_mkdirat, AT_FDCWD, a, b);
392 #endif
393 #ifdef SYS_open
394 case SYS_open:
395 return __syscall6(SYS_open, a, b, 0, 0, 0, 0);
396 #endif
397 case SYS_fstat: {
398 if (fd_dic[a] == 0) {
399 return -EBADF;
400 }
401
402 return __xstatxx(FS_REQ_FSTAT,
403 a, /* fd */
404 NULL, /* path */
405 0, /* flags */
406 (struct stat *)b, /* statbuf */
407 sizeof(struct stat) /* bufsize */
408 );
409 }
410 case SYS_statfs: {
411 return __xstatxx(FS_REQ_STATFS,
412 AT_FDCWD, /* fd */
413 (const char *)a, /* path */
414 0, /* flags */
415 (struct statfs *)b, /* statbuf */
416 sizeof(struct statfs) /* bufsize */
417 );
418 }
419 #ifdef SYS_dup2
420 case SYS_dup2: {
421 return chcore_dup2(a, b);
422 }
423 #endif
424 case SYS_fstatfs: {
425 if (fd_dic[a] == 0) {
426 return -EBADF;
427 }
428
429 return __xstatxx(FS_REQ_FSTATFS,
430 a, /* fd */
431 NULL, /* path */
432 0, /* flags */
433 (struct statfs *)b, /* statbuf */
434 sizeof(struct statfs) /* bufsize */
435 );
436 }
437 case SYS_getcwd: {
438 return chcore_getcwd((char *)a, b);
439 }
440 case SYS_ftruncate: {
441 return chcore_ftruncate(a, b);
442 }
443 case SYS_clock_gettime: {
444 return chcore_syscall2(CHCORE_SYS_clock_gettime, a, b);
445 }
446 case SYS_set_robust_list: {
447
448 return 0;
449 }
450 case SYS_munmap: {
451 /* munmap: @a is addr, @b is len */
452 // return chcore_syscall2(CHCORE_SYS_handle_munmap, a, b);
453 return chcore_munmap((void *)a, b);
454 }
455 case SYS_setpgid: {
456 warn_once("setpgid is not implemented.\n");
457 return 0;
458 }
459 case SYS_membarrier: {
460 warn_once("SYS_membarrier is not implmeneted.\n");
461 return 0;
462 }
463 case SYS_getrusage:
464 warn_once("getrusage is not implemented.\n");
465 memset((void *)b, 0, sizeof(struct rusage));
466 return 0;
467 case SYS_fcntl: {
468 return __syscall3(n, a, b, 0);
469 }
470 case SYS_eventfd2: {
471 return chcore_eventfd(a, b);
472 }
473 case SYS_timerfd_create:
474 return chcore_timerfd_create(a, b);
475 #ifdef SYS_timerfd_gettime64
476 case SYS_timerfd_gettime64:
477 #endif
478 case SYS_timerfd_gettime:
479 return chcore_timerfd_gettime(a, (struct itimerspec *)b);
480 case SYS_umount2: {
481 return chcore_umount((const char *)a);
482 }
483 case SYS_kill:
484 return chcore_kill(a, b);
485 default:
486 dead(n);
487 return chcore_syscall2(n, a, b);
488 }
489 }
490
__syscall3(long n,long a,long b,long c)491 long __syscall3(long n, long a, long b, long c)
492 {
493 int ret;
494 /* avoid recurrent invocation */
495 if (n != SYS_writev && n != SYS_ioctl && n != SYS_read)
496 syscall_trace(n);
497
498 switch (n) {
499 #ifdef SYS_readlink
500 case SYS_readlink:
501 return __syscall4(SYS_readlinkat, AT_FDCWD, a, b, c);
502 #endif
503 #ifdef SYS_open
504 case SYS_open:
505 return __syscall6(SYS_open, a, b, c, 0, 0, 0);
506 #endif
507
508 case SYS_readv:
509 return __syscall6(SYS_readv, a, b, c, 0, 0, 0);
510 case SYS_ioctl: {
511 return chcore_ioctl(a, b, (void *)c);
512 }
513 case SYS_writev: {
514 return __syscall6(SYS_writev, a, b, c, 0, 0, 0);
515 }
516 case SYS_read: {
517 return chcore_read((int)a, (void *)b, (size_t)c);
518 }
519 case SYS_sched_getaffinity: {
520 /*
521 * @a: tid, 0 means the calling thread
522 * @b: the size of mask
523 * @c: CPU mask
524 */
525 ret = chcore_syscall1(CHCORE_SYS_get_affinity, a);
526 if (ret >= 0) {
527 CPU_SET(ret, c);
528 return b;
529 } else {
530 /* Fail to get the affinity */
531 return ret;
532 }
533 }
534 case SYS_sched_setaffinity: {
535 /*
536 * @a: tid, 0 means the calling thread
537 * @b: the size of mask
538 * @c: CPU mask
539 */
540 for (size_t i = 0; i < b; ++i) {
541
542 if (CPU_ISSET(i, c)) {
543 return chcore_syscall2(CHCORE_SYS_set_affinity, a, i);
544 }
545 }
546 return -1;
547 }
548 case SYS_lseek: {
549 return chcore_lseek(a, b, c);
550 }
551 case SYS_mkdirat: {
552 return chcore_mkdirat(a, (const char *)b, c);
553 }
554 case SYS_unlinkat: {
555 return chcore_unlinkat(a, (const char *)b, c);
556 }
557 case SYS_symlinkat: {
558 return chcore_symlinkat((const char *)a, b, (const char *)c);
559 }
560 case SYS_getdents64: {
561 return chcore_getdents64(a, (char *)b, c);
562 }
563 case SYS_openat: {
564 return __syscall6(SYS_openat, a, b, c, /* mode */ 0, 0, 0);
565 }
566 case SYS_futex: {
567 /*
568 * XXX: Multiple sys_futex entries as parameter number varies in
569 * different futex ops.
570 */
571 return chcore_futex((int *)a, b, c, NULL, NULL, 0);
572 }
573 case SYS_fcntl: {
574 return chcore_fcntl(a, b, c);
575 }
576 case SYS_fchmodat: {
577 warn_once("SYS_fchmodat is not implemented.\n");
578 return 0;
579 }
580 case SYS_fchown: {
581 warn_once("SYS_fchown is not implemented.\n");
582 return 0;
583 }
584 case SYS_madvise: {
585 warn_once("SYS_madvise is not implemented.\n");
586 return 0;
587 }
588 case SYS_dup3: {
589 return chcore_dup2(a, b);
590 }
591 case SYS_mprotect: {
592 /* mproctect: @a addr, @b len, @c prot */
593 return chcore_syscall3(CHCORE_SYS_handle_mprotect, a, b, c);
594 }
595 case SYS_mincore: {
596
597 // page is in memory)
598 warn("SYS_mincore is not implemented.\n");
599
600 /* mincore: @a addr, @b length, @c vec */
601 size_t size;
602 size_t cnt;
603 size_t i;
604 unsigned char *vec;
605
606 size = ROUND_UP(b, PAGE_SIZE);
607 cnt = size / PAGE_SIZE;
608 vec = (unsigned char *)c;
609
610 for (i = 0; i < cnt; ++i) {
611 vec[i] = (char)1;
612 }
613 return 0;
614 }
615 /**
616 * SYS_ftruncate compat layer (for ABI not forcing 64bit
617 * argument start at even parameters)
618 */
619 case SYS_ftruncate: {
620 return chcore_ftruncate(a, _SYSCALL_LL_REV(b, c));
621 }
622 case SYS_faccessat: {
623 return chcore_faccessat(a, (const char *)b, c, 0);
624 }
625 default:
626 dead(n);
627 return chcore_syscall3(n, a, b, c);
628 }
629 }
630
chcore_waitpid(pid_t pid,int * status,int options,int d)631 pid_t chcore_waitpid(pid_t pid, int *status, int options, int d)
632 {
633 ipc_msg_t *ipc_msg;
634 int ret;
635 struct proc_request pr;
636 struct proc_request *reply_pr;
637
638 /* register_ipc_client is unnecessary here */
639 // procmgr_ipc_struct = ipc_register_client(procmgr_server_cap);
640 // assert(procmgr_ipc_struct);
641
642 ipc_msg = ipc_create_msg(procmgr_ipc_struct, sizeof(struct proc_request));
643 pr.req = PROC_REQ_WAIT;
644 pr.wait.pid = pid;
645
646 ipc_set_msg_data(ipc_msg, &pr, 0, sizeof(pr));
647 /* This ipc_call returns the pid. */
648 ret = ipc_call(procmgr_ipc_struct, ipc_msg);
649 assert(ret);
650 if (ret > 0) {
651 /* Get the actual exit status. */
652 reply_pr = (struct proc_request *)ipc_get_msg_data(ipc_msg);
653 *status = reply_pr->wait.exitstatus;
654 }
655 // debug("pid=%d => exitstatus: %d\n", pid, pr.exitstatus);
656
657 ipc_destroy_msg(ipc_msg);
658 return ret;
659 }
660
__syscall4(long n,long a,long b,long c,long d)661 long __syscall4(long n, long a, long b, long c, long d)
662 {
663 syscall_trace(n);
664
665 switch (n) {
666 case SYS_wait4: {
667 return chcore_waitpid((pid_t)a, (int *)b, (int)c, (int)d);
668 }
669 case SYS_newfstatat: {
670 return __xstatxx(FS_REQ_FSTATAT,
671 a, /* dirfd */
672 (const char *)b, /* path */
673 d, /* flags */
674 (struct stat *)c, /* statbuf */
675 sizeof(struct stat) /* bufsize */
676 );
677 }
678 case SYS_readlinkat: {
679 return chcore_readlinkat(a, (const char *)b, (char *)c, d);
680 }
681 #ifdef SYS_renameat
682 case SYS_renameat: {
683 return chcore_renameat(a, (const char *)b, c, (const char *)d);
684 }
685 #endif
686 case SYS_faccessat:
687 case SYS_faccessat2: {
688 return chcore_faccessat(a, (const char *)b, c, d);
689 }
690 case SYS_fallocate: {
691 return chcore_fallocate(a, b, c, d);
692 }
693 case SYS_futex: {
694 return chcore_futex((int *)a, b, c, (struct timespec *)d, NULL, 0);
695 }
696 case SYS_rt_sigprocmask: {
697 warn_once("SYS_rt_sigprocmask is not implemented.\n");
698 return 0;
699 }
700 case SYS_rt_sigaction: {
701 warn_once("SYS_rt_sigaction is not implemented.\n");
702 return 0;
703 }
704 case SYS_openat: {
705 return __syscall6(SYS_openat, a, b, c, d, 0, 0);
706 }
707 #ifdef SYS_timerfd_settime64
708 case SYS_timerfd_settime64:
709 #endif
710 case SYS_timerfd_settime:
711 return chcore_timerfd_settime(
712 a, b, (struct itimerspec *)c, (struct itimerspec *)d);
713 case SYS_prlimit64: {
714 warn_once("SYS_prlimit64 is not implemented.\n");
715 return -1;
716 }
717 case SYS_utimensat: {
718 warn("SYS_utimensat is implemented.\n");
719 return 0;
720 }
721 /**
722 * SYS_ftruncate compat layer (for ABI forcing 64bit
723 * argument start at even parameters, b would be zero here)
724 */
725 case SYS_ftruncate: {
726 return chcore_ftruncate(a, _SYSCALL_LL_REV(c, d));
727 }
728 case SYS_epoll_ctl:
729 return chcore_epoll_ctl(a, b, c, (struct epoll_event *)d);
730 default:
731 dead(n);
732 // chcore_syscall4(n, a, b, c, d);
733 }
734 }
735
__syscall5(long n,long a,long b,long c,long d,long e)736 long __syscall5(long n, long a, long b, long c, long d, long e)
737 {
738 syscall_trace(n);
739
740 switch (n) {
741 case SYS_statx: {
742 return chcore_statx(a, (const char *)b, c, d, (char *)e);
743 }
744 case SYS_renameat2: {
745 /* Since @e is always zero, it could be ignored. */
746 return chcore_renameat(a, (const char *)b, c, (const char *)d);
747 }
748 case SYS_futex:
749 return chcore_futex((int *)a, b, c, (struct timespec *)d, (int *)e, 0);
750 case SYS_mremap: {
751 warn("SYS_mremap is not implemented.\n");
752 /*
753 * At least, our libc can work without mremap
754 * since it will just try to invoke it and
755 * have backup solution.
756 */
757 errno = -EINVAL;
758 return -1;
759 }
760 case SYS_prctl: {
761 warn_once("SYS_prctl is not implemented\n");
762 return -1;
763 }
764 case SYS_mount: {
765 return chcore_mount((const char *)a,
766 (const char *)b,
767 (const char *)c,
768 (unsigned long)d,
769 (const void *)e);
770 }
771 /**
772 * lseek compat layer(for using and returning 64bit data of lseek()
773 * on 32bit archs)
774 */
775 #ifdef SYS__llseek
776 case SYS__llseek: {
777 off_t off = (off_t)b << 32 | c;
778 off_t ret = chcore_lseek(a, off, e);
779 *(off_t *)d = ret;
780 /**
781 * Intentionally truncated, see unistd/lseek.c
782 */
783 return ret < 0 ? ret : 0;
784 }
785 #endif
786 default:
787 dead(n);
788 return chcore_syscall5(n, a, b, c, d, e);
789 }
790 }
791
__syscall6(long n,long a,long b,long c,long d,long e,long f)792 long __syscall6(long n, long a, long b, long c, long d, long e, long f)
793 {
794 ipc_msg_t *ipc_msg = 0;
795 struct fd_record_extension *fd_ext;
796 struct fs_request fr;
797 ipc_struct_t *_fs_ipc_struct;
798 #ifdef CHCORE_ENABLE_FMAP
799 cap_t fmap_pmo_cap;
800 #endif
801 int ret = 0, fd = 0, len = 0;
802
803 if (n != SYS_io_submit && n != SYS_read)
804 syscall_trace(n);
805
806 switch (n) {
807 case SYS_mmap: {
808
809 if (e != -1) {
810 #ifdef CHCORE_ENABLE_FMAP
811 return (long)chcore_fmap(
812 (void *)a, (size_t)b, (int)c, (int)d, (int)e, (off_t)f);
813 #else
814 printf("The mmap configuration is disabled.\n");
815 return -ENOTSUP;
816 #endif
817 }
818 return (long)chcore_mmap(
819 (void *)a, (size_t)b, (int)c, (int)d, (int)e, (off_t)f);
820 }
821 /**
822 * For mmap to access files larger than 32bits,
823 * the @f argument has been divided by PAGE_SIZE in SYS_mmap2
824 */
825 #ifdef SYS_mmap2
826 case SYS_mmap2: {
827 if (e != -1) {
828 #ifdef CHCORE_ENABLE_FMAP
829 off_t off = (off_t)f * PAGE_SIZE;
830 return (long)chcore_fmap(
831 (void *)a, (size_t)b, (int)c, (int)d, (int)e, off);
832 #else
833 printf("The mmap configuration is disabled.\n");
834 return -ENOTSUP;
835 #endif
836 }
837 return (long)chcore_mmap(
838 (void *)a, (size_t)b, (int)c, (int)d, (int)e, (off_t)f);
839 }
840 #endif
841 case SYS_fsync: {
842 return chcore_fsync(a);
843 }
844 case SYS_fdatasync: {
845 return chcore_fdatasync(a);
846 }
847 case SYS_close: {
848 return chcore_close(a);
849 }
850 case SYS_ioctl: {
851 return chcore_ioctl(a, b, (void *)c);
852 }
853
854 #ifdef SYS_open
855 case SYS_open:
856 return __syscall6(SYS_openat, AT_FDCWD, a, b, c, 0, 0);
857 #endif
858 case SYS_openat: {
859 return chcore_openat(a, (const char *)b, c, d);
860 }
861 case SYS_write: {
862 return chcore_write((int)a, (void *)b, (size_t)c);
863 }
864 case SYS_read: {
865 return chcore_read((int)a, (void *)b, (size_t)c);
866 }
867 case SYS_epoll_pwait:
868 return chcore_epoll_pwait(
869 a, (struct epoll_event *)b, c, d, (sigset_t *)e);
870 #ifdef SYS_poll
871 case SYS_poll:
872 return chcore_poll((struct pollfd *)a, b, c);
873 #endif
874 case SYS_ppoll:
875 return chcore_ppoll(
876 (struct pollfd *)a, b, (struct timespec *)c, (sigset_t *)d);
877 case SYS_futex:
878 return chcore_futex((int *)a, b, c, (struct timespec *)d, (int *)e, f);
879
880 case SYS_readv: {
881 return chcore_readv(a, (const struct iovec *)b, c);
882 }
883 case SYS_writev: {
884 return chcore_writev(a, (const struct iovec *)b, c);
885 }
886 #ifdef SYS_clock_nanosleep_time64
887 case SYS_clock_nanosleep_time64:
888 #else
889 case SYS_clock_nanosleep:
890 #endif
891 /* Currently ChCore only support CLOCK_MONOTONIC */
892 BUG_ON(a != CLOCK_MONOTONIC);
893 BUG_ON(b != 0);
894 return chcore_syscall4(CHCORE_SYS_clock_nanosleep, a, b, c, d);
895 case SYS_nanosleep:
896 /*
897 * In original libc, CLOCK_REALTIME is used.
898 * Neverthelss, ChCore simply uses tick, indicating supporting
899 * CLOCK_MONOTONIC only. It just affects the precision.
900 *
901 * Actually, this flag will not be checked in the kernel.
902 */
903 return chcore_syscall4(
904 CHCORE_SYS_clock_nanosleep, CLOCK_MONOTONIC, 0, a, b);
905 case SYS_getrandom: {
906
907 // it should generate random bytes later.
908 warn("this getrandom is just a fake implementation\n");
909 return b;
910 }
911 case SYS_gettid: {
912 warn("temp impl of gettid\n");
913 return (long)pthread_self();
914 }
915 case SYS_rt_sigtimedwait: {
916 warn_once("SYS_rt_sigtimedwait is not implemented.\n");
917 return 0;
918 }
919 /**
920 * SYS_fallocate compat layer
921 */
922 case SYS_fallocate: {
923 return chcore_fallocate(
924 a, b, _SYSCALL_LL_REV(c, d), _SYSCALL_LL_REV(e, f));
925 }
926 default:
927 dead(n);
928 return chcore_syscall6(n, a, b, c, d, e, f);
929 }
930 }
931
932
dead(long n)933 void dead(long n)
934 {
935 printf("Unsupported syscall %d, bye.\n", n);
936 volatile int *addr = (int *)n;
937 *addr = 0;
938 }
939