From 5a1bcfd4d5e2a4621637c82fe1d62e3409c08866 Mon Sep 17 00:00:00 2001 In-Reply-To: <1383928417-38009-1-git-send-email-sson@FreeBSD.org> References: <1383928417-38009-1-git-send-email-sson@FreeBSD.org> From: Stacey Son Date: Mon, 7 Oct 2013 03:42:43 -0500 Subject: [PATCH v3 06/19] bsd-user: add support for freebsd time related system calls This change adds support or stubs for time related system calls including nanosleep(2), clock_gettime(2), clock_settime(2), clock_getres(2), gettimeofday(2), settimeofday(2), adjtime(2), ntp_adjtime(2), ntp_gettime(2), utimes(2), lutimes(2), futimes(2), futimesat(2), select(2), pselect(2), kqueue(2), kevent(2), setitimer(2), getitimer(2), and the undocumented ktimer_*() calls. --- bsd-user/Makefile.objs | 3 +- bsd-user/freebsd/os-time.c | 205 ++++++++++++ bsd-user/freebsd/os-time.h | 643 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/qemu-os.h | 53 +++ 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 | 102 ++++++ bsd-user/syscall_defs.h | 796 ++++++++++++++++++++++++++++++++++++++------ 12 files changed, 2061 insertions(+), 103 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 diff --git a/bsd-user/Makefile.objs b/bsd-user/Makefile.objs index a4dca8e..ac69be7 100644 --- a/bsd-user/Makefile.objs +++ b/bsd-user/Makefile.objs @@ -1,2 +1,3 @@ obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \ - uaccess.o $(HOST_VARIANT_DIR)/os-sys.o $(TARGET_ABI_DIR)/target_arch_cpu.o + uaccess.o $(HOST_VARIANT_DIR)/os-sys.o \ + $(HOST_VARIANT_DIR)/os-time.o $(TARGET_ABI_DIR)/target_arch_cpu.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 . + */ + +#include +#include +#include + +#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..c6b5b28 --- /dev/null +++ b/bsd-user/freebsd/os-time.h @@ -0,0 +1,643 @@ +/* + * 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 . + */ + +#ifndef __FREEBSD_OS_TIME_H_ +#define __FREEBSD_OS_TIME_H_ + +#include +#include +#include +#include +#include +#include + +#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_ulong arg1, abi_ulong 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; +} + +/* setitimer(2) */ +static inline abi_long do_freebsd_setitimer(int arg1, abi_ulong arg2, abi_ulong arg3) +{ + abi_long ret = 0; + struct itimerval value, ovalue, *pvalue; + + if (arg2) { + pvalue = &value; + if (t2h_freebsd_timeval(&pvalue->it_interval, arg2) || + t2h_freebsd_timeval(&pvalue->it_value, arg2 + sizeof(struct target_freebsd_timeval))) { + return -TARGET_EFAULT; + } + } else { + pvalue = NULL; + } + ret = get_errno(setitimer(arg1, pvalue, &ovalue)); + if (!is_error(ret) && arg3) { + if (h2t_freebsd_timeval(&ovalue.it_interval, arg3) + || h2t_freebsd_timeval(&ovalue.it_value, arg3 + sizeof(struct target_freebsd_timeval))) { + return -TARGET_EFAULT; + } + } + return ret; +} + +/* getitimer(2) */ +static inline abi_long do_freebsd_getitimer(int arg1, abi_ulong arg2) +{ + abi_long ret = 0; + struct itimerval value; + + ret = get_errno(getitimer(arg1, &value)); + if (!is_error(ret) && arg2) { + if (h2t_freebsd_timeval(&value.it_interval, arg2) || + h2t_freebsd_timeval(&value.it_value, arg2 + sizeof(struct target_freebsd_timeval))) { + return -TARGET_EFAULT; + } + } + 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..bde610e --- /dev/null +++ b/bsd-user/freebsd/qemu-os.h @@ -0,0 +1,53 @@ +/* + * 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 . + */ + +#ifndef _QEMU_OS_H_ +#define _QEMU_OS_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* 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 dbc212d..0996787 100644 --- a/bsd-user/syscall.c +++ b/bsd-user/syscall.c @@ -39,6 +39,9 @@ #define target_to_host_bitmask(x, tbl) (x) +/* *BSD dependent syscall shims */ +#include "os-time.h" + /* #define DEBUG */ static abi_ulong target_brk; @@ -224,6 +227,105 @@ 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_setitimer: /* setitimer(2) */ + ret = do_freebsd_setitimer(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_getitimer: /* getitimer(2) */ + ret = do_freebsd_getitimer(arg1, arg2); + break; + + /* * sys{ctl, arch, call} */ case TARGET_FREEBSD_NR___sysctl: /* sysctl(3) */ diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h index 207ddee..ad84d33 100644 --- a/bsd-user/syscall_defs.h +++ b/bsd-user/syscall_defs.h @@ -1,105 +1,5 @@ -/* $OpenBSD: signal.h,v 1.19 2006/01/08 14:20:16 millert Exp $ */ -/* $NetBSD: signal.h,v 1.21 1996/02/09 18:25:32 christos Exp $ */ - -/* - * Copyright (c) 1982, 1986, 1989, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * (c) UNIX System Laboratories, Inc. - * All or some portions of this file are derived from material licensed - * to the University of California by American Telephone and Telegraph - * Co. or Unix System Laboratories, Inc. and are reproduced herein with - * the permission of UNIX System Laboratories, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)signal.h 8.2 (Berkeley) 1/21/94 - */ - -#define TARGET_NSIG 32 /* counting 0; could be 33 (mask is 1-32) */ - -#define TARGET_SIGHUP 1 /* hangup */ -#define TARGET_SIGINT 2 /* interrupt */ -#define TARGET_SIGQUIT 3 /* quit */ -#define TARGET_SIGILL 4 /* illegal instruction (not reset when caught) */ -#define TARGET_SIGTRAP 5 /* trace trap (not reset when caught) */ -#define TARGET_SIGABRT 6 /* abort() */ -#define TARGET_SIGIOT SIGABRT /* compatibility */ -#define TARGET_SIGEMT 7 /* EMT instruction */ -#define TARGET_SIGFPE 8 /* floating point exception */ -#define TARGET_SIGKILL 9 /* kill (cannot be caught or ignored) */ -#define TARGET_SIGBUS 10 /* bus error */ -#define TARGET_SIGSEGV 11 /* segmentation violation */ -#define TARGET_SIGSYS 12 /* bad argument to system call */ -#define TARGET_SIGPIPE 13 /* write on a pipe with no one to read it */ -#define TARGET_SIGALRM 14 /* alarm clock */ -#define TARGET_SIGTERM 15 /* software termination signal from kill */ -#define TARGET_SIGURG 16 /* urgent condition on IO channel */ -#define TARGET_SIGSTOP 17 /* sendable stop signal not from tty */ -#define TARGET_SIGTSTP 18 /* stop signal from tty */ -#define TARGET_SIGCONT 19 /* continue a stopped process */ -#define TARGET_SIGCHLD 20 /* to parent on child stop or exit */ -#define TARGET_SIGTTIN 21 /* to readers pgrp upon background tty read */ -#define TARGET_SIGTTOU 22 /* like TTIN for output if (tp->t_local<OSTOP) */ -#define TARGET_SIGIO 23 /* input/output possible signal */ -#define TARGET_SIGXCPU 24 /* exceeded CPU time limit */ -#define TARGET_SIGXFSZ 25 /* exceeded file size limit */ -#define TARGET_SIGVTALRM 26 /* virtual time alarm */ -#define TARGET_SIGPROF 27 /* profiling time alarm */ -#define TARGET_SIGWINCH 28 /* window size changes */ -#define TARGET_SIGINFO 29 /* information request */ -#define TARGET_SIGUSR1 30 /* user defined signal 1 */ -#define TARGET_SIGUSR2 31 /* user defined signal 2 */ - -/* - * Language spec says we must list exactly one parameter, even though we - * actually supply three. Ugh! - */ -#define TARGET_SIG_DFL (void (*)(int))0 -#define TARGET_SIG_IGN (void (*)(int))1 -#define TARGET_SIG_ERR (void (*)(int))-1 - -#define TARGET_SA_ONSTACK 0x0001 /* take signal on signal stack */ -#define TARGET_SA_RESTART 0x0002 /* restart system on signal return */ -#define TARGET_SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */ -#define TARGET_SA_NODEFER 0x0010 /* don't mask the signal we're delivering */ -#define TARGET_SA_NOCLDWAIT 0x0020 /* don't create zombies (assign to pid 1) */ -#define TARGET_SA_USERTRAMP 0x0100 /* do not bounce off kernel's sigtramp */ -#define TARGET_SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */ -#define TARGET_SA_SIGINFO 0x0040 /* generate siginfo_t */ - -/* - * Flags for sigprocmask: - */ -#define TARGET_SIG_BLOCK 1 /* block specified signal set */ -#define TARGET_SIG_UNBLOCK 2 /* unblock specified signal set */ -#define TARGET_SIG_SETMASK 3 /* set specified signal set */ - -#define TARGET_BADSIG SIG_ERR - -#define TARGET_SS_ONSTACK 0x0001 /* take signals on alternate stack */ -#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate stack */ +#ifndef _SYSCALL_DEFS_H_ +#define _SYSCALL_DEFS_H_ #include "errno_defs.h" @@ -112,3 +12,695 @@ struct target_iovec { abi_long iov_len; /* Number of bytes */ }; +/* + * sys/ipc.h + */ +struct target_ipc_perm { + uint32_t cuid; /* creator user id */ + uint32_t cgid; /* creator group id */ + uint32_t uid; /* user id */ + uint32_t gid; /* group id */ + uint16_t mode; /* r/w permission */ + uint16_t seq; /* sequence # */ + abi_long key; /* user specified msg/sem/shm key */ +}; + +#define TARGET_IPC_RMID 0 /* remove identifier */ +#define TARGET_IPC_SET 1 /* set options */ +#define TARGET_IPC_STAT 2 /* get options */ + +/* + * sys/sem.h + */ +#define TARGET_GETNCNT 3 /* Return the value of semncnt {READ} */ +#define TARGET_GETPID 4 /* Return the value of sempid {READ} */ +#define TARGET_GETVAL 5 /* Return the value of semval {READ} */ +#define TARGET_GETALL 6 /* Return semvals into arg.array {READ} */ +#define TARGET_GETZCNT 7 /* Return the value of semzcnt {READ} */ +#define TARGET_SETVAL 8 /* Set the value of semval to arg.val {ALTER} */ +#define TARGET_SETALL 9 /* Set semvals from arg.array {ALTER} */ +#define TARGET_SEM_STAT 10 /* Like IPC_STAT but treats semid as sema-index */ +#define TARGET_SEM_INFO 11 /* Like IPC_INFO but treats semid as sema-index */ + +struct target_sembuf { + unsigned short sem_num; /* semaphore # */ + short sem_op; /* semaphore operation */ + short sem_flg; /* operation flags */ +}; + +union target_semun { + int val; /* value for SETVAL */ + abi_ulong buf; /* buffer for IPC_STAT & IPC_SET */ + abi_ulong array; /* array for GETALL & SETALL */ +}; + +struct target_semid_ds { + struct target_ipc_perm sem_perm; /* operation permission struct */ + abi_ulong sem_base; /* pointer to first semaphore in set */ + uint16_t sem_nsems; /* number of sems in set */ + abi_ulong sem_otime; /* last operation time */ + abi_ulong sem_ctime; /* times measured in secs */ +}; + +/* + * sys/shm.h + */ +struct target_shmid_ds { + struct target_ipc_perm shm_perm; /* peration permission structure */ + abi_ulong shm_segsz; /* size of segment in bytes */ + int32_t shm_lpid; /* process ID of last shared memory op */ + int32_t shm_cpid; /* process ID of creator */ + int32_t shm_nattch; /* number of current attaches */ + abi_ulong shm_atime; /* time of last shmat() */ + abi_ulong shm_dtime; /* time of last shmdt() */ + abi_ulong shm_ctime; /* time of last change by shmctl() */ +}; + +#define N_BSD_SHM_REGIONS 32 +struct bsd_shm_regions { + abi_long start; + abi_long size; +}; + +/* + * sys/msg.h + */ +struct target_msqid_ds { + struct target_ipc_perm msg_perm; /* msg queue permission bits */ + abi_ulong msg_first; /* first message in the queue */ + abi_ulong msg_last; /* last message in the queue */ + abi_ulong msg_cbytes; /* # of bytes in use on the queue */ + abi_ulong msg_qnum; /* number of msgs in the queue */ + abi_ulong msg_qbytes; /* max # of bytes on the queue */ + int32_t msg_lspid; /* pid of last msgsnd() */ + int32_t msg_lrpid; /* pid of last msgrcv() */ + abi_ulong msg_stime; /* time of last msgsnd() */ + abi_ulong msg_rtime; /* time of last msgrcv() */ + abi_ulong msg_ctime; /* time of last msgctl() */ +}; + +struct target_msgbuf { + abi_long mtype; /* message type */ + char mtext[1]; /* body of message */ +}; + +/* + * sched.h + */ +struct target_sched_param { + int32_t sched_priority; +}; + +/* + * sys/mman.h + */ +#define TARGET_FREEBSD_MAP_RESERVED0080 0x0080 /* previously misimplemented + MAP_INHERIT */ +#define TARGET_FREEBSD_MAP_RESERVED0100 0x0100 /* previously unimplemented + MAP_NOEXTEND */ +#define TARGET_FREEBSD_MAP_STACK 0x0400 /* region grows down, like a + stack */ +#define TARGET_FREEBSD_MAP_NOSYNC 0x0800 /* page to but do not sync + underlying file */ + +#define TARGET_FREEBSD_MAP_FLAGMASK 0x1ff7 + +#define TARGET_NETBSD_MAP_INHERIT 0x0080 /* region is retained after + exec */ +#define TARGET_NETBSD_MAP_TRYFIXED 0x0400 /* attempt hint address, even + within break */ +#define TARGET_NETBSD_MAP_WIRED 0x0800 /* mlock() mapping when it is + established */ + +#define TARGET_NETBSD_MAP_STACK 0x2000 /* allocated from memory, swap + space (stack) */ + +#define TARGET_NETBSD_MAP_FLAGMASK 0x3ff7 + +#define TARGET_OPENBSD_MAP_INHERIT 0x0080 /* region is retained after + exec */ +#define TARGET_OPENBSD_MAP_NOEXTEND 0x0100 /* for MAP_FILE, don't change + file size */ +#define TARGET_OPENBSD_MAP_TRYFIXED 0x0400 /* attempt hint address, + even within heap */ + +#define TARGET_OPENBSD_MAP_FLAGMASK 0x17f7 + +/* 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 */ +#if (defined(TARGET_ARM) || defined(TARGET_MIPS)) && TARGET_ABI_BITS == 32 + abi_long _pad; +#endif +} __packed; + +struct target_freebsd_timeval { + target_freebsd_time_t tv_sec; /* seconds */ + target_freebsd_suseconds_t tv_usec;/* and microseconds */ +#if (defined(TARGET_ARM) || defined(TARGET_MIPS)) && TARGET_ABI_BITS == 32 + abi_long _pad; +#endif +} __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; + +/* + * sys/resource.h + */ +#if defined(__FreeBSD__) && defined(TARGET_ALPHA) +#define TARGET_RLIM_INFINITY 0x7fffffffffffffffull +#elif defined(__FreeBSD__) && (defined(TARGET_MIPS) || \ + (defined(TARGET_SPARC) && TARGET_ABI_BITS == 32)) +#define TARGET_RLIM_INFINITY 0x7fffffffUL +#else +#define TARGET_RLIM_INFINITY ((abi_ulong)-1) +#endif + +#define TARGET_RLIMIT_CPU 0 +#define TARGET_RLIMIT_FSIZE 1 +#define TARGET_RLIMIT_DATA 2 +#define TARGET_RLIMIT_STACK 3 +#define TARGET_RLIMIT_CORE 4 +#define TARGET_RLIMIT_RSS 5 +#define TARGET_RLIMIT_MEMLOCK 6 +#define TARGET_RLIMIT_NPROC 7 +#define TARGET_RLIMIT_NOFILE 8 +#define TARGET_RLIMIT_SBSIZE 9 +#define TARGET_RLIMIT_AS 10 +#define TARGET_RLIMIT_NPTS 11 +#define TARGET_RLIMIT_SWAP 12 + +struct target_rlimit { + uint64_t rlim_cur; + uint64_t rlim_max; +}; + +struct target_freebsd_rusage { + struct target_freebsd_timeval ru_utime; /* user time used */ + struct target_freebsd_timeval ru_stime; /* system time used */ + abi_long ru_maxrss; /* maximum resident set size */ + abi_long ru_ixrss; /* integral shared memory size */ + abi_long ru_idrss; /* integral unshared data size */ + abi_long ru_isrss; /* integral unshared stack size */ + abi_long ru_minflt; /* page reclaims */ + abi_long ru_majflt; /* page faults */ + abi_long ru_nswap; /* swaps */ + abi_long ru_inblock; /* block input operations */ + abi_long ru_oublock; /* block output operations */ + abi_long ru_msgsnd; /* messages sent */ + abi_long ru_msgrcv; /* messages received */ + abi_long ru_nsignals; /* signals received */ + abi_long ru_nvcsw; /* voluntary context switches */ + abi_long ru_nivcsw; /* involuntary context switches */ +}; + +/* + * sys/socket.h + */ + +/* + * Types + */ +#define TARGET_SOCK_STREAM 1 /* stream socket */ +#define TARGET_SOCK_DGRAM 2 /* datagram socket */ +#define TARGET_SOCK_RAW 3 /* raw-protocol interface */ +#define TARGET_SOCK_RDM 4 /* reliably-delivered message */ +#define TARGET_SOCK_SEQPACKET 5 /* sequenced packet stream */ + + +/* + * Option flags per-socket. + */ + +#define TARGET_SO_DEBUG 0x0001 /* turn on debugging info recording */ +#define TARGET_SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define TARGET_SO_REUSEADDR 0x0004 /* allow local address reuse */ +#define TARGET_SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define TARGET_SO_DONTROUTE 0x0010 /* just use interface addresses */ +#define TARGET_SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */ +#define TARGET_SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ +#define TARGET_SO_LINGER 0x0080 /* linger on close if data present */ +#define TARGET_SO_OOBINLINE 0x0100 /* leave received OOB data in line */ +#define TARGET_SO_REUSEPORT 0x0200 /* allow local address & port reuse */ +#define TARGET_SO_TIMESTAMP 0x0400 /* timestamp received dgram traffic */ +#define TARGET_SO_NOSIGPIPE 0x0800 /* no SIGPIPE from EPIPE */ +#define TARGET_SO_ACCEPTFILTER 0x1000 /* there is an accept filter */ +#define TARGET_SO_BINTIME 0x2000 /* timestamp received dgram traffic */ +#define TARGET_SO_NO_OFFLOAD 0x4000 /* socket cannot be offloaded */ +#define TARGET_SO_NO_DDP 0x8000 /* disable direct data placement */ + +/* + * Additional options, not kept in so_options. + */ +#define TARGET_SO_SNDBUF 0x1001 /* send buffer size */ +#define TARGET_SO_RCVBUF 0x1002 /* receive buffer size */ +#define TARGET_SO_SNDLOWAT 0x1003 /* send low-water mark */ +#define TARGET_SO_RCVLOWAT 0x1004 /* receive low-water mark */ +#define TARGET_SO_SNDTIMEO 0x1005 /* send timeout */ +#define TARGET_SO_RCVTIMEO 0x1006 /* receive timeout */ +#define TARGET_SO_ERROR 0x1007 /* get error status and clear */ +#define TARGET_SO_TYPE 0x1008 /* get socket type */ +#define TARGET_SO_LABEL 0x1009 /* socket's MAC label */ +#define TARGET_SO_PEERLABEL 0x1010 /* socket's peer's MAC label */ +#define TARGET_SO_LISTENQLIMIT 0x1011 /* socket's backlog limit */ +#define TARGET_SO_LISTENQLEN 0x1012 /* socket's complete queue length */ +#define TARGET_SO_LISTENINCQLEN 0x1013 /* socket's incomplete queue length */ +#define TARGET_SO_SETFIB 0x1014 /* use this FIB to route */ +#define TARGET_SO_USER_COOKIE 0x1015 /* user cookie (dummynet etc.) */ +#define TARGET_SO_PROTOCOL 0x1016 /* get socket protocol (Linux name) */ + +/* alias for SO_PROTOCOL (SunOS name) */ +#define TARGET_SO_PROTOTYPE TARGET_SO_PROTOCOL + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define TARGET_SOL_SOCKET 0xffff /* options for socket level */ + +#ifndef CMSG_ALIGN +#define CMSG_ALIGN(len) (((len)+sizeof(long)-1) & ~(sizeof(long)-1)) +#endif + +struct target_msghdr { + abi_long msg_name; /* So cket name */ + int32_t msg_namelen; /* Length of name */ + abi_long msg_iov; /* Data blocks */ + abi_long msg_iovlen; /* Number of blocks */ + abi_long msg_control; /* Per protocol magic + (eg BSD file descriptor passing) */ + abi_long msg_controllen; /* Length of cmsg list */ + int32_t msg_flags; /* flags on received message */ +}; + +struct target_sockaddr { + uint8_t sa_len; + uint8_t sa_family; + uint8_t sa_data[14]; +} QEMU_PACKED; + +struct target_in_addr { + uint32_t s_addr; /* big endian */ +}; + +struct target_cmsghdr { + abi_long cmsg_len; + int32_t cmsg_level; + int32_t cmsg_type; +}; + +#define TARGET_CMSG_DATA(cmsg) \ + ((unsigned char *)((struct target_cmsghdr *) (cmsg) + 1)) +#define TARGET_CMSG_NXTHDR(mhdr, cmsg) __target_cmsg_nxthdr(mhdr, cmsg) +#define TARGET_CMSG_ALIGN(len) (((len) + sizeof(abi_long) - 1) \ + & (size_t) ~(sizeof(abi_long) - 1)) +#define TARGET_CMSG_SPACE(len) (TARGET_CMSG_ALIGN(len) \ + + TARGET_CMSG_ALIGN(sizeof(struct target_cmsghdr))) +#define TARGET_CMSG_LEN(len) \ + (TARGET_CMSG_ALIGN(sizeof(struct target_cmsghdr)) + (len)) + +static inline struct target_cmsghdr *__target_cmsg_nxthdr( + struct target_msghdr *__mhdr, struct target_cmsghdr *__cmsg) +{ + struct target_cmsghdr *__ptr; + + __ptr = (struct target_cmsghdr *)((unsigned char *) __cmsg + + TARGET_CMSG_ALIGN(tswapal(__cmsg->cmsg_len))); + if ((unsigned long)((char *)(__ptr+1) - + (char *)(size_t)tswapal(__mhdr->msg_control)) > + tswapal(__mhdr->msg_controllen)) { + /* No more entries. */ + return (struct target_cmsghdr *)0; + } + return __cmsg; +} + +/* + * netinet/in.h + */ +struct target_ip_mreq { + struct target_in_addr imr_multiaddr; + struct target_in_addr imr_interface; +}; + +struct target_ip_mreqn { + struct target_in_addr imr_multiaddr; + struct target_in_addr imr_address; + int32_t imr_ifindex; +}; + +/* + * sys/stat.h + */ +#if defined(__FreeBSD_version) && __FreeBSD_version < 900000 +#define st_atim st_atimespec +#define st_ctim st_ctimespec +#define st_mtim st_mtimespec +#define st_birthtim st_birthtimespec +#endif + +struct target_freebsd_stat { + uint32_t st_dev; /* inode's device */ + uint32_t st_ino; /* inode's number */ + int16_t st_mode; /* inode protection mode */ + int16_t st_nlink; /* number of hard links */ + uint32_t st_uid; /* user ID of the file's owner */ + uint32_t st_gid; /* group ID of the file's group */ + uint32_t st_rdev; /* device type */ + struct target_freebsd_timespec st_atim; /* time last accessed */ + struct target_freebsd_timespec st_mtim; /* time last data modification */ + struct target_freebsd_timespec st_ctim; /* time last file status change */ + int64_t st_size; /* file size, in bytes */ + int64_t st_blocks; /* blocks allocated for file */ + uint32_t st_blksize; /* optimal blocksize for I/O */ + uint32_t st_flags; /* user defined flags for file */ + __uint32_t st_gen; /* file generation number */ + __int32_t st_lspare; + struct target_freebsd_timespec st_birthtim; /* time of file creation */ + /* + * Explicitly pad st_birthtim to 16 bytes so that the size of + * struct stat is backwards compatible. We use bitfields instead + * of an array of chars so that this doesn't require a C99 compiler + * to compile if the size of the padding is 0. We use 2 bitfields + * to cover up to 64 bits on 32-bit machines. We assume that + * CHAR_BIT is 8... + */ + unsigned int:(8 / 2) * (16 - (int)sizeof(struct target_freebsd_timespec)); + unsigned int:(8 / 2) * (16 - (int)sizeof(struct target_freebsd_timespec)); +} __packed; + +/* struct nstat is the same as stat above but without the st_lspare field */ +struct target_freebsd_nstat { + uint32_t st_dev; /* inode's device */ + uint32_t st_ino; /* inode's number */ + int16_t st_mode; /* inode protection mode */ + int16_t st_nlink; /* number of hard links */ + uint32_t st_uid; /* user ID of the file's owner */ + uint32_t st_gid; /* group ID of the file's group */ + uint32_t st_rdev; /* device type */ + struct target_freebsd_timespec st_atim; /* time last accessed */ + struct target_freebsd_timespec st_mtim; /* time last data modification */ + struct target_freebsd_timespec st_ctim; /* time last file status change */ + int64_t st_size; /* file size, in bytes */ + int64_t st_blocks; /* blocks allocated for file */ + uint32_t st_blksize; /* optimal blocksize for I/O */ + uint32_t st_flags; /* user defined flags for file */ + __uint32_t st_gen; /* file generation number */ + /* __int32_t st_lspare; */ + struct target_freebsd_timespec st_birthtim; /* time of file creation */ + /* + * Explicitly pad st_birthtim to 16 bytes so that the size of + * struct stat is backwards compatible. We use bitfields instead + * of an array of chars so that this doesn't require a C99 compiler + * to compile if the size of the padding is 0. We use 2 bitfields + * to cover up to 64 bits on 32-bit machines. We assume that + * CHAR_BIT is 8... + */ + unsigned int:(8 / 2) * (16 - (int)sizeof(struct target_freebsd_timespec)); + unsigned int:(8 / 2) * (16 - (int)sizeof(struct target_freebsd_timespec)); +} __packed; + +/* + * sys/mount.h + */ + +/* filesystem id type */ +typedef struct target_freebsd_fsid { int32_t val[2]; } target_freebsd_fsid_t; + +/* filesystem statistics */ +#define TARGET_MFSNAMELEN 16 /* length of type name include null */ +#define TARGET_MNAMELEN 88 /* size of on/from name bufs */ +#define TARGET_STATFS_VERSION 0x20030518 /* current version number */ +struct target_freebsd_statfs { + uint32_t f_version; /* structure version number */ + uint32_t f_type; /* type of filesystem */ + uint64_t f_flags; /* copy of mount exported flags */ + uint64_t f_bsize; /* filesystem fragment size */ + uint64_t f_iosize; /* optimal transfer block size */ + uint64_t f_blocks; /* total data blocks in filesystem */ + uint64_t f_bfree; /* free blocks in filesystem */ + int64_t f_bavail; /* free blocks avail to non-superuser */ + uint64_t f_files; /* total file nodes in filesystem */ + int64_t f_ffree; /* free nodes avail to non-superuser */ + uint64_t f_syncwrites; /* count of sync writes since mount */ + uint64_t f_asyncwrites; /* count of async writes since mount */ + uint64_t f_syncreads; /* count of sync reads since mount */ + uint64_t f_asyncreads; /* count of async reads since mount */ + uint64_t f_spare[10]; /* unused spare */ + uint32_t f_namemax; /* maximum filename length */ + uint32_t f_owner; /* user that mounted the filesystem */ + target_freebsd_fsid_t f_fsid; /* filesystem id */ + char f_charspare[80]; /* spare string space */ + char f_fstypename[TARGET_MFSNAMELEN]; /* filesys type name */ + char f_mntfromname[TARGET_MNAMELEN]; /* mount filesystem */ + char f_mntonname[TARGET_MNAMELEN]; /* dir on which mounted*/ +}; + +/* File identifier. These are unique per filesystem on a single machine. */ +#define TARGET_MAXFIDSZ 16 + +struct target_freebsd_fid { + u_short fid_len; /* len of data in bytes */ + u_short fid_data0; /* force longword align */ + char fid_data[TARGET_MAXFIDSZ]; /* data (variable len) */ +}; + +/* Generic file handle */ +struct target_freebsd_fhandle { + target_freebsd_fsid_t fh_fsid; /* Filesystem id of mount point */ + struct target_freebsd_fid fh_fid; /* Filesys specific id */ +}; +typedef struct target_freebsd_fhandle target_freebsd_fhandle_t; + +/* + * sys/fcntl.h + */ +#define TARGET_F_DUPFD 0 +#define TARGET_F_GETFD 1 +#define TARGET_F_SETFD 2 +#define TARGET_F_GETFL 3 +#define TARGET_F_SETFL 4 +#define TARGET_F_GETOWN 5 +#define TARGET_F_SETOWN 6 +#define TARGET_F_OGETLK 7 +#define TARGET_F_OSETLK 8 +#define TARGET_F_OSETLKW 9 +#define TARGET_F_DUP2FD 10 +#define TARGET_F_GETLK 11 +#define TARGET_F_SETLK 12 +#define TARGET_F_SETLKW 13 +#define TARGET_F_SETLK_REMOTE 14 +#define TARGET_F_READAHEAD 15 +#define TARGET_F_RDAHEAD 16 +#define TARGET_F_DUPFD_CLOEXEC 17 +#define TARGET_F_DUP2FD_CLOEXEC 18 + +struct target_freebsd_flock { + int64_t l_start; + int64_t l_len; + int32_t l_pid; + int16_t l_type; + int16_t l_whence; + int32_t l_sysid; +} QEMU_PACKED; + +/* + * FreeBSD thread and user mutex support. + */ + +/* sys/thr.h */ +#define TARGET_THR_SUSPENDED 0x0001 +#define TARGET_THR_SYSTEM_SCOPE 0x0002 + +struct target_freebsd_thr_param { + abi_ulong start_func; /* thread entry function. */ + abi_ulong arg; /* argument for entry function. */ + abi_ulong stack_base; /* stack base address. */ + abi_ulong stack_size; /* stack size. */ + abi_ulong tls_base; /* tls base address. */ + abi_ulong tls_size; /* tls size. */ + abi_ulong child_tid; /* address to store new TID. */ + abi_ulong parent_tid; /* parent access the new TID here. */ + int32_t flags; /* thread flags. */ + abi_ulong rtp; /* Real-time scheduling priority. */ + abi_ulong spare[3]; /* spares. */ +}; + +/* sys/rtprio.h */ +struct target_freebsd_rtprio { + uint16_t type; + uint16_t prio; +}; + +typedef struct { + CPUArchState *env; + long parent_tid; + pthread_mutex_t mutex; + pthread_cond_t cond; + pthread_t thread; + sigset_t sigmask; + struct target_freebsd_thr_param param; +} new_freebsd_thread_info_t; + +/* sys/utmx.h */ +/* op code for _umtx_op */ +#define TARGET_UMTX_OP_LOCK 0 +#define TARGET_UMTX_OP_UNLOCK 1 +#define TARGET_UMTX_OP_WAIT 2 +#define TARGET_UMTX_OP_WAKE 3 +#define TARGET_UMTX_OP_MUTEX_TRYLOCK 4 +#define TARGET_UMTX_OP_MUTEX_LOCK 5 +#define TARGET_UMTX_OP_MUTEX_UNLOCK 6 +#define TARGET_UMTX_OP_SET_CEILING 7 +#define TARGET_UMTX_OP_CV_WAIT 8 +#define TARGET_UMTX_OP_CV_SIGNAL 9 +#define TARGET_UMTX_OP_CV_BROADCAST 10 +#define TARGET_UMTX_OP_WAIT_UINT 11 +#define TARGET_UMTX_OP_RW_RDLOCK 12 +#define TARGET_UMTX_OP_RW_WRLOCK 13 +#define TARGET_UMTX_OP_RW_UNLOCK 14 +#define TARGET_UMTX_OP_WAIT_UINT_PRIVATE 15 +#define TARGET_UMTX_OP_WAKE_PRIVATE 16 +#define TARGET_UMTX_OP_MUTEX_WAIT 17 +#define TARGET_UMTX_OP_MUTEX_WAKE 18 +#define TARGET_UMTX_OP_SEM_WAIT 19 +#define TARGET_UMTX_OP_SEM_WAKE 20 +#define TARGET_UMTX_OP_NWAKE_PRIVATE 21 +#define TARGET_UMTX_OP_MUTEX_WAKE2 22 +#define TARGET_UMTX_OP_MAX 23 + +/* flags for UMTX_OP_CV_WAIT */ +#define TARGET_CVWAIT_CHECK_UNPARKING 0x01 +#define TARGET_CVWAIT_ABSTIME 0x02 +#define TARGET_CVWAIT_CLOCKID 0x04 + +#define TARGET_UMTX_UNOWNED 0x0 +#define TARGET_UMUTEX_UNOWNED 0x0 +#define TARGET_UMTX_CONTESTED (abi_ulong)(-1) +#define TARGET_UMUTEX_CONTESTED 0x80000000U + +/* flags for umutex */ +#define TARGET_UMUTEX_ERROR_CHECK 0x0002 /* Error-checking mutex */ +#define TARGET_UMUTEX_PRIO_INHERIT 0x0004 /* Priority inherited mutex */ +#define TARGET_UMUTEX_PRIO_PROTECT 0x0008 /* Priority protect mutex */ + +#define TARGET_UMUTEX_TRY 1 +#define TARGET_UMUTEX_WAIT 2 + +/* urwlock flags */ +#define TARGET_URWLOCK_PREFER_READER 0x0002 +#define TARGET_URWLOCK_WRITE_OWNER 0x80000000U +#define TARGET_URWLOCK_WRITE_WAITERS 0x40000000U +#define TARGET_URWLOCK_READ_WAITERS 0x20000000U +#define TARGET_URWLOCK_MAX_READERS 0x1fffffffU +#define TARGET_URWLOCK_READER_COUNT(c) ((c) & TARGET_URWLOCK_MAX_READERS) + +/* + * sys/acl.h + */ +#define TARGET_FREEBSD_ACL_MAX_ENTRIES 254 + +/* vaild acl_type_t arguments */ +#define TARGET_FREEBSD_ACL_TYPE_ACCESS_OLD 0x00000000 +#define TARGET_FREEBSD_ACL_TYPE_DEFAULT_OLD 0x00000001 +#define TARGET_FREEBSD_ACL_TYPE_ACCESS 0x00000002 +#define TARGET_FREEBSD_ACL_TYPE_DEFAULT 0x00000003 +#define TARGET_FREEBSD_ACL_TYPE_NFS4 0x00000004 + +struct target_freebsd_acl_entry { + uint32_t ae_tag; + uint32_t ae_id; + uint32_t ae_perm; + uint16_t ae_entry_type; + uint16_t ae_flags; +}; + +struct target_freebsd_acl { + uint32_t acl_maxcnt; + uint32_t acl_cnt; + int32_t acl_spare[4]; + struct target_freebsd_acl_entry acl_entry[TARGET_FREEBSD_ACL_MAX_ENTRIES]; +}; + +/* + * sys/uuid.h + */ + +#define TARGET_UUID_NODE_LEN 6 + +struct target_uuid { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq_hi_and_reserved; + uint8_t clock_seq_low; + uint8_t node[TARGET_UUID_NODE_LEN]; +}; + +#endif /* ! _SYSCALL_DEFS_H_ */ -- 1.7.8