From 3afaaa0324df7dc6edec7e1ba2fcbbbde6185fe5 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Tue, 28 May 2013 02:41:18 -0500 Subject: [PATCH 11/23] bsd-user: add shims for file related system calls To: Cc: This changes adds support for file and file system related system calls that are largely BSD OS independent. Also includes some more clean up of syscall.c. Signed-off-by: Stacey Son --- bsd-user/bsd-file.h | 1095 ++++++++++++++++++++++++++++++++ bsd-user/i386/target_arch_vmparam.h | 5 + bsd-user/mips/target_arch_vmparam.h | 5 + bsd-user/mips64/target_arch_vmparam.h | 5 + bsd-user/qemu.h | 36 + bsd-user/sparc/target_arch_vmparam.h | 5 + bsd-user/sparc64/target_arch_vmparam.h | 5 + bsd-user/syscall.c | 384 +++++++++--- bsd-user/x86_64/target_arch_vmparam.h | 5 + 9 files changed, 1467 insertions(+), 78 deletions(-) create mode 100644 bsd-user/bsd-file.h diff --git a/bsd-user/bsd-file.h b/bsd-user/bsd-file.h new file mode 100644 index 0000000..f2c0fc7 --- /dev/null +++ b/bsd-user/bsd-file.h @@ -0,0 +1,1095 @@ +/* + * file related system call shims and definitions + * + * 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 __BSD_FILE_H_ +#define __BSD_FILE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define target_to_host_bitmask(x, tbl) (x) + +#define LOCK_PATH(p, arg) do { \ + (p) = lock_user_string(arg); \ + if ((p) == NULL) { \ + return -TARGET_EFAULT; \ + } \ +} while (0) + +#define UNLOCK_PATH(p, arg) unlock_user((p), (arg), 0) + +struct target_pollfd { + int32_t fd; /* file descriptor */ + int16_t events; /* requested events */ + int16_t revents; /* returned events */ +}; + +static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr, + int count, int copy); +static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr, + int count, int copy); +extern int __getcwd(char *path, size_t len); + +/* read(2) */ +static inline abi_long do_bsd_read(abi_long arg1, abi_long arg2, abi_long arg3) +{ + abi_long ret; + void *p; + + p = lock_user(VERIFY_WRITE, arg2, arg3, 0); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(read(arg1, p, arg3)); + unlock_user(p, arg2, ret); + + return ret; +} + +/* pread(2) */ +static inline abi_long do_bsd_pread(abi_long arg1, abi_long arg2, abi_long arg3, + abi_long arg4, abi_long arg5) +{ + abi_long ret; + void *p; + + p = lock_user(VERIFY_WRITE, arg2, arg3, 0); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(pread(arg1, p, arg3, target_offset64(arg4, arg5))); + unlock_user(p, arg2, ret); + + return ret; +} + +/* readv(2) */ +static inline abi_long do_bsd_readv(abi_long arg1, abi_long arg2, abi_long arg3) +{ + abi_long ret; + int count = arg3; + struct iovec *vec; + + vec = alloca(count * sizeof(struct iovec)); + if (vec == NULL) { + return -TARGET_ENOMEM; + } + if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0) { + return -TARGET_EFAULT; + } + ret = get_errno(readv(arg1, vec, count)); + unlock_iovec(vec, arg2, count, 1); + + return ret; +} + +/* write(2) */ +static inline abi_long do_bsd_write(abi_long arg1, abi_long arg2, abi_long arg3) +{ + abi_long ret; + void *p; + + p = lock_user(VERIFY_READ, arg2, arg3, 1); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(write(arg1, p, arg3)); + unlock_user(p, arg2, 0); + + return ret; +} + +/* pwrite(2) */ +static inline abi_long do_bsd_pwrite(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + abi_long ret; + void *p; + + p = lock_user(VERIFY_READ, arg2, arg3, 1); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(pwrite(arg1, p, arg3, target_offset64(arg4, arg5))); + unlock_user(p, arg2, 0); + + return ret; +} + +/* writev(2) */ +static inline abi_long do_bsd_writev(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + abi_long ret; + int count = arg3; + struct iovec *vec; + + vec = alloca(count * sizeof(struct iovec)); + if (vec == NULL) { + return -TARGET_ENOMEM; + } + if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0) { + return -TARGET_EFAULT; + } + ret = get_errno(writev(arg1, vec, count)); + unlock_iovec(vec, arg2, count, 0); + + return ret; +} + +/* pwritev(2) */ +static inline abi_long do_bsd_pwritev(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + abi_long ret; + int count = arg3; + struct iovec *vec; + + vec = alloca(count * sizeof(struct iovec)); + if (vec == NULL) { + return -TARGET_ENOMEM; + } + if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0) { + return -TARGET_EFAULT; + } + ret = get_errno(pwritev(arg1, vec, count, target_offset64(arg4, arg5))); + unlock_iovec(vec, arg2, count, 0); + + return ret; +} + +/* open(2) */ +static inline abi_long do_bsd_open(abi_long arg1, abi_long arg2, abi_long arg3) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(open(path(p), target_to_host_bitmask(arg2, fcntl_flags_tbl), + arg3)); + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* openat(2) */ +static inline abi_long do_bsd_openat(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg2); + ret = get_errno(openat(arg1, path(p), + target_to_host_bitmask(arg3, fcntl_flags_tbl), arg4)); + UNLOCK_PATH(p, arg2); + + return ret; +} + +/* close(2) */ +static inline abi_long do_bsd_close(abi_long arg1) +{ + + return get_errno(close(arg1)); +} + +/* closefrom(2) */ +static inline abi_long do_bsd_closefrom(abi_long arg1) +{ + + closefrom(arg1); /* returns void */ + return get_errno(0); +} + +/* revoke(2) */ +static inline abi_long do_bsd_revoke(abi_long arg1) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(revoke(p)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* creat(2) (obsolete) */ +static inline abi_long do_bsd_creat(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(open(path(p), O_CREAT | O_TRUNC | O_WRONLY, arg2)); + UNLOCK_PATH(p, arg1); + + return ret; +} + + +/* access(2) */ +static inline abi_long do_bsd_access(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(access(path(p), arg2)); + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* eaccess(2) */ +static inline abi_long do_bsd_eaccess(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(eaccess(path(p), arg2)); + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* faccessat(2) */ +static inline abi_long do_bsd_faccessat(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg2); + ret = get_errno(faccessat(arg1, p, arg3, arg4)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg2); + + return ret; +} + +/* chdir(2) */ +static inline abi_long do_bsd_chdir(abi_long arg1) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(chdir(p)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* fchdir(2) */ +static inline abi_long do_bsd_fchdir(abi_long arg1) +{ + + return get_errno(fchdir(arg1)); +} + +/* rename(2) */ +static inline abi_long do_bsd_rename(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p1, *p2; + + LOCK_PATH(p1, arg1); + LOCK_PATH(p2, arg2); + if (!p1 || !p2) { + ret = -TARGET_EFAULT; + } else { + ret = get_errno(rename(p1, p2)); /* XXX path(p1), path(p2) */ + } + UNLOCK_PATH(p2, arg2); + UNLOCK_PATH(p1, arg1); + + return ret; +} + +/* renameat(2) */ +static inline abi_long do_bsd_renameat(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4) +{ + abi_long ret; + void *p1, *p2; + + LOCK_PATH(p1, arg1); + LOCK_PATH(p2, arg2); + if (!p1 || !p2) { + ret = -TARGET_EFAULT; + } else { + ret = get_errno(renameat(arg1, p1, arg3, p2)); + } + UNLOCK_PATH(p2, arg2); + UNLOCK_PATH(p1, arg1); + + return ret; +} + +/* link(2) */ +static inline abi_long do_bsd_link(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p1, *p2; + + LOCK_PATH(p1, arg1); + LOCK_PATH(p2, arg2); + if (!p1 || !p2) { + ret = -TARGET_EFAULT; + } else { + ret = get_errno(link(p1, p2)); /* XXX path(p1), path(p2) */ + } + UNLOCK_PATH(p2, arg2); + UNLOCK_PATH(p1, arg1); + + return ret; +} + +/* linkat(2) */ +static inline abi_long do_bsd_linkat(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + abi_long ret; + void *p1, *p2; + + LOCK_PATH(p1, arg2); + LOCK_PATH(p2, arg4); + if (!p1 || !p2) { + ret = -TARGET_EFAULT; + } else { + ret = get_errno(linkat(arg1, p1, arg3, p2, arg5)); + } + UNLOCK_PATH(p2, arg4); + UNLOCK_PATH(p1, arg2); + + return ret; +} + +/* unlink(2) */ +static inline abi_long do_bsd_unlink(abi_long arg1) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(unlink(p)); /* XXX path(p) */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* unlinkat(2) */ +static inline abi_long do_bsd_unlinkat(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg2); + ret = get_errno(unlinkat(arg1, p, arg3)); /* XXX path(p) */ + UNLOCK_PATH(p, arg2); + + return ret; +} + +/* mkdir(2) */ +static inline abi_long do_bsd_mkdir(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(mkdir(p, arg2)); /* XXX path(p) */ + UNLOCK_PATH(p, arg1); + + return ret; +} + + +/* mkdirat(2) */ +static inline abi_long do_bsd_mkdirat(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg2); + ret = get_errno(mkdirat(arg1, p, arg3)); + UNLOCK_PATH(p, arg2); + + return ret; +} + + +/* rmdir(2) */ +static inline abi_long do_bsd_rmdir(abi_long arg1) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(rmdir(p)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* undocumented __getcwd(char *buf, size_t len) system call */ +static inline abi_long do_bsd___getcwd(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + + p = lock_user(VERIFY_WRITE, arg1, arg2, 0); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(__getcwd(p, arg2)); + unlock_user(p, arg1, ret); + + return ret; +} + +/* dup(2) */ +static inline abi_long do_bsd_dup(abi_long arg1) +{ + + return get_errno(dup(arg1)); +} + +/* dup2(2) */ +static inline abi_long do_bsd_dup2(abi_long arg1, abi_long arg2) +{ + + return get_errno(dup2(arg1, arg2)); +} + +/* truncate(2) */ +static inline abi_long do_bsd_truncate(void *cpu_env, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + if (regpairs_aligned(cpu_env) != 0) { + arg2 = arg3; + arg3 = arg4; + } + ret = get_errno(truncate(p, target_offset64(arg2, arg3))); + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* ftruncate(2) */ +static inline abi_long do_bsd_ftruncate(void *cpu_env, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4) +{ + + if (regpairs_aligned(cpu_env)) { + arg2 = arg3; + arg3 = arg4; + } + return get_errno(ftruncate(arg1, target_offset64(arg2, arg3))); +} + +/* acct(2) */ +static inline abi_long do_bsd_acct(abi_long arg1) +{ + abi_long ret; + void *p; + + if (arg1 == 0) { + ret = get_errno(acct(NULL)); + } else { + LOCK_PATH(p, arg1); + ret = get_errno(acct(path(p))); + UNLOCK_PATH(p, arg1); + } + return ret; +} + +/* sync(2) */ +static inline abi_long do_bsd_sync(void) +{ + + sync(); + return 0; +} + +/* mount(2) */ +static inline abi_long do_bsd_mount(abi_long arg1, abi_long arg2, abi_long arg3, + abi_long arg4) +{ + abi_long ret; + void *p1, *p2; + + LOCK_PATH(p1, arg1); + LOCK_PATH(p2, arg2); + if (!p1 || !p2) { + ret = -TARGET_EFAULT; + } else { + /* + * XXX arg4 should be locked, but it isn't clear how to do that + * since it's it may be not be a NULL-terminated string. + */ + if (arg4 == 0) { + ret = get_errno(mount(p1, p2, arg3, NULL)); /* XXX path(p2)? */ + } else { + ret = get_errno(mount(p1, p2, arg3, g2h(arg4))); /* XXX path(p2)? */ + } + } + UNLOCK_PATH(p2, arg2); + UNLOCK_PATH(p1, arg1); + + return ret; +} + +/* unmount(2) */ +static inline abi_long do_bsd_unmount(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(unmount(p, arg2)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* nmount(2) */ +static inline abi_long do_bsd_nmount(abi_long arg1, abi_long count, + abi_long flags) +{ + abi_long ret; + struct iovec *vec; + + vec = alloca(count * sizeof(struct iovec)); + if (lock_iovec(VERIFY_READ, vec, arg1, count, 1) < 0) { + return -TARGET_EFAULT; + } + ret = get_errno(nmount(vec, count, flags)); + unlock_iovec(vec, arg1, count, 0); + + return ret; +} + +/* symlink(2) */ +static inline abi_long do_bsd_symlink(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p1, *p2; + + LOCK_PATH(p1, arg1); + LOCK_PATH(p2, arg2); + if (!p1 || !p2) { + ret = -TARGET_EFAULT; + } else { + ret = get_errno(symlink(p1, p2)); /* XXX path(p1), path(p2) */ + } + UNLOCK_PATH(p2, arg2); + UNLOCK_PATH(p1, arg1); + + return ret; +} + +/* symlinkat(2) */ +static inline abi_long do_bsd_symlinkat(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + abi_long ret; + void *p1, *p2; + + LOCK_PATH(p1, arg1); + LOCK_PATH(p2, arg3); + if (!p1 || !p2) { + ret = -TARGET_EFAULT; + } else { + ret = get_errno(symlinkat(p1, arg2, p2)); /* XXX path(p1), path(p2) */ + } + UNLOCK_PATH(p2, arg3); + UNLOCK_PATH(p1, arg1); + + return ret; +} + +/* readlink(2) */ +static inline abi_long do_bsd_readlink(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + abi_long ret; + void *p1, *p2; + + LOCK_PATH(p1, arg1); + p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0); + if (!p1 || !p2) { + ret = -TARGET_EFAULT; + } else { + ret = get_errno(readlink(path(p1), p2, arg3)); + } + unlock_user(p2, arg2, ret); + UNLOCK_PATH(p1, arg1); + + return ret; +} + +/* readlinkat(2) */ +static inline abi_long do_bsd_readlinkat(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4) +{ + abi_long ret; + void *p1, *p2; + + LOCK_PATH(p1, arg2); + p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0); + if (!p1 || !p2) { + ret = -TARGET_EFAULT; + } else { + ret = get_errno(readlinkat(arg1, p1, p2, arg4)); + } + unlock_user(p2, arg3, ret); + UNLOCK_PATH(p1, arg2); + + return ret; +} + +/* chmod(2) */ +static inline abi_long do_bsd_chmod(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(chmod(p, arg2)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* fchmod(2) */ +static inline abi_long do_bsd_fchmod(abi_long arg1, abi_long arg2) +{ + + return get_errno(fchmod(arg1, arg2)); +} + +/* lchmod(2) */ +static inline abi_long do_bsd_lchmod(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(lchmod(p, arg2)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* fchmodat(2) */ +static inline abi_long do_bsd_fchmodat(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg2); + ret = get_errno(fchmodat(arg1, p, arg3, arg4)); + UNLOCK_PATH(p, arg2); + + return ret; +} + +/* mknod(2) */ +static inline abi_long do_bsd_mknod(abi_long arg1, abi_long arg2, abi_long arg3) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(mknod(p, arg2, arg3)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* mknodat(2) */ +static inline abi_long do_bsd_mknodat(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg2); + ret = get_errno(mknodat(arg1, p, arg3, arg4)); + UNLOCK_PATH(p, arg2); + + return ret; +} + +/* chown(2) */ +static inline abi_long do_bsd_chown(abi_long arg1, abi_long arg2, abi_long arg3) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(chown(p, arg2, arg3)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* fchown(2) */ +static inline abi_long do_bsd_fchown(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + + return get_errno(fchown(arg1, arg2, arg3)); +} + +/* lchown(2) */ +static inline abi_long do_bsd_lchown(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(lchown(p, arg2, arg3)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* fchownat(2) */ +static inline abi_long do_bsd_fchownat(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg2); + ret = get_errno(fchownat(arg1, p, arg3, arg4, arg5)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg2); + + return ret; +} + +/* chflags(2) */ +static inline abi_long do_bsd_chflags(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(chflags(p, arg2)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* lchflags(2) */ +static inline abi_long do_bsd_lchflags(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(lchflags(p, arg2)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* fchflags(2) */ +static inline abi_long do_bsd_fchflags(abi_long arg1, abi_long arg2) +{ + + return get_errno(fchflags(arg1, arg2)); +} + +/* chroot(2) */ +static inline abi_long do_bsd_chroot(abi_long arg1) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(chroot(p)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* flock(2) */ +static abi_long do_bsd_flock(abi_long arg1, abi_long arg2) +{ + + return get_errno(flock(arg1, arg2)); +} + +/* mkfifo(2) */ +static inline abi_long do_bsd_mkfifo(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(mkfifo(p, arg2)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* mkfifoat(2) */ +static inline abi_long do_bsd_mkfifoat(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg2); + ret = get_errno(mkfifoat(arg1, p, arg3)); + UNLOCK_PATH(p, arg2); + + return ret; +} + +/* pathconf(2) */ +static inline abi_long do_bsd_pathconf(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(pathconf(p, arg2)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* lpathconf(2) */ +static inline abi_long do_bsd_lpathconf(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(lpathconf(p, arg2)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* fpathconf(2) */ +static inline abi_long do_bsd_fpathconf(abi_long arg1, abi_long arg2) +{ + + return get_errno(fpathconf(arg1, arg2)); +} + +/* undelete(2) */ +static inline abi_long do_bsd_undelete(abi_long arg1) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(undelete(p)); /* XXX path(p)? */ + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* poll(2) */ +static abi_long do_bsd_poll(abi_long arg1, abi_long arg2, abi_long arg3) +{ + abi_long ret; + nfds_t i, nfds = arg2; + int timeout = arg3; + struct pollfd *pfd; + struct target_pollfd *target_pfd; + + target_pfd = lock_user(VERIFY_WRITE, arg1, + sizeof(struct target_pollfd) * nfds, 1); + if (!target_pfd) { + return -TARGET_EFAULT; + } + pfd = alloca(sizeof(struct pollfd) * nfds); + for (i = 0; i < nfds; i++) { + pfd[i].fd = tswap32(target_pfd[i].fd); + pfd[i].events = tswap16(target_pfd[i].events); + } ret = get_errno(poll(pfd, nfds, timeout)); + if (!is_error(ret)) { + for (i = 0; i < nfds; i++) { + target_pfd[i].revents = tswap16(pfd[i].revents); + } + } + unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds); + + return ret; +} + +/* + * undocumented openbsd_poll(struct pollfd *fds, u_int nfds, int + * timeout) system call. + */ +static abi_long do_bsd_openbsd_poll(abi_long arg1, abi_long arg2, abi_long arg3) +{ + + qemu_log("qemu: Unsupported syscall openbsd_poll()\n"); + return -TARGET_ENOSYS; +} + +/* lseek(2) */ +static abi_long do_bsd_lseek(void *cpu_env, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4) +{ + abi_long ret; + +#if TARGET_ABI_BITS == 32 + /* 32-bit arch's use two 32 registers for 64 bit return value */ + int64_t res = lseek(arg1, target_offset64(arg2, arg3), arg4); + + if (res == -1) { + ret = get_errno(res); + } else { + ret = res & 0xFFFFFFFF; + set_second_rval(cpu_env, (res >> 32) & 0xFFFFFFFF); + } +#else + ret = get_errno(lseek(arg1, arg2, arg3)); +#endif + return ret; +} + +/* pipe(2) */ +static abi_long do_bsd_pipe(void *cpu_env, abi_long arg1) +{ + abi_long ret; + int host_pipe[2]; + int host_ret = pipe(host_pipe); + + if (host_ret != -1) { + set_second_rval(cpu_env, host_pipe[1]); + ret = host_pipe[0]; + } else { + ret = get_errno(host_ret); + } + return ret; +} + +/* swapon(2) */ +static abi_long do_bsd_swapon(abi_long arg1) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(swapon(path(p))); + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* swapoff(2) */ +static abi_long do_bsd_swapoff(abi_long arg1) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, arg1); + ret = get_errno(swapoff(path(p))); + UNLOCK_PATH(p, arg1); + + return ret; +} + +/* + * undocumented freebsd6_pread(int fd, void *buf, size_t nbyte, int pad, + * off_t offset) system call. + */ +static abi_long do_bsd_freebsd6_pread(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + + qemu_log("qemu: Unsupported syscall freebsd6_pread()\n"); + return -TARGET_ENOSYS; +} + +/* + * undocumented freebsd6_pwrite(int fd, void *buf, size_t nbyte, int pad, + * off_t offset) system call. + */ +static abi_long do_bsd_freebsd6_pwrite(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + + qemu_log("qemu: Unsupported syscall freebsd6_pwrite()\n"); + return -TARGET_ENOSYS; +} + +/* + * undocumented freebsd6_lseek(int fd, int pad, off_t offset, int whence) + * system call. + */ +static abi_long do_bsd_freebsd6_lseek(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4) +{ + + qemu_log("qemu: Unsupported syscall freebsd6_lseek()\n"); + return -TARGET_ENOSYS; +} + +/* + * undocumented freebsd6_truncate(char *path, int pad, off_t offset) system + * call. + */ +static abi_long do_bsd_freebsd6_truncate(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + + qemu_log("qemu: Unsupported syscall freebsd6_truncate()\n"); + return -TARGET_ENOSYS; +} + +/* + * undocumented freebsd6_ftruncate(int fd, int pad, off_t offset) system + * call. + */ +static abi_long do_bsd_freebsd6_ftruncate(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + + qemu_log("qemu: Unsupported syscall freebsd6_ftruncate()\n"); + return -TARGET_ENOSYS; +} + +#endif /* !__BSD_FILE_H_ */ diff --git a/bsd-user/i386/target_arch_vmparam.h b/bsd-user/i386/target_arch_vmparam.h index 6d3cf4f..654400a 100644 --- a/bsd-user/i386/target_arch_vmparam.h +++ b/bsd-user/i386/target_arch_vmparam.h @@ -18,4 +18,9 @@ static inline abi_ulong get_sp_from_cpustate(CPUX86State *state) return state->regs[R_ESP]; } +static inline void set_second_rval(CPUX86State *state, abi_ulong retval2) +{ + state->regs[R_EDX] = retval2; +} + #endif /* !_TARGET_ARCH_VMPARAM_H_ */ diff --git a/bsd-user/mips/target_arch_vmparam.h b/bsd-user/mips/target_arch_vmparam.h index 8f8bc9e..f9e54ce 100644 --- a/bsd-user/mips/target_arch_vmparam.h +++ b/bsd-user/mips/target_arch_vmparam.h @@ -39,4 +39,9 @@ static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state) return state->active_tc.gpr[29]; } +static inline void set_second_rval(CPUMIPSState *state, abi_ulong retval2) +{ + state->active_tc.gpr[3] = retval2; +} + #endif /* ! _TARGET_ARCH_VMPARAM_H_ */ diff --git a/bsd-user/mips64/target_arch_vmparam.h b/bsd-user/mips64/target_arch_vmparam.h index 0480035..1ba09e0 100644 --- a/bsd-user/mips64/target_arch_vmparam.h +++ b/bsd-user/mips64/target_arch_vmparam.h @@ -39,4 +39,9 @@ static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state) return state->active_tc.gpr[29]; } +static inline void set_second_rval(CPUMIPSState *state, abi_ulong retval2) +{ + state->active_tc.gpr[3] = retval2; +} + #endif /* ! _TARGET_ARCH_VMPARAM_H_ */ diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h index 02a05bb..da69073 100644 --- a/bsd-user/qemu.h +++ b/bsd-user/qemu.h @@ -422,6 +422,42 @@ static inline void *lock_user_string(abi_ulong guest_addr) #define unlock_user_struct(host_ptr, guest_addr, copy) \ unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0) +#if TARGET_ABI_BITS == 32 +static inline uint64_t +target_offset64(uint32_t word0, uint32_t word1) +{ +#ifdef TARGET_WORDS_BIGENDIAN + return ((uint64_t)word0 << 32) | word1; +#else + return ((uint64_t)word1 << 32) | word0; +#endif +} +#else /* TARGET_ABI_BITS != 32 */ +static inline uint64_t +target_offset64(uint64_t word0, uint64_t word1) +{ + return word0; +} +#endif /* TARGET_ABI_BITS != 32 */ + +/* ARM EABI and MIPS expect 64bit types aligned even on pairs of registers */ +#ifdef TARGET_ARM +static inline int +regpairs_aligned(void *cpu_env) { + return ((((CPUARMState *)cpu_env)->eabi) == 1); +} +#elif defined(TARGET_MIPS) && TARGET_ABI_BITS == 32 +static inline int regpairs_aligned(void *cpu_env) +{ + return 1; +} +#else +static inline int regpairs_aligned(void *cpu_env) +{ + return 0; +} +#endif + #if defined(CONFIG_USE_NPTL) #include #endif diff --git a/bsd-user/sparc/target_arch_vmparam.h b/bsd-user/sparc/target_arch_vmparam.h index 4bda417..75bbeeb 100644 --- a/bsd-user/sparc/target_arch_vmparam.h +++ b/bsd-user/sparc/target_arch_vmparam.h @@ -26,5 +26,10 @@ static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state) return state->regwptr[UREG_FP]; } +static inline void set_second_rval(CPUSPARCState *state, abi_ulong retval2) +{ + state->regwptr[1] = retval2; +} + #endif /* !_TARGET_ARCH_VMPARAM_H_ */ diff --git a/bsd-user/sparc64/target_arch_vmparam.h b/bsd-user/sparc64/target_arch_vmparam.h index 87548da..2c2323b 100644 --- a/bsd-user/sparc64/target_arch_vmparam.h +++ b/bsd-user/sparc64/target_arch_vmparam.h @@ -28,5 +28,10 @@ static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state) return state->regwptr[UREG_FP]; } +static inline void set_second_rval(CPUSPARCState *state, abi_ulong retval2) +{ + state->regwptr[1] = retval2; +} + #endif /* !_TARGET_ARCH_VMPARAM_H_ */ diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c index b64c0b0..2efa772 100644 --- a/bsd-user/syscall.c +++ b/bsd-user/syscall.c @@ -16,21 +16,16 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ -#include #include #include #include #include #include -#include -#include #include -#include #include #include #include #include -#include #include "qemu.h" #include "qemu-common.h" @@ -38,6 +33,7 @@ #define target_to_host_bitmask(x, tbl) (x) #include "bsd-errno.h" +#include "bsd-file.h" #include "bsd-mem.h" /* #define DEBUG */ @@ -282,7 +278,6 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg8) { abi_long ret; - void *p; #ifdef DEBUG gemu_log("freebsd syscall %d\n", num); @@ -300,39 +295,305 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, _exit(arg1); ret = 0; /* avoid warning */ break; - case TARGET_FREEBSD_NR_read: - if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) - goto efault; - ret = get_errno(read(arg1, p, arg3)); - unlock_user(p, arg2, ret); - break; - case TARGET_FREEBSD_NR_write: - if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) - goto efault; - ret = get_errno(write(arg1, p, arg3)); - unlock_user(p, arg2, 0); - break; - case TARGET_FREEBSD_NR_writev: - { - int count = arg3; - struct iovec *vec; - - vec = alloca(count * sizeof(struct iovec)); - if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0) - goto efault; - ret = get_errno(writev(arg1, vec, count)); - unlock_iovec(vec, arg2, count, 0); - } + + /* + * File system calls. + */ + case TARGET_FREEBSD_NR_read: /* read(2) */ + ret = do_bsd_read(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_pread: /* pread(2) */ + ret = do_bsd_pread(arg1, arg2, arg3, arg4, arg5); + break; + + case TARGET_FREEBSD_NR_readv: /* readv(2) */ + ret = do_bsd_read(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_write: /* write(2) */ + ret = do_bsd_write(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_pwrite: /* pwrite(2) */ + ret = do_bsd_pwrite(arg1, arg2, arg3, arg4, arg5); + break; + + case TARGET_FREEBSD_NR_writev: /* writev(2) */ + ret = do_bsd_writev(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_pwritev: /* pwritev(2) */ + ret = do_bsd_pwritev(arg1, arg2, arg3, arg4, arg5); + break; + + case TARGET_FREEBSD_NR_open: /* open(2) */ + ret = do_bsd_open(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_openat: /* openat(2) */ + ret = do_bsd_openat(arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_close: /* close(2) */ + ret = do_bsd_close(arg1); + break; + + case TARGET_FREEBSD_NR_closefrom: /* closefrom(2) */ + ret = do_bsd_closefrom(arg1); + break; + + case TARGET_FREEBSD_NR_revoke: /* revoke(2) */ + ret = do_bsd_revoke(arg1); + break; + +#ifdef TARGET_FREEBSD_NR_creat + case TARGET_FREEBSD_NR_creat: /* creat(2) (obsolete) */ + ret = do_bsd_creat(arg1); + break; +#endif + + case TARGET_FREEBSD_NR_access: /* access(2) */ + ret = do_bsd_access(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_eaccess: /* eaccess(2) */ + ret = do_bsd_eaccess(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_faccessat: /* faccessat(2) */ + ret = do_bsd_faccessat(arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_chdir: /* chdir(2) */ + ret = do_bsd_chdir(arg1); + break; + + case TARGET_FREEBSD_NR_fchdir: /* fchdir(2) */ + ret = do_bsd_fchdir(arg1); + break; + + case TARGET_FREEBSD_NR_rename: /* rename(2) */ + ret = do_bsd_rename(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_renameat: /* renameat(2) */ + ret = do_bsd_renameat(arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_link: /* link(2) */ + ret = do_bsd_link(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_linkat: /* linkat(2) */ + ret = do_bsd_linkat(arg1, arg2, arg3, arg4, arg5); + break; + + case TARGET_FREEBSD_NR_unlink: /* unlink(2) */ + ret = do_bsd_unlink(arg1); + break; + + case TARGET_FREEBSD_NR_unlinkat: /* unlinkat(2) */ + ret = do_bsd_unlinkat(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_mkdir: /* mkdir(2) */ + ret = do_bsd_mkdir(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_mkdirat: /* mkdirat(2) */ + ret = do_bsd_mkdirat(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_rmdir: /* rmdir(2) (XXX no rmdirat()?) */ + ret = do_bsd_rmdir(arg1); + break; + + case TARGET_FREEBSD_NR___getcwd: /* undocumented __getcwd() */ + ret = do_bsd___getcwd(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_dup: /* dup(2) */ + ret = do_bsd_dup(arg1); + break; + + case TARGET_FREEBSD_NR_dup2: /* dup2(2) */ + ret = do_bsd_dup2(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_truncate: /* truncate(2) */ + ret = do_bsd_truncate(cpu_env, arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_ftruncate: /* ftruncate(2) */ + ret = do_bsd_ftruncate(cpu_env, arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_acct: /* acct(2) */ + ret = do_bsd_acct(arg1); + break; + + case TARGET_FREEBSD_NR_sync: /* sync(2) */ + ret = do_bsd_sync(); + break; + + case TARGET_FREEBSD_NR_mount: /* mount(2) */ + ret = do_bsd_mount(arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_unmount: /* unmount(2) */ + ret = do_bsd_unmount(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_nmount: /* nmount(2) */ + ret = do_bsd_nmount(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_symlink: /* symlink(2) */ + ret = do_bsd_symlink(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_symlinkat: /* symlinkat(2) */ + ret = do_bsd_symlinkat(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_readlink: /* readlink(2) */ + ret = do_bsd_readlink(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_readlinkat: /* readlinkat(2) */ + ret = do_bsd_readlinkat(arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_chmod: /* chmod(2) */ + ret = do_bsd_chmod(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_fchmod: /* fchmod(2) */ + ret = do_bsd_fchmod(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_lchmod: /* lchmod(2) */ + ret = do_bsd_lchmod(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_fchmodat: /* fchmodat(2) */ + ret = do_bsd_fchmodat(arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_mknod: /* mknod(2) */ + ret = do_bsd_mknod(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_mknodat: /* mknodat(2) */ + ret = do_bsd_mknodat(arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_chown: /* chown(2) */ + ret = do_bsd_chown(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_fchown: /* fchown(2) */ + ret = do_bsd_fchown(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_lchown: /* lchown(2) */ + ret = do_bsd_lchown(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_fchownat: /* fchownat(2) */ + ret = do_bsd_fchownat(arg1, arg2, arg3, arg4, arg5); + break; + + case TARGET_FREEBSD_NR_chflags: /* chflags(2) */ + ret = do_bsd_chflags(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_lchflags: /* lchflags(2) */ + ret = do_bsd_lchflags(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_fchflags: /* fchflags(2) */ + ret = do_bsd_fchflags(arg2, arg2); + break; + + case TARGET_FREEBSD_NR_chroot: /* chroot(2) */ + ret = do_bsd_chroot(arg1); + break; + + case TARGET_FREEBSD_NR_flock: /* flock(2) */ + ret = do_bsd_flock(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_mkfifo: /* mkfifo(2) */ + ret = do_bsd_mkfifo(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_mkfifoat: /* mkfifoat(2) */ + ret = do_bsd_mkfifoat(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_pathconf: /* pathconf(2) */ + ret = do_bsd_pathconf(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_lpathconf: /* lpathconf(2) */ + ret = do_bsd_lpathconf(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_fpathconf: /* fpathconf(2) */ + ret = do_bsd_fpathconf(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_undelete: /* undelete(2) */ + ret = do_bsd_undelete(arg1); + break; + + case TARGET_FREEBSD_NR_poll: /* poll(2) */ + ret = do_bsd_poll(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_openbsd_poll: /* undocumented openbsd_poll() */ + ret = do_bsd_openbsd_poll(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_lseek: /* lseek(2) */ + ret = do_bsd_lseek(cpu_env, arg1, arg2, arg3, arg4); break; - case TARGET_FREEBSD_NR_open: - if (!(p = lock_user_string(arg1))) - goto efault; - ret = get_errno(open(path(p), - target_to_host_bitmask(arg2, fcntl_flags_tbl), - arg3)); - unlock_user(p, arg1, 0); + + case TARGET_FREEBSD_NR_pipe: /* pipe(2) */ + ret = do_bsd_pipe(cpu_env, arg1); + break; + + case TARGET_FREEBSD_NR_swapon: /* swapon(2) */ + ret = do_bsd_swapon(arg1); + break; + + case TARGET_FREEBSD_NR_swapoff: /* swapoff(2) */ + ret = do_bsd_swapoff(arg1); break; + case TARGET_FREEBSD_NR_freebsd6_pread: /* undocumented freebsd6_pread() */ + ret = do_bsd_freebsd6_pread(arg1, arg2, arg3, arg4, arg5); + break; + + case TARGET_FREEBSD_NR_freebsd6_pwrite: /* undocumented freebsd6_pwrite() */ + ret = do_bsd_freebsd6_pwrite(arg1, arg2, arg3, arg4, arg5); + break; + + case TARGET_FREEBSD_NR_freebsd6_lseek: /* undocumented freebsd6_lseek() */ + ret = do_bsd_freebsd6_lseek(arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_freebsd6_truncate: /* undocumented */ + ret = do_bsd_freebsd6_truncate(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_freebsd6_ftruncate: /* undocumented */ + ret = do_bsd_freebsd6_ftruncate(arg1, arg2, arg3); + break; + + /* * Memory management system calls. */ @@ -440,16 +701,13 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = get_errno(syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)); break; } - fail: + #ifdef DEBUG gemu_log(" = %ld\n", ret); #endif if (do_strace) print_freebsd_syscall_ret(num, ret); return ret; - efault: - ret = -TARGET_EFAULT; - goto fail; } abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1, @@ -457,7 +715,6 @@ abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg5, abi_long arg6) { abi_long ret; - void *p; #ifdef DEBUG gemu_log("netbsd syscall %d\n", num); @@ -475,25 +732,15 @@ abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1, _exit(arg1); ret = 0; /* avoid warning */ break; + case TARGET_NETBSD_NR_read: - if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) - goto efault; - ret = get_errno(read(arg1, p, arg3)); - unlock_user(p, arg2, ret); + ret = do_bsd_read(arg1, arg2, arg3); break; case TARGET_NETBSD_NR_write: - if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) - goto efault; - ret = get_errno(write(arg1, p, arg3)); - unlock_user(p, arg2, 0); + ret = do_bsd_write(arg1, arg2, arg3); break; case TARGET_NETBSD_NR_open: - if (!(p = lock_user_string(arg1))) - goto efault; - ret = get_errno(open(path(p), - target_to_host_bitmask(arg2, fcntl_flags_tbl), - arg3)); - unlock_user(p, arg1, 0); + ret = do_bsd_open(arg1, arg2, arg3); break; case TARGET_NETBSD_NR_mmap: @@ -511,16 +758,12 @@ abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1, ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); break; } - fail: #ifdef DEBUG gemu_log(" = %ld\n", ret); #endif if (do_strace) print_netbsd_syscall_ret(num, ret); return ret; - efault: - ret = -TARGET_EFAULT; - goto fail; } abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1, @@ -528,7 +771,6 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg5, abi_long arg6) { abi_long ret; - void *p; #ifdef DEBUG gemu_log("openbsd syscall %d\n", num); @@ -546,25 +788,15 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1, _exit(arg1); ret = 0; /* avoid warning */ break; + case TARGET_OPENBSD_NR_read: - if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) - goto efault; - ret = get_errno(read(arg1, p, arg3)); - unlock_user(p, arg2, ret); + ret = do_bsd_read(arg1, arg2, arg3); break; case TARGET_OPENBSD_NR_write: - if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) - goto efault; - ret = get_errno(write(arg1, p, arg3)); - unlock_user(p, arg2, 0); + ret = do_bsd_write(arg1, arg2, arg3); break; case TARGET_OPENBSD_NR_open: - if (!(p = lock_user_string(arg1))) - goto efault; - ret = get_errno(open(path(p), - target_to_host_bitmask(arg2, fcntl_flags_tbl), - arg3)); - unlock_user(p, arg1, 0); + ret = do_bsd_open(arg1, arg2, arg3); break; case TARGET_OPENBSD_NR_mmap: @@ -582,16 +814,12 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1, ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); break; } - fail: #ifdef DEBUG gemu_log(" = %ld\n", ret); #endif if (do_strace) print_openbsd_syscall_ret(num, ret); return ret; - efault: - ret = -TARGET_EFAULT; - goto fail; } void syscall_init(void) diff --git a/bsd-user/x86_64/target_arch_vmparam.h b/bsd-user/x86_64/target_arch_vmparam.h index 8acf7a5..5e13076 100644 --- a/bsd-user/x86_64/target_arch_vmparam.h +++ b/bsd-user/x86_64/target_arch_vmparam.h @@ -20,4 +20,9 @@ static inline abi_ulong get_sp_from_cpustate(CPUX86State *state) return state->regs[R_ESP]; } +static inline void set_second_rval(CPUX86State *state, abi_ulong retval2) +{ + state->regs[R_EDX] = retval2; +} + #endif /* !_TARGET_ARCH_VMPARAM_H_ */ -- 1.7.8