Add do_bsd_poll, do_bsd_lseek, do_bsd_pipe, do_bsd_swapon, do_freebsd13_swapoff, and do_bsd_swapoff to bsd-file.h. Also add target_pollfd structure to syscall_defs.h and include poll.h in os-syscall.c.
Signed-off-by: Stacey Son <[email protected]> Assisted-by: Claude Opus 4.6 (1M context) Reviewed-by: Pierrick Bouvier <[email protected]> Acked-by: Richard Henderson <[email protected]> Signed-off-by: Warner Losh <[email protected]> --- bsd-user/bsd-file.h | 136 ++++++++++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-file.h | 26 ++++++++ bsd-user/freebsd/os-syscall.c | 34 +++++++++++ bsd-user/syscall_defs.h | 6 ++ 4 files changed, 202 insertions(+) diff --git a/bsd-user/bsd-file.h b/bsd-user/bsd-file.h index 7ef9470c4e..0fefc07232 100644 --- a/bsd-user/bsd-file.h +++ b/bsd-user/bsd-file.h @@ -55,6 +55,10 @@ ssize_t safe_pwrite(int fd, void *buf, size_t nbytes, off_t offset); ssize_t safe_writev(int fd, const struct iovec *iov, int iovcnt); ssize_t safe_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset); +int safe_ppoll(struct pollfd *fds, nfds_t nfds, + const struct timespec *restrict timeout, + const sigset_t *restrict newsigmask); + /* read(2) */ static abi_long do_bsd_read(abi_long arg1, abi_long arg2, abi_long arg3) { @@ -925,4 +929,136 @@ static abi_long do_bsd_undelete(abi_long arg1) return ret; } +/* poll(2) */ +static abi_long do_bsd_poll(abi_long arg1, abi_long arg2, abi_long arg3) +{ + abi_long ret; + nfds_t i, nfds = arg2; + int timeout = arg3; + struct pollfd *pfd; + struct target_pollfd *target_pfd; + struct timespec ts, *pts = NULL; + + target_pfd = lock_user(VERIFY_WRITE, arg1, + sizeof(struct target_pollfd) * nfds, 1); + if (!target_pfd) { + return -TARGET_EFAULT; + } + pfd = alloca(sizeof(struct pollfd) * nfds); + for (i = 0; i < nfds; i++) { + pfd[i].fd = tswap32(target_pfd[i].fd); + pfd[i].events = tswap16(target_pfd[i].events); + } + + if (timeout != INFTIM) { + ts.tv_sec = timeout / 1000; + ts.tv_nsec = (timeout % 1000) * 1000000; + pts = &ts; + } + + ret = get_errno(safe_ppoll(pfd, nfds, pts, NULL)); + + if (!is_error(ret)) { + for (i = 0; i < nfds; i++) { + target_pfd[i].revents = tswap16(pfd[i].revents); + } + } + unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds); + + return ret; +} + +/* lseek(2) */ +static abi_long do_bsd_lseek(CPUArchState *env, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + abi_long ret; +#if TARGET_ABI_BITS == 32 + int64_t res; + + /* 32-bit arch's use two 32 registers for 64 bit return value */ + if (regpairs_aligned(env) != 0) { + res = lseek(arg1, target_arg64(arg3, arg4), arg5); + } else { + res = lseek(arg1, target_arg64(arg2, arg3), arg4); + } + if (res == -1) { + ret = get_errno(res); + set_second_rval(env, 0xFFFFFFFF); + } else { +#ifdef TARGET_BIG_ENDIAN + ret = ((res >> 32) & 0xFFFFFFFF); + set_second_rval(env, res & 0xFFFFFFFF); +#else + ret = res & 0xFFFFFFFF; + set_second_rval(env, (res >> 32) & 0xFFFFFFFF); +#endif + } +#else + ret = get_errno(lseek(arg1, arg2, arg3)); +#endif + return ret; +} + +/* pipe(2) */ +static abi_long do_bsd_pipe(CPUArchState *env, abi_ulong pipedes) +{ + abi_long ret; + int host_pipe[2]; + int host_ret = pipe(host_pipe); + + if (host_ret != -1) { + set_second_rval(env, host_pipe[1]); + ret = host_pipe[0]; + } else { + ret = get_errno(host_ret); + } + return ret; +} + +/* swapon(2) */ +static abi_long do_bsd_swapon(abi_long arg1) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(swapon(path(p))); + UNLOCK_PATH(p, arg1); + + return ret; +} + +#ifdef TARGET_FREEBSD_NR_freebsd13_swapoff +/* swapoff(2) */ +static abi_long do_freebsd13_swapoff(abi_long arg1) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(swapoff(path(p), 0)); + UNLOCK_PATH(p, arg1); + + return ret; +} +#endif + +/* swapoff(2) */ +static abi_long do_bsd_swapoff(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); +#ifdef TARGET_FREEBSD_NR_freebsd13_swapoff + ret = get_errno(swapoff(path(p), arg2)); +#else + ret = get_errno(swapoff(path(p))); +#endif + UNLOCK_PATH(p, arg1); + + return ret; +} + #endif /* BSD_FILE_H */ diff --git a/bsd-user/freebsd/os-file.h b/bsd-user/freebsd/os-file.h index d5d91336ea..c1da52789a 100644 --- a/bsd-user/freebsd/os-file.h +++ b/bsd-user/freebsd/os-file.h @@ -14,6 +14,32 @@ * Asynchronous I/O. */ +/* pipe2(2) */ +static abi_long do_bsd_pipe2(CPUArchState *env, abi_ulong pipedes, int flags) +{ + int host_pipe[2]; + int host_ret = pipe2(host_pipe, flags); + /* XXXss - flags should be translated from target to host. */ + + if (host_ret == -1) { + return get_errno(host_ret); + } + + /* + * pipe2() returns it's second FD by copying it back to userspace and not in + * a second register like pipe(2): set_second_rval(env, host_pipe[1]); + * + * Copy the FD's back to userspace: + */ + if (put_user_s32(host_pipe[0], pipedes) || + put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0]))) { + close(host_pipe[0]); + close(host_pipe[1]); + return -TARGET_EFAULT; + } + return 0; +} + /* chflagsat(2) */ static inline abi_long do_bsd_chflagsat(int fd, abi_ulong path, abi_ulong flags, int atflags) diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 4fc230e8e5..228daed4c4 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -26,6 +26,7 @@ #include <sys/mount.h> #include <sys/sysctl.h> #include <utime.h> +#include <poll.h> #include "include/gdbstub/syscalls.h" @@ -66,6 +67,9 @@ safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt); safe_syscall4(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt, off_t, offset); +safe_syscall4(int, ppoll, struct pollfd *, fds, nfds_t, nfds, + const struct timespec *, restrict_timeout, const sigset_t *, + restrict_newsigmask); safe_syscall6(ssize_t, copy_file_range, int, infd, off_t *, inoffp, int, outfd, off_t *, outoffp, size_t, len, unsigned int, flags); @@ -696,6 +700,36 @@ static abi_long freebsd_syscall(CPUArchState *env, int num, abi_long arg1, ret = do_bsd_undelete(arg1); break; + case TARGET_FREEBSD_NR_poll: /* poll(2) */ + ret = do_bsd_poll(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_lseek: /* lseek(2) */ + ret = do_bsd_lseek(env, arg1, arg2, arg3, arg4, arg5); + break; + + case TARGET_FREEBSD_NR_freebsd10_pipe: /* pipe(2) */ + ret = do_bsd_pipe(env, arg1); + break; + + case TARGET_FREEBSD_NR_pipe2: /* pipe2(2) */ + ret = do_bsd_pipe2(env, arg1, arg2); + break; + + case TARGET_FREEBSD_NR_swapon: /* swapon(2) */ + ret = do_bsd_swapon(arg1); + break; + +#if TARGET_FREEBSD_NR_freebsd13_swapoff + case TARGET_FREEBSD_NR_freebsd13_swapoff: /* freebsd13_swapoff(2) */ + ret = do_freebsd13_swapoff(arg1); + break; +#endif + + case TARGET_FREEBSD_NR_swapoff: /* swapoff(2) */ + ret = do_bsd_swapoff(arg1, arg2); + break; + case TARGET_FREEBSD_NR_chflagsat: /* chflagsat(2) */ ret = do_bsd_chflagsat(arg1, arg2, arg3, arg4); break; diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h index 88dd7a763a..75122ad521 100644 --- a/bsd-user/syscall_defs.h +++ b/bsd-user/syscall_defs.h @@ -547,6 +547,12 @@ struct target_in_addr { #define safe_ioctl(...) safe_syscall(SYS_ioctl, __VA_ARGS__) #define safe_fcntl(...) safe_syscall(SYS_fcntl, __VA_ARGS__) +struct target_pollfd { + int32_t fd; /* file descriptor */ + int16_t events; /* requested events */ + int16_t revents; /* returned events */ +}; + /* So far all target and host bitmasks are the same */ #undef target_to_host_bitmask #define target_to_host_bitmask(x, tbl) (x) -- 2.55.0
