xref: /openbmc/qemu/bsd-user/freebsd/os-syscall.c (revision 259ebed4)
1 /*
2  *  BSD syscalls
3  *
4  *  Copyright (c) 2003-2008 Fabrice Bellard
5  *  Copyright (c) 2013-2014 Stacey D. Son
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20 #include "qemu/osdep.h"
21 #include "qemu/cutils.h"
22 #include "qemu/path.h"
23 #include <sys/syscall.h>
24 #include <sys/cdefs.h>
25 #include <sys/param.h>
26 #include <sys/mount.h>
27 #include <sys/sysctl.h>
28 #include <utime.h>
29 
30 #include "include/gdbstub/syscalls.h"
31 
32 #include "qemu.h"
33 #include "signal-common.h"
34 #include "user/syscall-trace.h"
35 
36 /* BSD independent syscall shims */
37 #include "bsd-file.h"
38 #include "bsd-mem.h"
39 #include "bsd-proc.h"
40 
41 /* BSD dependent syscall shims */
42 #include "os-stat.h"
43 #include "os-proc.h"
44 #include "os-misc.h"
45 
46 /* I/O */
47 safe_syscall3(int, open, const char *, path, int, flags, mode_t, mode);
48 safe_syscall4(int, openat, int, fd, const char *, path, int, flags, mode_t,
49     mode);
50 
51 safe_syscall3(ssize_t, read, int, fd, void *, buf, size_t, nbytes);
52 safe_syscall4(ssize_t, pread, int, fd, void *, buf, size_t, nbytes, off_t,
53     offset);
54 safe_syscall3(ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt);
55 safe_syscall4(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt,
56     off_t, offset);
57 
58 safe_syscall3(ssize_t, write, int, fd, void *, buf, size_t, nbytes);
59 safe_syscall4(ssize_t, pwrite, int, fd, void *, buf, size_t, nbytes, off_t,
60     offset);
61 safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt);
62 safe_syscall4(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt,
63     off_t, offset);
64 
65 /* used in os-proc */
66 safe_syscall4(pid_t, wait4, pid_t, wpid, int *, status, int, options,
67     struct rusage *, rusage);
68 safe_syscall6(pid_t, wait6, idtype_t, idtype, id_t, id, int *, status, int,
69     options, struct __wrusage *, wrusage, siginfo_t *, infop);
70 
71 /*
72  * errno conversion.
73  */
74 abi_long get_errno(abi_long ret)
75 {
76     if (ret == -1) {
77         return -host_to_target_errno(errno);
78     } else {
79         return ret;
80     }
81 }
82 
83 int host_to_target_errno(int err)
84 {
85     /*
86      * All the BSDs have the property that the error numbers are uniform across
87      * all architectures for a given BSD, though they may vary between different
88      * BSDs.
89      */
90     return err;
91 }
92 
93 bool is_error(abi_long ret)
94 {
95     return (abi_ulong)ret >= (abi_ulong)(-4096);
96 }
97 
98 /*
99  * Unlocks a iovec. Unlike unlock_iovec, it assumes the tvec array itself is
100  * already locked from target_addr. It will be unlocked as well as all the iovec
101  * elements.
102  */
103 static void helper_unlock_iovec(struct target_iovec *target_vec,
104                                 abi_ulong target_addr, struct iovec *vec,
105                                 int count, int copy)
106 {
107     for (int i = 0; i < count; i++) {
108         abi_ulong base = tswapal(target_vec[i].iov_base);
109 
110         if (vec[i].iov_base) {
111             unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
112         }
113     }
114     unlock_user(target_vec, target_addr, 0);
115 }
116 
117 struct iovec *lock_iovec(int type, abi_ulong target_addr,
118         int count, int copy)
119 {
120     struct target_iovec *target_vec;
121     struct iovec *vec;
122     abi_ulong total_len, max_len;
123     int i;
124     int err = 0;
125 
126     if (count == 0) {
127         errno = 0;
128         return NULL;
129     }
130     if (count < 0 || count > IOV_MAX) {
131         errno = EINVAL;
132         return NULL;
133     }
134 
135     vec = g_try_new0(struct iovec, count);
136     if (vec == NULL) {
137         errno = ENOMEM;
138         return NULL;
139     }
140 
141     target_vec = lock_user(VERIFY_READ, target_addr,
142                            count * sizeof(struct target_iovec), 1);
143     if (target_vec == NULL) {
144         err = EFAULT;
145         goto fail2;
146     }
147 
148     max_len = 0x7fffffff & MIN(TARGET_PAGE_MASK, PAGE_MASK);
149     total_len = 0;
150 
151     for (i = 0; i < count; i++) {
152         abi_ulong base = tswapal(target_vec[i].iov_base);
153         abi_long len = tswapal(target_vec[i].iov_len);
154 
155         if (len < 0) {
156             err = EINVAL;
157             goto fail;
158         } else if (len == 0) {
159             /* Zero length pointer is ignored. */
160             vec[i].iov_base = 0;
161         } else {
162             vec[i].iov_base = lock_user(type, base, len, copy);
163             /*
164              * If the first buffer pointer is bad, this is a fault.  But
165              * subsequent bad buffers will result in a partial write; this is
166              * realized by filling the vector with null pointers and zero
167              * lengths.
168              */
169             if (!vec[i].iov_base) {
170                 if (i == 0) {
171                     err = EFAULT;
172                     goto fail;
173                 } else {
174                     /*
175                      * Fail all the subsequent addresses, they are already
176                      * zero'd.
177                      */
178                     goto out;
179                 }
180             }
181             if (len > max_len - total_len) {
182                 len = max_len - total_len;
183             }
184         }
185         vec[i].iov_len = len;
186         total_len += len;
187     }
188 out:
189     unlock_user(target_vec, target_addr, 0);
190     return vec;
191 
192 fail:
193     helper_unlock_iovec(target_vec, target_addr, vec, i, copy);
194 fail2:
195     g_free(vec);
196     errno = err;
197     return NULL;
198 }
199 
200 void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
201         int count, int copy)
202 {
203     struct target_iovec *target_vec;
204 
205     target_vec = lock_user(VERIFY_READ, target_addr,
206                            count * sizeof(struct target_iovec), 1);
207     if (target_vec) {
208         helper_unlock_iovec(target_vec, target_addr, vec, count, copy);
209     }
210 
211     g_free(vec);
212 }
213 
214 /*
215  * All errnos that freebsd_syscall() returns must be -TARGET_<errcode>.
216  */
217 static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1,
218                                 abi_long arg2, abi_long arg3, abi_long arg4,
219                                 abi_long arg5, abi_long arg6, abi_long arg7,
220                                 abi_long arg8)
221 {
222     abi_long ret;
223 
224     switch (num) {
225         /*
226          * process system calls
227          */
228     case TARGET_FREEBSD_NR_fork: /* fork(2) */
229         ret = do_freebsd_fork(cpu_env);
230         break;
231 
232     case TARGET_FREEBSD_NR_vfork: /* vfork(2) */
233         ret = do_freebsd_vfork(cpu_env);
234         break;
235 
236     case TARGET_FREEBSD_NR_rfork: /* rfork(2) */
237         ret = do_freebsd_rfork(cpu_env, arg1);
238         break;
239 
240     case TARGET_FREEBSD_NR_pdfork: /* pdfork(2) */
241         ret = do_freebsd_pdfork(cpu_env, arg1, arg2);
242         break;
243 
244     case TARGET_FREEBSD_NR_execve: /* execve(2) */
245         ret = do_freebsd_execve(arg1, arg2, arg3);
246         break;
247 
248     case TARGET_FREEBSD_NR_fexecve: /* fexecve(2) */
249         ret = do_freebsd_fexecve(arg1, arg2, arg3);
250         break;
251 
252     case TARGET_FREEBSD_NR_wait4: /* wait4(2) */
253         ret = do_freebsd_wait4(arg1, arg2, arg3, arg4);
254         break;
255 
256     case TARGET_FREEBSD_NR_wait6: /* wait6(2) */
257         ret = do_freebsd_wait6(cpu_env, arg1, arg2, arg3,
258                                arg4, arg5, arg6, arg7, arg8);
259         break;
260 
261     case TARGET_FREEBSD_NR_exit: /* exit(2) */
262         ret = do_bsd_exit(cpu_env, arg1);
263         break;
264 
265     case TARGET_FREEBSD_NR_getgroups: /* getgroups(2) */
266         ret = do_bsd_getgroups(arg1, arg2);
267         break;
268 
269     case TARGET_FREEBSD_NR_setgroups: /* setgroups(2) */
270         ret = do_bsd_setgroups(arg1, arg2);
271         break;
272 
273     case TARGET_FREEBSD_NR_umask: /* umask(2) */
274         ret = do_bsd_umask(arg1);
275         break;
276 
277     case TARGET_FREEBSD_NR_setlogin: /* setlogin(2) */
278         ret = do_bsd_setlogin(arg1);
279         break;
280 
281     case TARGET_FREEBSD_NR_getlogin: /* getlogin(2) */
282         ret = do_bsd_getlogin(arg1, arg2);
283         break;
284 
285     case TARGET_FREEBSD_NR_getrusage: /* getrusage(2) */
286         ret = do_bsd_getrusage(arg1, arg2);
287         break;
288 
289     case TARGET_FREEBSD_NR_getrlimit: /* getrlimit(2) */
290         ret = do_bsd_getrlimit(arg1, arg2);
291         break;
292 
293     case TARGET_FREEBSD_NR_setrlimit: /* setrlimit(2) */
294         ret = do_bsd_setrlimit(arg1, arg2);
295         break;
296 
297     case TARGET_FREEBSD_NR_getpid: /* getpid(2) */
298         ret = do_bsd_getpid();
299         break;
300 
301     case TARGET_FREEBSD_NR_getppid: /* getppid(2) */
302         ret = do_bsd_getppid();
303         break;
304 
305     case TARGET_FREEBSD_NR_getuid: /* getuid(2) */
306         ret = do_bsd_getuid();
307         break;
308 
309     case TARGET_FREEBSD_NR_geteuid: /* geteuid(2) */
310         ret = do_bsd_geteuid();
311         break;
312 
313     case TARGET_FREEBSD_NR_getgid: /* getgid(2) */
314         ret = do_bsd_getgid();
315         break;
316 
317     case TARGET_FREEBSD_NR_getegid: /* getegid(2) */
318         ret = do_bsd_getegid();
319         break;
320 
321     case TARGET_FREEBSD_NR_setuid: /* setuid(2) */
322         ret = do_bsd_setuid(arg1);
323         break;
324 
325     case TARGET_FREEBSD_NR_seteuid: /* seteuid(2) */
326         ret = do_bsd_seteuid(arg1);
327         break;
328 
329     case TARGET_FREEBSD_NR_setgid: /* setgid(2) */
330         ret = do_bsd_setgid(arg1);
331         break;
332 
333     case TARGET_FREEBSD_NR_setegid: /* setegid(2) */
334         ret = do_bsd_setegid(arg1);
335         break;
336 
337     case TARGET_FREEBSD_NR_getpgrp: /* getpgrp(2) */
338         ret = do_bsd_getpgrp();
339         break;
340 
341     case TARGET_FREEBSD_NR_getpgid: /* getpgid(2) */
342          ret = do_bsd_getpgid(arg1);
343          break;
344 
345     case TARGET_FREEBSD_NR_setpgid: /* setpgid(2) */
346          ret = do_bsd_setpgid(arg1, arg2);
347          break;
348 
349     case TARGET_FREEBSD_NR_setreuid: /* setreuid(2) */
350         ret = do_bsd_setreuid(arg1, arg2);
351         break;
352 
353     case TARGET_FREEBSD_NR_setregid: /* setregid(2) */
354         ret = do_bsd_setregid(arg1, arg2);
355         break;
356 
357     case TARGET_FREEBSD_NR_getresuid: /* getresuid(2) */
358         ret = do_bsd_getresuid(arg1, arg2, arg3);
359         break;
360 
361     case TARGET_FREEBSD_NR_getresgid: /* getresgid(2) */
362         ret = do_bsd_getresgid(arg1, arg2, arg3);
363         break;
364 
365     case TARGET_FREEBSD_NR_setresuid: /* setresuid(2) */
366         ret = do_bsd_setresuid(arg1, arg2, arg3);
367         break;
368 
369     case TARGET_FREEBSD_NR_setresgid: /* setresgid(2) */
370         ret = do_bsd_setresgid(arg1, arg2, arg3);
371         break;
372 
373     case TARGET_FREEBSD_NR_getsid: /* getsid(2) */
374         ret = do_bsd_getsid(arg1);
375         break;
376 
377     case TARGET_FREEBSD_NR_setsid: /* setsid(2) */
378         ret = do_bsd_setsid();
379         break;
380 
381     case TARGET_FREEBSD_NR_issetugid: /* issetugid(2) */
382         ret = do_bsd_issetugid();
383         break;
384 
385     case TARGET_FREEBSD_NR_profil: /* profil(2) */
386         ret = do_bsd_profil(arg1, arg2, arg3, arg4);
387         break;
388 
389     case TARGET_FREEBSD_NR_ktrace: /* ktrace(2) */
390         ret = do_bsd_ktrace(arg1, arg2, arg3, arg4);
391         break;
392 
393     case TARGET_FREEBSD_NR_setloginclass: /* setloginclass(2) */
394         ret = do_freebsd_setloginclass(arg1);
395         break;
396 
397     case TARGET_FREEBSD_NR_getloginclass: /* getloginclass(2) */
398         ret = do_freebsd_getloginclass(arg1, arg2);
399         break;
400 
401     case TARGET_FREEBSD_NR_pdgetpid: /* pdgetpid(2) */
402         ret = do_freebsd_pdgetpid(arg1, arg2);
403         break;
404 
405     case TARGET_FREEBSD_NR___setugid: /* undocumented */
406         ret = do_freebsd___setugid(arg1);
407         break;
408 
409     case TARGET_FREEBSD_NR_utrace: /* utrace(2) */
410         ret = do_bsd_utrace(arg1, arg2);
411         break;
412 
413     case TARGET_FREEBSD_NR_ptrace: /* ptrace(2) */
414         ret = do_bsd_ptrace(arg1, arg2, arg3, arg4);
415         break;
416 
417     case TARGET_FREEBSD_NR_getpriority: /* getpriority(2) */
418         ret = do_bsd_getpriority(arg1, arg2);
419         break;
420 
421     case TARGET_FREEBSD_NR_setpriority: /* setpriority(2) */
422         ret = do_bsd_setpriority(arg1, arg2, arg3);
423         break;
424 
425     case TARGET_FREEBSD_NR_procctl: /* procctl(2) */
426         ret = do_freebsd_procctl(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
427         break;
428 
429         /*
430          * File system calls.
431          */
432     case TARGET_FREEBSD_NR_read: /* read(2) */
433         ret = do_bsd_read(arg1, arg2, arg3);
434         break;
435 
436     case TARGET_FREEBSD_NR_pread: /* pread(2) */
437         ret = do_bsd_pread(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
438         break;
439 
440     case TARGET_FREEBSD_NR_readv: /* readv(2) */
441         ret = do_bsd_readv(arg1, arg2, arg3);
442         break;
443 
444     case TARGET_FREEBSD_NR_preadv: /* preadv(2) */
445         ret = do_bsd_preadv(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
446         break;
447 
448     case TARGET_FREEBSD_NR_write: /* write(2) */
449         ret = do_bsd_write(arg1, arg2, arg3);
450         break;
451 
452     case TARGET_FREEBSD_NR_pwrite: /* pwrite(2) */
453         ret = do_bsd_pwrite(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
454         break;
455 
456     case TARGET_FREEBSD_NR_writev: /* writev(2) */
457         ret = do_bsd_writev(arg1, arg2, arg3);
458         break;
459 
460     case TARGET_FREEBSD_NR_pwritev: /* pwritev(2) */
461         ret = do_bsd_pwritev(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
462         break;
463 
464     case TARGET_FREEBSD_NR_open: /* open(2) */
465         ret = do_bsd_open(arg1, arg2, arg3);
466         break;
467 
468     case TARGET_FREEBSD_NR_openat: /* openat(2) */
469         ret = do_bsd_openat(arg1, arg2, arg3, arg4);
470         break;
471 
472     case TARGET_FREEBSD_NR_close: /* close(2) */
473         ret = do_bsd_close(arg1);
474         break;
475 
476     case TARGET_FREEBSD_NR_fdatasync: /* fdatasync(2) */
477         ret = do_bsd_fdatasync(arg1);
478         break;
479 
480     case TARGET_FREEBSD_NR_fsync: /* fsync(2) */
481         ret = do_bsd_fsync(arg1);
482         break;
483 
484     case TARGET_FREEBSD_NR_freebsd12_closefrom: /* closefrom(2) */
485         ret = do_bsd_closefrom(arg1);
486         break;
487 
488     case TARGET_FREEBSD_NR_revoke: /* revoke(2) */
489         ret = do_bsd_revoke(arg1);
490         break;
491 
492     case TARGET_FREEBSD_NR_access: /* access(2) */
493         ret = do_bsd_access(arg1, arg2);
494         break;
495 
496     case TARGET_FREEBSD_NR_eaccess: /* eaccess(2) */
497         ret = do_bsd_eaccess(arg1, arg2);
498         break;
499 
500     case TARGET_FREEBSD_NR_faccessat: /* faccessat(2) */
501         ret = do_bsd_faccessat(arg1, arg2, arg3, arg4);
502         break;
503 
504     case TARGET_FREEBSD_NR_chdir: /* chdir(2) */
505         ret = do_bsd_chdir(arg1);
506         break;
507 
508     case TARGET_FREEBSD_NR_fchdir: /* fchdir(2) */
509         ret = do_bsd_fchdir(arg1);
510         break;
511 
512     case TARGET_FREEBSD_NR_rename: /* rename(2) */
513         ret = do_bsd_rename(arg1, arg2);
514         break;
515 
516     case TARGET_FREEBSD_NR_renameat: /* renameat(2) */
517         ret = do_bsd_renameat(arg1, arg2, arg3, arg4);
518         break;
519 
520     case TARGET_FREEBSD_NR_link: /* link(2) */
521         ret = do_bsd_link(arg1, arg2);
522         break;
523 
524     case TARGET_FREEBSD_NR_linkat: /* linkat(2) */
525         ret = do_bsd_linkat(arg1, arg2, arg3, arg4, arg5);
526         break;
527 
528     case TARGET_FREEBSD_NR_unlink: /* unlink(2) */
529         ret = do_bsd_unlink(arg1);
530         break;
531 
532     case TARGET_FREEBSD_NR_unlinkat: /* unlinkat(2) */
533         ret = do_bsd_unlinkat(arg1, arg2, arg3);
534         break;
535 
536     case TARGET_FREEBSD_NR_mkdir: /* mkdir(2) */
537         ret = do_bsd_mkdir(arg1, arg2);
538         break;
539 
540     case TARGET_FREEBSD_NR_mkdirat: /* mkdirat(2) */
541         ret = do_bsd_mkdirat(arg1, arg2, arg3);
542         break;
543 
544     case TARGET_FREEBSD_NR_rmdir: /* rmdir(2) (XXX no rmdirat()?) */
545         ret = do_bsd_rmdir(arg1);
546         break;
547 
548     case TARGET_FREEBSD_NR___getcwd: /* undocumented __getcwd() */
549         ret = do_bsd___getcwd(arg1, arg2);
550         break;
551 
552     case TARGET_FREEBSD_NR_dup: /* dup(2) */
553         ret = do_bsd_dup(arg1);
554         break;
555 
556     case TARGET_FREEBSD_NR_dup2: /* dup2(2) */
557         ret = do_bsd_dup2(arg1, arg2);
558         break;
559 
560     case TARGET_FREEBSD_NR_truncate: /* truncate(2) */
561         ret = do_bsd_truncate(cpu_env, arg1, arg2, arg3, arg4);
562         break;
563 
564     case TARGET_FREEBSD_NR_ftruncate: /* ftruncate(2) */
565         ret = do_bsd_ftruncate(cpu_env, arg1, arg2, arg3, arg4);
566         break;
567 
568     case TARGET_FREEBSD_NR_acct: /* acct(2) */
569         ret = do_bsd_acct(arg1);
570         break;
571 
572     case TARGET_FREEBSD_NR_sync: /* sync(2) */
573         ret = do_bsd_sync();
574         break;
575 
576     case TARGET_FREEBSD_NR_mount: /* mount(2) */
577         ret = do_bsd_mount(arg1, arg2, arg3, arg4);
578         break;
579 
580     case TARGET_FREEBSD_NR_unmount: /* unmount(2) */
581         ret = do_bsd_unmount(arg1, arg2);
582         break;
583 
584     case TARGET_FREEBSD_NR_nmount: /* nmount(2) */
585         ret = do_bsd_nmount(arg1, arg2, arg3);
586         break;
587 
588     case TARGET_FREEBSD_NR_symlink: /* symlink(2) */
589         ret = do_bsd_symlink(arg1, arg2);
590         break;
591 
592     case TARGET_FREEBSD_NR_symlinkat: /* symlinkat(2) */
593         ret = do_bsd_symlinkat(arg1, arg2, arg3);
594         break;
595 
596     case TARGET_FREEBSD_NR_readlink: /* readlink(2) */
597         ret = do_bsd_readlink(cpu_env, arg1, arg2, arg3);
598         break;
599 
600     case TARGET_FREEBSD_NR_readlinkat: /* readlinkat(2) */
601         ret = do_bsd_readlinkat(arg1, arg2, arg3, arg4);
602         break;
603 
604     case TARGET_FREEBSD_NR_chmod: /* chmod(2) */
605         ret = do_bsd_chmod(arg1, arg2);
606         break;
607 
608     case TARGET_FREEBSD_NR_fchmod: /* fchmod(2) */
609         ret = do_bsd_fchmod(arg1, arg2);
610         break;
611 
612     case TARGET_FREEBSD_NR_lchmod: /* lchmod(2) */
613         ret = do_bsd_lchmod(arg1, arg2);
614         break;
615 
616     case TARGET_FREEBSD_NR_fchmodat: /* fchmodat(2) */
617         ret = do_bsd_fchmodat(arg1, arg2, arg3, arg4);
618         break;
619 
620     case TARGET_FREEBSD_NR_freebsd11_mknod: /* mknod(2) */
621         ret = do_bsd_freebsd11_mknod(arg1, arg2, arg3);
622         break;
623 
624     case TARGET_FREEBSD_NR_freebsd11_mknodat: /* mknodat(2) */
625         ret = do_bsd_freebsd11_mknodat(arg1, arg2, arg3, arg4);
626         break;
627 
628     case TARGET_FREEBSD_NR_mknodat: /* mknodat(2) */
629         ret = do_bsd_mknodat(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
630         break;
631 
632     case TARGET_FREEBSD_NR_chown: /* chown(2) */
633         ret = do_bsd_chown(arg1, arg2, arg3);
634         break;
635 
636     case TARGET_FREEBSD_NR_fchown: /* fchown(2) */
637         ret = do_bsd_fchown(arg1, arg2, arg3);
638         break;
639 
640     case TARGET_FREEBSD_NR_lchown: /* lchown(2) */
641         ret = do_bsd_lchown(arg1, arg2, arg3);
642         break;
643 
644     case TARGET_FREEBSD_NR_fchownat: /* fchownat(2) */
645         ret = do_bsd_fchownat(arg1, arg2, arg3, arg4, arg5);
646         break;
647 
648     case TARGET_FREEBSD_NR_chflags: /* chflags(2) */
649         ret = do_bsd_chflags(arg1, arg2);
650         break;
651 
652     case TARGET_FREEBSD_NR_lchflags: /* lchflags(2) */
653         ret = do_bsd_lchflags(arg1, arg2);
654         break;
655 
656     case TARGET_FREEBSD_NR_fchflags: /* fchflags(2) */
657         ret = do_bsd_fchflags(arg1, arg2);
658         break;
659 
660     case TARGET_FREEBSD_NR_chroot: /* chroot(2) */
661         ret = do_bsd_chroot(arg1);
662         break;
663 
664     case TARGET_FREEBSD_NR_flock: /* flock(2) */
665         ret = do_bsd_flock(arg1, arg2);
666         break;
667 
668     case TARGET_FREEBSD_NR_mkfifo: /* mkfifo(2) */
669         ret = do_bsd_mkfifo(arg1, arg2);
670         break;
671 
672     case TARGET_FREEBSD_NR_mkfifoat: /* mkfifoat(2) */
673         ret = do_bsd_mkfifoat(arg1, arg2, arg3);
674         break;
675 
676     case TARGET_FREEBSD_NR_pathconf: /* pathconf(2) */
677         ret = do_bsd_pathconf(arg1, arg2);
678         break;
679 
680     case TARGET_FREEBSD_NR_lpathconf: /* lpathconf(2) */
681         ret = do_bsd_lpathconf(arg1, arg2);
682         break;
683 
684     case TARGET_FREEBSD_NR_fpathconf: /* fpathconf(2) */
685         ret = do_bsd_fpathconf(arg1, arg2);
686         break;
687 
688     case TARGET_FREEBSD_NR_undelete: /* undelete(2) */
689         ret = do_bsd_undelete(arg1);
690         break;
691 
692         /*
693          * stat system calls
694          */
695     case TARGET_FREEBSD_NR_freebsd11_stat: /* stat(2) */
696         ret = do_freebsd11_stat(arg1, arg2);
697         break;
698 
699     case TARGET_FREEBSD_NR_freebsd11_lstat: /* lstat(2) */
700         ret = do_freebsd11_lstat(arg1, arg2);
701         break;
702 
703     case TARGET_FREEBSD_NR_freebsd11_fstat: /* fstat(2) */
704         ret = do_freebsd11_fstat(arg1, arg2);
705         break;
706 
707     case TARGET_FREEBSD_NR_fstat: /* fstat(2) */
708         ret = do_freebsd_fstat(arg1, arg2);
709         break;
710 
711     case TARGET_FREEBSD_NR_freebsd11_fstatat: /* fstatat(2) */
712         ret = do_freebsd11_fstatat(arg1, arg2, arg3, arg4);
713         break;
714 
715     case TARGET_FREEBSD_NR_fstatat: /* fstatat(2) */
716         ret = do_freebsd_fstatat(arg1, arg2, arg3, arg4);
717         break;
718 
719     case TARGET_FREEBSD_NR_freebsd11_nstat: /* undocumented */
720         ret = do_freebsd11_nstat(arg1, arg2);
721         break;
722 
723     case TARGET_FREEBSD_NR_freebsd11_nfstat: /* undocumented */
724         ret = do_freebsd11_nfstat(arg1, arg2);
725         break;
726 
727     case TARGET_FREEBSD_NR_freebsd11_nlstat: /* undocumented */
728         ret = do_freebsd11_nlstat(arg1, arg2);
729         break;
730 
731     case TARGET_FREEBSD_NR_getfh: /* getfh(2) */
732         ret = do_freebsd_getfh(arg1, arg2);
733         break;
734 
735     case TARGET_FREEBSD_NR_lgetfh: /* lgetfh(2) */
736         ret = do_freebsd_lgetfh(arg1, arg2);
737         break;
738 
739     case TARGET_FREEBSD_NR_fhopen: /* fhopen(2) */
740         ret = do_freebsd_fhopen(arg1, arg2);
741         break;
742 
743     case TARGET_FREEBSD_NR_freebsd11_fhstat: /* fhstat(2) */
744         ret = do_freebsd11_fhstat(arg1, arg2);
745         break;
746 
747     case TARGET_FREEBSD_NR_fhstat: /* fhstat(2) */
748         ret = do_freebsd_fhstat(arg1, arg2);
749         break;
750 
751     case TARGET_FREEBSD_NR_freebsd11_fhstatfs: /* fhstatfs(2) */
752         ret = do_freebsd11_fhstatfs(arg1, arg2);
753         break;
754 
755     case TARGET_FREEBSD_NR_fhstatfs: /* fhstatfs(2) */
756         ret = do_freebsd_fhstatfs(arg1, arg2);
757         break;
758 
759     case TARGET_FREEBSD_NR_freebsd11_statfs: /* statfs(2) */
760         ret = do_freebsd11_statfs(arg1, arg2);
761         break;
762 
763     case TARGET_FREEBSD_NR_statfs: /* statfs(2) */
764         ret = do_freebsd_statfs(arg1, arg2);
765         break;
766 
767     case TARGET_FREEBSD_NR_freebsd11_fstatfs: /* fstatfs(2) */
768         ret = do_freebsd11_fstatfs(arg1, arg2);
769         break;
770 
771     case TARGET_FREEBSD_NR_fstatfs: /* fstatfs(2) */
772         ret = do_freebsd_fstatfs(arg1, arg2);
773         break;
774 
775     case TARGET_FREEBSD_NR_freebsd11_getfsstat: /* getfsstat(2) */
776         ret = do_freebsd11_getfsstat(arg1, arg2, arg3);
777         break;
778 
779     case TARGET_FREEBSD_NR_getfsstat: /* getfsstat(2) */
780         ret = do_freebsd_getfsstat(arg1, arg2, arg3);
781         break;
782 
783     case TARGET_FREEBSD_NR_freebsd11_getdents: /* getdents(2) */
784         ret = do_freebsd11_getdents(arg1, arg2, arg3);
785         break;
786 
787     case TARGET_FREEBSD_NR_getdirentries: /* getdirentries(2) */
788         ret = do_freebsd_getdirentries(arg1, arg2, arg3, arg4);
789         break;
790 
791     case TARGET_FREEBSD_NR_freebsd11_getdirentries: /* getdirentries(2) */
792         ret = do_freebsd11_getdirentries(arg1, arg2, arg3, arg4);
793         break;
794     case TARGET_FREEBSD_NR_fcntl: /* fcntl(2) */
795         ret = do_freebsd_fcntl(arg1, arg2, arg3);
796         break;
797 
798         /*
799          * Memory management system calls.
800          */
801     case TARGET_FREEBSD_NR_mmap: /* mmap(2) */
802         ret = do_bsd_mmap(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
803                           arg8);
804         break;
805 
806     case TARGET_FREEBSD_NR_munmap: /* munmap(2) */
807         ret = do_bsd_munmap(arg1, arg2);
808         break;
809 
810     case TARGET_FREEBSD_NR_mprotect: /* mprotect(2) */
811         ret = do_bsd_mprotect(arg1, arg2, arg3);
812         break;
813 
814     case TARGET_FREEBSD_NR_msync: /* msync(2) */
815         ret = do_bsd_msync(arg1, arg2, arg3);
816         break;
817 
818     case TARGET_FREEBSD_NR_mlock: /* mlock(2) */
819         ret = do_bsd_mlock(arg1, arg2);
820         break;
821 
822     case TARGET_FREEBSD_NR_munlock: /* munlock(2) */
823         ret = do_bsd_munlock(arg1, arg2);
824         break;
825 
826     case TARGET_FREEBSD_NR_mlockall: /* mlockall(2) */
827         ret = do_bsd_mlockall(arg1);
828         break;
829 
830     case TARGET_FREEBSD_NR_munlockall: /* munlockall(2) */
831         ret = do_bsd_munlockall();
832         break;
833 
834     case TARGET_FREEBSD_NR_madvise: /* madvise(2) */
835         ret = do_bsd_madvise(arg1, arg2, arg3);
836         break;
837 
838     case TARGET_FREEBSD_NR_minherit: /* minherit(2) */
839         ret = do_bsd_minherit(arg1, arg2, arg3);
840         break;
841 
842     case TARGET_FREEBSD_NR_mincore: /* mincore(2) */
843         ret = do_bsd_mincore(arg1, arg2, arg3);
844         break;
845 
846     case TARGET_FREEBSD_NR_freebsd12_shm_open: /* shm_open(2) */
847         ret = do_bsd_shm_open(arg1, arg2, arg3);
848         break;
849 
850 #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048
851     case TARGET_FREEBSD_NR_shm_open2: /* shm_open2(2) */
852         ret = do_freebsd_shm_open2(arg1, arg2, arg3, arg4, arg5);
853         break;
854 #endif
855 
856 #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300049
857     case TARGET_FREEBSD_NR_shm_rename: /* shm_rename(2) */
858         ret = do_freebsd_shm_rename(arg1, arg2, arg3);
859         break;
860 #endif
861 
862     case TARGET_FREEBSD_NR_shm_unlink: /* shm_unlink(2) */
863         ret = do_bsd_shm_unlink(arg1);
864         break;
865 
866     case TARGET_FREEBSD_NR_shmget: /* shmget(2) */
867         ret = do_bsd_shmget(arg1, arg2, arg3);
868         break;
869 
870     case TARGET_FREEBSD_NR_shmctl: /* shmctl(2) */
871         ret = do_bsd_shmctl(arg1, arg2, arg3);
872         break;
873 
874     case TARGET_FREEBSD_NR_shmat: /* shmat(2) */
875         ret = do_bsd_shmat(arg1, arg2, arg3);
876         break;
877 
878     case TARGET_FREEBSD_NR_shmdt: /* shmdt(2) */
879         ret = do_bsd_shmdt(arg1);
880         break;
881 
882     case TARGET_FREEBSD_NR_freebsd11_vadvise:
883         ret = do_bsd_vadvise();
884         break;
885 
886     case TARGET_FREEBSD_NR_sbrk:
887         ret = do_bsd_sbrk();
888         break;
889 
890     case TARGET_FREEBSD_NR_sstk:
891         ret = do_bsd_sstk();
892         break;
893 
894         /*
895          * Misc
896          */
897     case TARGET_FREEBSD_NR_break:
898         ret = do_obreak(arg1);
899         break;
900 
901         /*
902          * sys{ctl, arch, call}
903          */
904     case TARGET_FREEBSD_NR___sysctl: /* sysctl(3) */
905         ret = do_freebsd_sysctl(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
906         break;
907 
908     case TARGET_FREEBSD_NR___sysctlbyname: /* sysctlbyname(2) */
909         ret = do_freebsd_sysctlbyname(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
910         break;
911 
912     case TARGET_FREEBSD_NR_sysarch: /* sysarch(2) */
913         ret = do_freebsd_sysarch(cpu_env, arg1, arg2);
914         break;
915 
916     default:
917         qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
918         ret = -TARGET_ENOSYS;
919         break;
920     }
921 
922     return ret;
923 }
924 
925 /*
926  * do_freebsd_syscall() should always have a single exit point at the end so
927  * that actions, such as logging of syscall results, can be performed. This
928  * as a wrapper around freebsd_syscall() so that actually happens. Since
929  * that is a singleton, modern compilers will inline it anyway...
930  */
931 abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
932                             abi_long arg2, abi_long arg3, abi_long arg4,
933                             abi_long arg5, abi_long arg6, abi_long arg7,
934                             abi_long arg8)
935 {
936     abi_long ret;
937 
938     if (do_strace) {
939         print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
940     }
941 
942     ret = freebsd_syscall(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6,
943                           arg7, arg8);
944     if (do_strace) {
945         print_freebsd_syscall_ret(num, ret);
946     }
947 
948     return ret;
949 }
950 
951 void syscall_init(void)
952 {
953 }
954