Patchwork [12/23] bsd-user: add shims for time related system calls.

login
register
mail settings
Submitter Stacey Son
Date June 24, 2013, 2:03 a.m.
Message ID <1372039435-41921-13-git-send-email-sson@FreeBSD.org>
Download mbox | patch
Permalink /patch/253917/
State New
Headers show

Comments

Stacey Son - June 24, 2013, 2:03 a.m.
This change adds support for time related system calls that are largely
FreeBSD dependent because  time_t is inconsistly defined for the various *BSD's.
On FreeBSD time_t is mostly defined as a 64-bit value.  On some architectures
like PPC32 it is defined as a 32-bit value, however.  On NetBSD it is always
defined as an int64_t.  On OpenBSD it is defined as an int. This change also
defines system call shim stubs for NetBSD/OpenBSD in case some whats to add
code to emulate FreeBSD binaries on one of the other *BSD's.

Signed-off-by: Stacey Son <sson@FreeBSD.org>
---
 bsd-user/Makefile.objs     |    2 +-
 bsd-user/freebsd/os-time.c |  205 +++++++++++++++
 bsd-user/freebsd/os-time.h |  602 ++++++++++++++++++++++++++++++++++++++++++++
 bsd-user/freebsd/qemu-os.h |   41 +++
 bsd-user/netbsd/os-time.c  |    1 +
 bsd-user/netbsd/os-time.h  |  179 +++++++++++++
 bsd-user/netbsd/qemu-os.h  |    1 +
 bsd-user/openbsd/os-time.c |    1 +
 bsd-user/openbsd/os-time.h |  179 +++++++++++++
 bsd-user/openbsd/qemu-os.h |    1 +
 bsd-user/syscall.c         |   96 +++++++
 bsd-user/syscall_defs.h    |   76 ++++++
 12 files changed, 1383 insertions(+), 1 deletions(-)
 create mode 100644 bsd-user/freebsd/os-time.c
 create mode 100644 bsd-user/freebsd/os-time.h
 create mode 100644 bsd-user/freebsd/qemu-os.h
 create mode 100644 bsd-user/netbsd/os-time.c
 create mode 100644 bsd-user/netbsd/os-time.h
 create mode 100644 bsd-user/netbsd/qemu-os.h
 create mode 100644 bsd-user/openbsd/os-time.c
 create mode 100644 bsd-user/openbsd/os-time.h
 create mode 100644 bsd-user/openbsd/qemu-os.h

Patch

diff --git a/bsd-user/Makefile.objs b/bsd-user/Makefile.objs
index d0cea36..4c6acb0 100644
--- a/bsd-user/Makefile.objs
+++ b/bsd-user/Makefile.objs
@@ -1,2 +1,2 @@ 
 obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \
