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


Reply via email to