• 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 
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