-	        uaccess.o bsd-mem.o
+	        uaccess.o bsd-mem.o $(TARGET_OS)/os-time.o
diff --git a/bsd-user/freebsd/os-time.c b/bsd-user/freebsd/os-time.c
new file mode 100644
index 0000000..7ac4397
--- /dev/null
+++ b/bsd-user/freebsd/os-time.c
@@ -0,0 +1,205 @@ 
+/*
+ *  FreeBSD time related system call helpers
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <time.h>
+#include <sys/timex.h>
+#include <sys/select.h>
+
+#include "qemu.h"
+#include "qemu-os.h"
+
+/*
+ * FreeBSD time conversion functions
+ */
+abi_long t2h_freebsd_timeval(struct timeval *tv, abi_ulong target_tv_addr)
+{
+    struct target_freebsd_timeval *target_tv;
+
+    if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+    __get_user(tv->tv_sec, &target_tv->tv_sec);
+    __get_user(tv->tv_usec, &target_tv->tv_usec);
+    unlock_user_struct(target_tv, target_tv_addr, 1);
+
+    return 0;
+}
+
+abi_long h2t_freebsd_timeval(struct timeval *tv, abi_ulong target_tv_addr)
+{
+    struct target_freebsd_timeval *target_tv;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+    __put_user(tv->tv_sec, &target_tv->tv_sec);
+    __put_user(tv->tv_usec, &target_tv->tv_usec);
+    unlock_user_struct(target_tv, target_tv_addr, 1);
+
+    return 0;
+}
+
+abi_long t2h_freebsd_timespec(struct timespec *ts, abi_ulong target_ts_addr)
+{
+    struct target_freebsd_timespec *target_ts;
+
+    if (!lock_user_struct(VERIFY_READ, target_ts, target_ts_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+    __get_user(ts->tv_sec, &target_ts->tv_sec);
+    __get_user(ts->tv_nsec, &target_ts->tv_nsec);
+    unlock_user_struct(target_ts, target_ts_addr, 1);
+
+    return 0;
+}
+
+abi_long h2t_freebsd_timespec(abi_ulong target_ts_addr, struct timespec *ts)
+{
+    struct target_freebsd_timespec *target_ts;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_ts, target_ts_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+    __put_user(ts->tv_sec, &target_ts->tv_sec);
+    __put_user(ts->tv_nsec, &target_ts->tv_nsec);
+    unlock_user_struct(target_ts, target_ts_addr, 1);
+
+    return 0;
+}
+
+abi_long t2h_freebsd_timex(struct timex *host_tx, abi_ulong target_tx_addr)
+{
+    struct target_freebsd_timex *target_tx;
+
+    if (!lock_user_struct(VERIFY_READ, target_tx, target_tx_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+    __get_user(host_tx->modes, &target_tx->modes);
+    __get_user(host_tx->offset, &target_tx->offset);
+    __get_user(host_tx->freq, &target_tx->freq);
+    __get_user(host_tx->maxerror, &target_tx->maxerror);
+    __get_user(host_tx->esterror, &target_tx->esterror);
+    __get_user(host_tx->status, &target_tx->status);
+    __get_user(host_tx->constant, &target_tx->constant);
+    __get_user(host_tx->precision, &target_tx->precision);
+    __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
+    __get_user(host_tx->jitter, &target_tx->jitter);
+    __get_user(host_tx->shift, &target_tx->shift);
+    __get_user(host_tx->stabil, &target_tx->stabil);
+    __get_user(host_tx->jitcnt, &target_tx->jitcnt);
+    __get_user(host_tx->calcnt, &target_tx->calcnt);
+    __get_user(host_tx->errcnt, &target_tx->errcnt);
+    __get_user(host_tx->stbcnt, &target_tx->stbcnt);
+    unlock_user_struct(target_tx, target_tx_addr, 1);
+
+    return 0;
+}
+
+abi_long h2t_freebsd_ntptimeval(abi_ulong target_ntv_addr,
+        struct ntptimeval *ntv)
+{
+    struct target_freebsd_ntptimeval *target_ntv;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_ntv, target_ntv_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+    __put_user(ntv->time.tv_sec, &target_ntv->time.tv_sec);
+    __put_user(ntv->time.tv_nsec, &target_ntv->time.tv_nsec);
+    __put_user(ntv->maxerror, &target_ntv->maxerror);
+    __put_user(ntv->esterror, &target_ntv->esterror);
+    __put_user(ntv->tai, &target_ntv->tai);
+    __put_user(ntv->time_state, &target_ntv->time_state);
+
+    return 0;
+}
+
+/*
+ * select(2) fdset copy functions
+ */
+abi_ulong copy_from_user_fdset(fd_set *fds, abi_ulong target_fds_addr, int n)
+{
+    int i, nw, j, k;
+    abi_ulong b, *target_fds;
+
+    nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
+    target_fds = lock_user(VERIFY_READ, target_fds_addr,
+            sizeof(abi_ulong) * nw, 1);
+    if (target_fds == NULL) {
+        return -TARGET_EFAULT;
+    }
+    FD_ZERO(fds);
+    k = 0;
+    for (i = 0; i < nw; i++) {
+        /* grab the abi_ulong */
+        __get_user(b, &target_fds[i]);
+        for (j = 0; j < TARGET_ABI_BITS; j++) {
+            /* check the bit inside the abi_ulong */
+            if ((b >> j) & 1) {
+                FD_SET(k, fds);
+            }
+            k++;
+        }
+    }
+    unlock_user(target_fds, target_fds_addr, 0);
+
+    return 0;
+}
+
+abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
+        abi_ulong target_fds_addr, int n)
+{
+
+    if (target_fds_addr) {
+        if (copy_from_user_fdset(fds, target_fds_addr, n)) {
+            return -TARGET_EFAULT;
+        }
+        *fds_ptr = fds;
+    } else {
+        *fds_ptr = NULL;
+    }
+
+    return 0;
+}
+
+abi_long copy_to_user_fdset(abi_ulong target_fds_addr, const fd_set *fds, int n)
+{
+    int i, nw, j, k;
+    abi_long v;
+    abi_ulong *target_fds;
+
+    nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
+    target_fds = lock_user(VERIFY_WRITE, target_fds_addr,
+            sizeof(abi_ulong) * nw, 0);
+    if (target_fds == NULL) {
+        return -TARGET_EFAULT;
+    }
+    k = 0;
+    for (i = 0; i < nw; i++) {
+        v = 0;
+        for (j = 0; j < TARGET_ABI_BITS; j++) {
+            v |= ((FD_ISSET(k, fds) != 0) << j);
+            k++;
+        }
+        __put_user(v, &target_fds[i]);
+    }
+    unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
+
+    return 0;
+}
+
diff --git a/bsd-user/freebsd/os-time.h b/bsd-user/freebsd/os-time.h
new file mode 100644
index 0000000..a607e06
--- /dev/null
+++ b/bsd-user/freebsd/os-time.h
@@ -0,0 +1,602 @@ 
+/*
+ *  FreeBSD time related system call shims
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __FREEBSD_OS_TIME_H_
+#define __FREEBSD_OS_TIME_H_
+
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/select.h>
+#include <sys/timex.h>
+#include <signal.h>
+#include <time.h>
+
+#include "qemu-os.h"
+
+/* nanosleep(2) */
+static inline abi_long do_freebsd_nanosleep(abi_long arg1, abi_long arg2)
+{
+    abi_long ret;
+    struct timespec req, rem;
+
+    ret = t2h_freebsd_timespec(&req, arg1);
+    if (!is_error(ret)) {
+        ret = get_errno(nanosleep(&req, &rem));
+        if (!is_error(ret) && arg2) {
+            h2t_freebsd_timespec(arg2, &rem);
+        }
+    }
+
+    return ret;
+}
+
+/* clock_gettime(2) */
+static inline abi_long do_freebsd_clock_gettime(abi_long arg1, abi_long arg2)
+{
+    abi_long ret;
+    struct timespec ts;
+
+    ret = get_errno(clock_gettime(arg1, &ts));
+    if (!is_error(ret)) {
+        if (h2t_freebsd_timespec(arg2, &ts)) {
+            return -TARGET_EFAULT;
+        }
+    }
+
+    return ret;
+}
+
+/* clock_settime(2) */
+static inline abi_long do_freebsd_clock_settime(abi_long arg1, abi_long arg2)
+{
+    struct timespec ts;
+
+    if (t2h_freebsd_timespec(&ts, arg2) != 0) {
+        return -TARGET_EFAULT;
+    }
+
+    return get_errno(clock_settime(arg1, &ts));
+}
+
+/* clock_getres(2) */
+static inline abi_long do_freebsd_clock_getres(abi_long arg1, abi_long arg2)
+{
+    abi_long ret;
+    struct timespec ts;
+
+    ret = get_errno(clock_getres(arg1, &ts));
+    if (!is_error(ret)) {
+        if (h2t_freebsd_timespec(arg2, &ts)) {
+            return -TARGET_EFAULT;
+        }
+    }
+
+    return ret;
+}
+
+/* gettimeofday(2) */
+static inline abi_long do_freebsd_gettimeofday(abi_long arg1, abi_long arg2)
+{
+    abi_long ret;
+    struct timeval tv;
+    struct timezone tz, *target_tz; /* XXX */
+
+    if (arg2 != 0) {
+        if (!lock_user_struct(VERIFY_READ, target_tz, arg2, 0)) {
+            return -TARGET_EFAULT;
+        }
+        __get_user(tz.tz_minuteswest, &target_tz->tz_minuteswest);
+        __get_user(tz.tz_dsttime, &target_tz->tz_dsttime);
+        unlock_user_struct(target_tz, arg2, 1);
+    }
+    ret = get_errno(gettimeofday(&tv, arg2 != 0 ? &tz : NULL));
+    if (!is_error(ret)) {
+        if (h2t_freebsd_timeval(&tv, arg1)) {
+            return -TARGET_EFAULT;
+        }
+    }
+
+    return ret;
+}
+
+/* settimeofday(2) */
+static inline abi_long do_freebsd_settimeofday(abi_long arg1, abi_long arg2)
+{
+    struct timeval tv;
+    struct timezone tz, *target_tz; /* XXX */
+
+    if (arg2 != 0) {
+        if (!lock_user_struct(VERIFY_READ, target_tz, arg2, 0)) {
+            return -TARGET_EFAULT;
+        }
+        __get_user(tz.tz_minuteswest, &target_tz->tz_minuteswest);
+        __get_user(tz.tz_dsttime, &target_tz->tz_dsttime);
+        unlock_user_struct(target_tz, arg2, 1);
+    }
+    if (t2h_freebsd_timeval(&tv, arg1)) {
+        return -TARGET_EFAULT;
+    }
+
+    return get_errno(settimeofday(&tv, arg2 != 0 ? &tz : NULL));
+}
+
+/* adjtime(2) */
+static inline abi_long do_freebsd_adjtime(abi_ulong target_delta_addr,
+        abi_ulong target_old_addr)
+{
+    abi_long ret;
+    struct timeval host_delta, host_old;
+
+    ret = t2h_freebsd_timeval(&host_delta, target_delta_addr);
+    if (is_error(ret)) {
+        return ret;
+    }
+
+    if (target_old_addr) {
+        ret = get_errno(adjtime(&host_delta, &host_old));
+        if (is_error(ret)) {
+            return ret;
+        }
+        ret = h2t_freebsd_timeval(&host_old, target_old_addr);
+    } else {
+        ret = get_errno(adjtime(&host_delta, NULL));
+    }
+
+    return ret;
+}
+
+/* ntp_adjtime(2) */
+static abi_long do_freebsd_ntp_adjtime(abi_ulong target_tx_addr)
+{
+    abi_long ret;
+    struct timex host_tx;
+
+    ret = t2h_freebsd_timex(&host_tx, target_tx_addr);
+    if (ret == 0) {
+        ret = get_errno(ntp_adjtime(&host_tx));
+    }
+
+    return ret;
+}
+
+/* ntp_gettime(2) */
+static abi_long do_freebsd_ntp_gettime(abi_ulong target_ntv_addr)
+{
+    abi_long ret;
+    struct ntptimeval host_ntv;
+
+    ret = get_errno(ntp_gettime(&host_ntv));
+    if (ret == 0) {
+        ret = h2t_freebsd_ntptimeval(target_ntv_addr, &host_ntv);
+    }
+
+    return ret;
+}
+
+
+/* utimes(2) */
+static inline abi_long do_freebsd_utimes(abi_long arg1, abi_long arg2)
+{
+    abi_long ret;
+    void *p;
+    struct timeval *tvp, tv[2];
+
+    if (arg2 != 0) {
+        if (t2h_freebsd_timeval(&tv[0], arg2) ||
+                t2h_freebsd_timeval(&tv[1], arg2 +
+                        sizeof(struct target_freebsd_timeval))) {
+            return -TARGET_EFAULT;
+        }
+        tvp = tv;
+    } else {
+        tvp = NULL;
+    }
+    p = lock_user_string(arg1);
+    if (p == NULL) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(utimes(p, tvp));
+    unlock_user(p, arg1, 0);
+
+    return ret;
+}
+
+/* lutimes(2) */
+static inline abi_long do_freebsd_lutimes(abi_long arg1, abi_long arg2)
+{
+    abi_long ret;
+    void *p;
+    struct timeval *tvp, tv[2];
+
+    if (arg2 != 0) {
+        if (t2h_freebsd_timeval(&tv[0], arg2) ||
+                t2h_freebsd_timeval(&tv[1], arg2 +
+                        sizeof(struct target_freebsd_timeval))) {
+            return -TARGET_EFAULT;
+        }
+        tvp = tv;
+    } else {
+        tvp = NULL;
+    }
+    p = lock_user_string(arg1);
+    if (p == NULL) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(lutimes(p, tvp));
+    unlock_user(p, arg1, 0);
+
+    return ret;
+}
+
+/* futimes(2) */
+static inline abi_long do_freebsd_futimes(abi_long arg1, abi_long arg2)
+{
+    struct timeval *tvp, tv[2];
+
+    if (arg2 != 0) {
+        if (t2h_freebsd_timeval(&tv[0], arg2) ||
+                t2h_freebsd_timeval(&tv[1], arg2 +
+                        sizeof(struct target_freebsd_timeval))) {
+            return -TARGET_EFAULT;
+        }
+        tvp = tv;
+    } else {
+        tvp = NULL;
+    }
+
+    return get_errno(futimes(arg1, tvp));
+}
+
+/* futimesat(2) */
+static inline abi_long do_freebsd_futimesat(abi_long arg1, abi_long arg2,
+        abi_long arg3)
+{
+    abi_long ret;
+    void *p;
+    struct timeval *tvp, tv[2];
+
+    if (arg3 != 0) {
+        if (t2h_freebsd_timeval(&tv[0], arg3) ||
+                t2h_freebsd_timeval(&tv[1], arg3 +
+                        sizeof(struct target_freebsd_timeval))) {
+            return -TARGET_EFAULT;
+        }
+        tvp = tv;
+    } else {
+        tvp = NULL;
+    }
+
+    p = lock_user_string(arg2);
+    if (p == NULL) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(futimesat(arg1, p, tvp));
+    unlock_user(p, arg2, 0);
+
+    return ret;
+}
+
+/*
+ * undocumented ktimer_create(clockid_t clock_id,  struct sigevent *evp,
+ * int *timerid) syscall
+ */
+static inline abi_long do_freebsd_ktimer_create(abi_long arg1, abi_long arg2,
+        abi_long arg3)
+{
+
+    qemu_log("qemu: Unsupported syscall ktimer_create()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* undocumented ktimer_delete(int timerid) syscall */
+static inline abi_long do_freebsd_ktimer_delete(abi_long arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall ktimer_delete()\n");
+    return -TARGET_ENOSYS;
+}
+
+/*
+ * undocumented ktimer_settime(int timerid, int flags,
+ * const struct itimerspec *value, struct itimerspec *ovalue) syscall
+ */
+static inline abi_long do_freebsd_ktimer_settime(abi_long arg1, abi_long arg2,
+        abi_long arg3, abi_long arg4)
+{
+
+    qemu_log("qemu: Unsupported syscall ktimer_settime()\n");
+    return -TARGET_ENOSYS;
+}
+
+/*
+ * undocumented ktimer_gettime(int timerid, struct itimerspec *value)
+ * syscall
+ */
+static inline abi_long do_freebsd_ktimer_gettime(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall ktimer_gettime()\n");
+    return -TARGET_ENOSYS;
+}
+
+/*
+ * undocumented ktimer_getoverrun(int timerid) syscall
+ */
+static inline abi_long do_freebsd_ktimer_getoverrun(abi_long arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall ktimer_getoverrun()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* select(2) */
+static inline abi_long do_freebsd_select(int n, abi_ulong rfd_addr,
+        abi_ulong wfd_addr, abi_ulong efd_addr, abi_ulong target_tv_addr)
+{
+    fd_set rfds, wfds, efds;
+    fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
+    struct timeval tv, *tv_ptr;
+    abi_long ret, error;
+
+    ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
+    if (ret != 0) {
+        return ret;
+    }
+    ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
+    if (ret != 0) {
+        return ret;
+    }
+    ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
+    if (ret != 0) {
+        return ret;
+    }
+
+    if (target_tv_addr != 0) {
+        if (t2h_freebsd_timeval(&tv, target_tv_addr)) {
+            return -TARGET_EFAULT;
+        }
+        tv_ptr = &tv;
+    } else {
+        tv_ptr = NULL;
+    }
+
+    ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
+
+    if (!is_error(ret)) {
+        if (rfd_addr != 0) {
+            error = copy_to_user_fdset(rfd_addr, &rfds, n);
+            if (error != 0) {
+                return error;
+            }
+        }
+        if (wfd_addr != 0) {
+            error = copy_to_user_fdset(wfd_addr, &wfds, n);
+            if (error != 0) {
+                return error;
+            }
+        }
+        if (efd_addr != 0) {
+            error = copy_to_user_fdset(efd_addr, &efds, n);
+            if (error != 0) {
+                return error;
+            }
+        }
+        if (target_tv_addr != 0) {
+            error = h2t_freebsd_timeval(&tv, target_tv_addr);
+            if (is_error(error)) {
+                return error;
+            }
+        }
+    }
+    return ret;
+}
+
+/* pselect(2) */
+static inline abi_long do_freebsd_pselect(int n, abi_ulong rfd_addr,
+        abi_ulong wfd_addr, abi_ulong efd_addr, abi_ulong ts_addr,
+        abi_ulong set_addr)
+{
+    fd_set rfds, wfds, efds;
+    fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
+    sigset_t set, *set_ptr;
+    struct timespec ts, *ts_ptr;
+    void *p;
+    abi_long ret;
+
+    ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
+    if (is_error(ret)) {
+        return ret;
+    }
+    ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
+    if (is_error(ret)) {
+        return ret;
+    }
+    ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
+    if (is_error(ret)) {
+        return ret;
+    }
+
+    /* Unlike select(), pselect() uses struct timespec instead of timeval */
+    if (ts_addr) {
+        if (t2h_freebsd_timespec(&ts, ts_addr)) {
+            return -TARGET_EFAULT;
+        }
+        ts_ptr = &ts;
+    } else {
+        ts_ptr = NULL;
+    }
+
+    if (set_addr != 0) {
+        p = lock_user(VERIFY_READ, set_addr, sizeof(target_sigset_t), 1);
+        if (p == NULL) {
+            return -TARGET_EFAULT;
+        }
+        target_to_host_sigset(&set, p);
+        unlock_user(p, set_addr, 0);
+        set_ptr = &set;
+    } else {
+        set_ptr = NULL;
+    }
+
+    ret = get_errno(pselect(n, rfds_ptr, wfds_ptr, efds_ptr, ts_ptr, set_ptr));
+
+    if (!is_error(ret)) {
+        if (rfd_addr != 0) {
+            ret = copy_to_user_fdset(rfd_addr, &rfds, n);
+            if (is_error(ret)) {
+                return ret;
+            }
+        }
+        if (wfd_addr != 0) {
+            ret = copy_to_user_fdset(wfd_addr, &wfds, n);
+            if (is_error(ret)) {
+                return ret;
+            }
+        }
+        if (efd_addr != 0) {
+            ret = copy_to_user_fdset(efd_addr, &efds, n);
+            if (is_error(ret)) {
+                return ret;
+            }
+        }
+        if (ts_addr != 0) {
+            ret = h2t_freebsd_timespec(ts_addr, &ts);
+            if (is_error(ret)) {
+                return ret;
+            }
+        }
+    }
+    return ret;
+}
+
+/* kqueue(2) */
+static inline abi_long do_freebsd_kqueue(void)
+{
+
+    return get_errno(kqueue());
+}
+
+/* kevent(2) */
+static inline abi_long do_freebsd_kevent(abi_long arg1, abi_ulong arg2,
+        abi_long arg3, abi_ulong arg4, abi_long arg5, abi_long arg6)
+{
+    abi_long ret;
+    struct kevent *changelist = NULL, *eventlist = NULL;
+    struct target_freebsd_kevent *target_changelist, *target_eventlist;
+    struct timespec ts;
+    int i;
+
+    if (arg3 != 0) {
+        target_changelist = lock_user(VERIFY_READ, arg2,
+                sizeof(struct target_freebsd_kevent) * arg3, 1);
+        if (target_changelist == NULL) {
+            return -TARGET_EFAULT;
+        }
+
+        changelist = alloca(sizeof(struct kevent) * arg3);
+        for (i = 0; i < arg3; i++) {
+            __get_user(changelist[i].ident, &target_changelist[i].ident);
+            __get_user(changelist[i].filter, &target_changelist[i].filter);
+            __get_user(changelist[i].flags, &target_changelist[i].flags);
+            __get_user(changelist[i].fflags, &target_changelist[i].fflags);
+            __get_user(changelist[i].data, &target_changelist[i].data);
+            /* __get_user(changelist[i].udata, &target_changelist[i].udata); */
+#if TARGET_ABI_BITS == 32
+            changelist[i].udata = (void *)(uintptr_t)target_changelist[i].udata;
+            tswap32s((uint32_t *)&changelist[i].udata);
+#else
+            changelist[i].udata = (void *)(uintptr_t)target_changelist[i].udata;
+            tswap64s((uint64_t *)&changelist[i].udata);
+#endif
+        }
+        unlock_user(target_changelist, arg2, 0);
+    }
+
+    if (arg5 != 0) {
+        eventlist = alloca(sizeof(struct kevent) * arg5);
+    }
+    if (arg6 != 0) {
+        if (t2h_freebsd_timespec(&ts, arg6)) {
+            return -TARGET_EFAULT;
+        }
+    }
+    ret = get_errno(kevent(arg1, changelist, arg3, eventlist, arg5,
+                arg6 != 0 ? &ts : NULL));
+    if (!is_error(ret)) {
+        target_eventlist = lock_user(VERIFY_WRITE, arg4,
+                sizeof(struct target_freebsd_kevent) * arg5, 0);
+        if (target_eventlist == NULL) {
+                return -TARGET_EFAULT;
+        }
+        for (i = 0; i < arg5; i++) {
+            __put_user(eventlist[i].ident, &target_eventlist[i].ident);
+            __put_user(eventlist[i].filter, &target_eventlist[i].filter);
+            __put_user(eventlist[i].flags, &target_eventlist[i].flags);
+            __put_user(eventlist[i].fflags, &target_eventlist[i].fflags);
+            __put_user(eventlist[i].data, &target_eventlist[i].data);
+            /* __put_user(eventlist[i].udata, &target_eventlist[i].udata);*/
+#if TARGET_ABI_BITS == 32
+            tswap32s((uint32_t *)&eventlist[i].data);
+            target_eventlist[i].data = (uintptr_t)eventlist[i].data;
+#else
+            tswap64s((uint64_t *)&eventlist[i].data);
+            target_eventlist[i].data = (uintptr_t)eventlist[i].data;
+#endif
+        }
+        unlock_user(target_eventlist, arg4,
+                sizeof(struct target_freebsd_kevent) * arg5);
+    }
+    return ret;
+}
+
+/* sigtimedwait(2) */
+static inline abi_long do_freebsd_sigtimedwait(abi_ulong arg1, abi_ulong arg2,
+        abi_ulong arg3)
+{
+    abi_long ret;
+    void *p;
+    sigset_t set;
+    struct timespec uts, *puts;
+    siginfo_t uinfo;
+
+    p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
+    if (p == NULL) {
+        return -TARGET_EFAULT;
+    }
+    target_to_host_sigset(&set, p);
+    unlock_user(p, arg1, 0);
+    if (arg3) {
+        puts = &uts;
+        t2h_freebsd_timespec(puts, arg3);
+    } else {
+        puts = NULL;
+    }
+    ret = get_errno(sigtimedwait(&set, &uinfo, puts));
+    if (!is_error(ret) && arg2) {
+        p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0);
+        if (p == NULL) {
+            return -TARGET_EFAULT;
+        }
+        host_to_target_siginfo(p, &uinfo);
+        unlock_user(p, arg2, sizeof(target_siginfo_t));
+    }
+    return ret;
+}
+
+#endif /* __FREEBSD_OS_TIME_H_ */
diff --git a/bsd-user/freebsd/qemu-os.h b/bsd-user/freebsd/qemu-os.h
new file mode 100644
index 0000000..7a1ed9c
--- /dev/null
+++ b/bsd-user/freebsd/qemu-os.h
@@ -0,0 +1,41 @@ 
+/*
+ *  FreeBSD conversion extern declarations
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _QEMU_OS_H_
+#define _QEMU_OS_H_
+
+/* os-time.c */
+abi_long t2h_freebsd_timeval(struct timeval *tv, abi_ulong target_tv_addr);
+abi_long h2t_freebsd_timeval(struct timeval *tv, abi_ulong target_tv_addr);
+
+abi_long t2h_freebsd_timespec(struct timespec *ts, abi_ulong target_ts_addr);
+abi_long h2t_freebsd_timespec(abi_ulong target_ts_addr, struct timespec *ts);
+
+abi_long t2h_freebsd_timex(struct timex *host_tx, abi_ulong target_tx_addr);
+
+abi_long h2t_freebsd_ntptimeval(abi_ulong target_ntv_addr,
+        struct ntptimeval *ntv);
+
+abi_ulong copy_from_user_fdset(fd_set *fds, abi_ulong target_fds_addr, int n);
+abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
+        abi_ulong target_fds_addr, int n);
+abi_long copy_to_user_fdset(abi_ulong target_fds_addr, const fd_set *fds,
+        int n);
+
+#endif /* !_QEMU_OS_H_ */
diff --git a/bsd-user/netbsd/os-time.c b/bsd-user/netbsd/os-time.c
new file mode 100644
index 0000000..ee2c7a0
--- /dev/null
+++ b/bsd-user/netbsd/os-time.c
@@ -0,0 +1 @@ 
+/* XXX NetBSD time related helpers */
diff --git a/bsd-user/netbsd/os-time.h b/bsd-user/netbsd/os-time.h
new file mode 100644
index 0000000..6d0f1de
--- /dev/null
+++ b/bsd-user/netbsd/os-time.h
@@ -0,0 +1,179 @@ 
+#ifndef __NETBSD_OS_TIME_H_
+#define __NETBSD_OS_TIME_H_
+
+/*
+ * XXX To support FreeBSD binaries on NetBSD these syscalls will need to
+ * be emulated.
+ */
+static inline abi_long do_freebsd_nanosleep(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_clock_gettime(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_clock_settime(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_clock_getres(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_gettimeofday(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_settimeofday(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_adjtime(abi_ulong target_delta_addr,
+        abi_ulong target_old_addr)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static abi_long do_freebsd_ntp_adjtime(abi_ulong target_tx_addr)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static abi_long do_freebsd_ntp_gettime(abi_ulong target_ntv_addr)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_utimes(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_lutimes(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_futimes(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_futimesat(abi_long arg1, abi_long arg2,
+        abi_long arg3)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_ktimer_create(abi_long arg1, abi_long arg2,
+        abi_long arg3)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_ktimer_delete(abi_long arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_ktimer_settime(abi_long arg1, abi_long arg2,
+        abi_long arg3, abi_long arg4)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_ktimer_gettime(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_ktimer_getoverrun(abi_long arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_select(int n, abi_ulong rfd_addr,
+        abi_ulong wfd_addr, abi_ulong efd_addr, abi_ulong target_tv_addr)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+
+static inline abi_long do_freebsd_pselect(int n, abi_ulong rfd_addr,
+        abi_ulong wfd_addr, abi_ulong efd_addr, abi_ulong ts_addr,
+        abi_ulong set_addr)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_kqueue(void)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_kevent(abi_long arg1, abi_ulong arg2,
+        abi_long arg3, abi_ulong arg4, abi_long arg5, abi_long arg6)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_sigtimedwait(abi_ulong arg1, abi_ulong arg2,
+        abi_ulong arg3)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+#endif /* ! __NETBSD_OS_TIME_H_ */
diff --git a/bsd-user/netbsd/qemu-os.h b/bsd-user/netbsd/qemu-os.h
new file mode 100644
index 0000000..016618b
--- /dev/null
+++ b/bsd-user/netbsd/qemu-os.h
@@ -0,0 +1 @@ 
+/* NetBSD conversion extern declarations */
diff --git a/bsd-user/openbsd/os-time.c b/bsd-user/openbsd/os-time.c
new file mode 100644
index 0000000..accd886
--- /dev/null
+++ b/bsd-user/openbsd/os-time.c
@@ -0,0 +1 @@ 
+/* XXX OpenBSD time related helpers */
diff --git a/bsd-user/openbsd/os-time.h b/bsd-user/openbsd/os-time.h
new file mode 100644
index 0000000..fc444bb
--- /dev/null
+++ b/bsd-user/openbsd/os-time.h
@@ -0,0 +1,179 @@ 
+#ifndef __OPENBSD_OS_TIME_H_
+#define __OPENBSD_OS_TIME_H_
+
+/*
+ * XXX To support FreeBSD binaries on OpenBSD these syscalls will need to
+ * be emulated.
+ */
+static inline abi_long do_freebsd_nanosleep(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_clock_gettime(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_clock_settime(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_clock_getres(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_gettimeofday(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_settimeofday(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_adjtime(abi_ulong target_delta_addr,
+        abi_ulong target_old_addr)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static abi_long do_freebsd_ntp_adjtime(abi_ulong target_tx_addr)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static abi_long do_freebsd_ntp_gettime(abi_ulong target_ntv_addr)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_utimes(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_lutimes(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_futimes(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_futimesat(abi_long arg1, abi_long arg2,
+        abi_long arg3)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_ktimer_create(abi_long arg1, abi_long arg2,
+        abi_long arg3)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_ktimer_delete(abi_long arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_ktimer_settime(abi_long arg1, abi_long arg2,
+        abi_long arg3, abi_long arg4)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_ktimer_gettime(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_ktimer_getoverrun(abi_long arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_select(int n, abi_ulong rfd_addr,
+        abi_ulong wfd_addr, abi_ulong efd_addr, abi_ulong target_tv_addr)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+
+static inline abi_long do_freebsd_pselect(int n, abi_ulong rfd_addr,
+        abi_ulong wfd_addr, abi_ulong efd_addr, abi_ulong ts_addr,
+        abi_ulong set_addr)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_kqueue(void)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_kevent(abi_long arg1, abi_ulong arg2,
+        abi_long arg3, abi_ulong arg4, abi_long arg5, abi_long arg6)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+static inline abi_long do_freebsd_sigtimedwait(abi_ulong arg1, abi_ulong arg2,
+        abi_ulong arg3)
+{
+
+    qemu_log("qemu: Unsupported syscall %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
+
+#endif /* ! __OPENBSD_OS_TIME_H_ */
diff --git a/bsd-user/openbsd/qemu-os.h b/bsd-user/openbsd/qemu-os.h
new file mode 100644
index 0000000..f4ad3be
--- /dev/null
+++ b/bsd-user/openbsd/qemu-os.h
@@ -0,0 +1 @@ 
+/* OpenBSD conversion extern declarations */
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
index 2efa772..cbdd363 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -2,6 +2,7 @@ 
  *  BSD syscalls
  *
  *  Copyright (c) 2003 - 2008 Fabrice Bellard
+ *  Copyright (c) 2013 Stacey D. Son
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -36,6 +37,8 @@ 
 #include "bsd-file.h"
 #include "bsd-mem.h"
 
+#include "os-time.h"
+
 /* #define DEBUG */
 
 #if defined(TARGET_I386)
@@ -682,6 +685,99 @@  abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 
 
+        /*
+         * time related system calls.
+         */
+    case TARGET_FREEBSD_NR_nanosleep: /* nanosleep(2) */
+        ret = do_freebsd_nanosleep(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_clock_gettime: /* clock_gettime(2) */
+        ret = do_freebsd_clock_gettime(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_clock_settime: /* clock_settime(2) */
+        ret = do_freebsd_clock_settime(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_clock_getres: /* clock_getres(2) */
+        ret = do_freebsd_clock_getres(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_gettimeofday: /* gettimeofday(2) */
+        ret = do_freebsd_gettimeofday(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_settimeofday: /* settimeofday(2) */
+        ret = do_freebsd_settimeofday(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_adjtime: /* adjtime(2) */
+        ret = do_freebsd_adjtime(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_ntp_adjtime: /* ntp_adjtime(2) */
+        ret = do_freebsd_ntp_adjtime(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_ntp_gettime: /* ntp_gettime(2) */
+        ret = do_freebsd_ntp_gettime(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_utimes: /* utimes(2) */
+        ret = do_freebsd_utimes(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_lutimes: /* lutimes(2) */
+        ret = do_freebsd_lutimes(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_futimes: /* futimes(2) */
+        ret = do_freebsd_futimes(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_futimesat: /* futimesat(2) */
+        ret = do_freebsd_futimesat(arg1, arg2, arg3);
+        break;
+
+    case TARGET_FREEBSD_NR_ktimer_create: /* undocumented */
+        ret = do_freebsd_ktimer_create(arg1, arg2, arg3);
+        break;
+
+    case TARGET_FREEBSD_NR_ktimer_delete: /* undocumented */
+        ret = do_freebsd_ktimer_delete(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_ktimer_settime: /* undocumented */
+        ret = do_freebsd_ktimer_settime(arg1, arg2, arg3, arg4);
+        break;
+
+    case TARGET_FREEBSD_NR_ktimer_gettime: /* undocumented */
+        ret = do_freebsd_ktimer_gettime(arg1, arg2);
+        break;
+
+
+    case TARGET_FREEBSD_NR_ktimer_getoverrun: /* undocumented */
+        ret = do_freebsd_ktimer_getoverrun(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_select: /* select(2) */
+        ret = do_freebsd_select(arg1, arg2, arg3, arg4, arg5);
+        break;
+
+    case TARGET_FREEBSD_NR_pselect: /* pselect(2) */
+        ret = do_freebsd_pselect(arg1, arg2, arg3, arg4, arg5, arg6);
+        break;
+
+    case TARGET_FREEBSD_NR_kqueue: /* kqueue(2) */
+        ret = do_freebsd_kqueue();
+        break;
+
+    case TARGET_FREEBSD_NR_kevent: /* kevent(2) */
+        ret = do_freebsd_kevent(arg1, arg2, arg3, arg4, arg5, arg6);
+        break;
+
+
     case TARGET_FREEBSD_NR_break:
         ret = do_obreak(arg1);
         break;
diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h
index dea94ef..7b85835 100644
--- a/bsd-user/syscall_defs.h
+++ b/bsd-user/syscall_defs.h
@@ -83,4 +83,80 @@  struct bsd_shm_regions {
 /* XXX */
 #define TARGET_BSD_MAP_FLAGMASK         0x3ff7
 
+/*
+ * sys/time.h
+ * sys/timex.h
+ */
+
+/*
+ * time_t seems to be very inconsistly defined for the different *BSD's...
+ *
+ * FreeBSD/{arm, mips} uses a 64bits time_t, even in 32bits mode,
+ * so we have to add a special case here.
+ *
+ * On NetBSD time_t is always defined as an int64_t.  On OpenBSD time_t
+ * is always defined as an int.
+ *
+ */
+#if (defined(TARGET_ARM) || defined(TARGET_MIPS))
+typedef int64_t target_freebsd_time_t;
+#else
+typedef abi_long target_freebsd_time_t;
+#endif
+
+typedef abi_long target_freebsd_suseconds_t;
+
+/* compare to sys/timespec.h */
+struct target_freebsd_timespec {
+    target_freebsd_time_t   tv_sec;     /* seconds */
+    abi_long                tv_nsec;    /* and nanoseconds */
+} __packed;
+
+struct target_freebsd_timeval {
+    target_freebsd_time_t       tv_sec; /* seconds */
+    target_freebsd_suseconds_t  tv_usec;/* and microseconds */
+} __packed;
+
+/* compare to sys/timex.h */
+struct target_freebsd_ntptimeval {
+    struct target_freebsd_timespec  time;
+    abi_long    maxerror;
+    abi_long    esterror;
+    abi_long    tai;
+    int32_t     time_state;
+};
+
+struct target_freebsd_timex {
+    uint32_t    modes;
+    abi_long    offset;
+    abi_long    freq;
+    abi_long    maxerror;
+    abi_long    esterror;
+    int32_t     status;
+    abi_long    constant;
+    abi_long    precision;
+    abi_long    tolerance;
+
+    abi_long    ppsfreq;
+    abi_long    jitter;
+    int32_t     shift;
+    abi_long    stabil;
+    abi_long    jitcnt;
+    abi_long    calcnt;
+    abi_long    errcnt;
+    abi_long    stbcnt;
+};
+
+/*
+ * sys/event.h
+ */
+struct target_freebsd_kevent {
+    abi_ulong  ident;
+    int16_t    filter;
+    uint16_t   flags;
+    uint32_t   fflags;
+    abi_long   data;
+    abi_ulong  udata;
+} __packed;
+
 #endif /* ! _SYSCALL_DEFS_H_ */