All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall
@ 2019-05-19 20:36 Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 01/74] linux-user: Setup split syscall infrastructure Richard Henderson
                   ` (76 more replies)
  0 siblings, 77 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Based-on: <20190519201953.20161-1-richard.henderson@linaro.org>
Aka "linux-user: path, clone, sparc, shmat fixes"

Version 6 was
https://lists.gnu.org/archive/html/qemu-devel/2019-01/msg04794.html

Since v5, I've fixed the ioctl failure that Laurent found, and
have done a few more syscalls.

I've tried to do more testing with LTP, but it's a really annoying
testsuite.  There are at least 3 tests that hang forever (before 
and after this patch set), and the host kernel's OOM handler kills
my login session, ending the test run.  This seems to be different
behaviour than I was seeing in January, when I did have test runs
that completed successfully.

OTOH, looking back at the v6 cover letter, I now see that I was
testing armhf and i386 as guests, whereas this time I was trying
aarch64 and ppc64 as guests.  32-bit guests unable to trigger the
host OOM killer?

Laurent, is there anything special that you're doing to see these
tests run to completion?


r~


Richard Henderson (74):
  linux-user: Setup split syscall infrastructure
  linux-user: Split out open, open_at
  linux-user: Share more code for open and openat
  linux-user: Tidy do_openat loop over fakes
  linux-user: Split out readlink, readlinkat
  linux-user: Split out close
  linux-user: Split out read, write
  linux-user: Reduce regpairs_aligned & target_offset64 ifdefs
  linux-user: Split out readv, writev
  linux-user: Split out pread64, pwrite64
  linux-user: Split out preadv, pwritev
  linux-user: Split out name_to_handle_at, open_by_handle_at
  linux-user: Split out ipc syscalls
  linux-user: Split out memory syscalls
  linux-user: Split out exit
  linux-user: Split out brk
  linux-user: Split out clone, fork, vfork
  linux-user: Split out wait4, waitid, waitpid
  linux-user: Implement rusage argument to waitid
  linux-user: Split out creat
  linux-user: Split out link, linkat
  linux-user: Split out unlink, unlinkat, rmdir
  linux-user: Split out execve
  linux-user: Implement execveat
  linux-user: Split out chdir
  linux-user: Split out time
  linux-user: Split out mknod, mknodat
  linux-user: Split out chmod, fchmod, fchmodat
  linux-user: Split out lseek, llseek
  linux-user: Split out getpid, getppid, getxpid
  linux-user: Split out mount
  linux-user: Split out umount, umount2
  linux-user: Split out stime
  linux-user: Split out alarm, pause
  linux-user: Split out utime, utimes, futimesat
  linux-user: Split out access, faccessat
  linux-user: Split out nice
  linux-user: Split out sync, syncfs
  linux-user: Split out kill
  linux-user: Split out rename, renameat, renameat2
  linux-user: Split out mkdir, mkdirat
  linux-user: Split out dup, dup2, dup3
  linux-user: Split out pipe, pipe2
  linux-user: Split out times
  linux-user: Split out acct
  linux-user: Move syscall_init to the end
  linux-user: Split out ioctl
  linux-user: Fix types in ioctl logging
  linux-user: Remove sentinel from ioctl_entries
  linux-user: Split out fcntl, fcntl64
  linux-user: Split out setpgid
  linux-user: Split out umask
  linux-user: Split out chroot
  linux-user: Split out getpgid, getpgrp
  linux-user: Split out getsid, setsid
  linux-user: Split out sigaction, rt_sigaction
  linux-user: Split out sgetmask, ssetmask
  linux-user: Split out sigprocmask, rt_sigprocmask
  linux-user: Split out sigpending, rt_sigpending
  linux-user: Split out sigsuspend, rt_sigsuspend
  linux-user: Split out rt_sigtimedwait
  linux-user: Split out rt_sigqueueinfo, rt_tgsigqueueinfo
  linux-user: Split out sigreturn, rt_sigreturn
  linux-user: Split out gethostname, sethostname
  linux-user: Split out getrlimit, setrlimit
  linux-user: Split out getrusage
  linux-user: Split out gettimeofday, settimeofday
  linux-user: Split out select, _newselect
  linux-user: Split out pselect6
  linux-user: Split out symlink, symlinkat
  linux-user: Split out swapon, swapoff
  linux-user: Split out reboot
  linux-user: Split out truncate, truncate64, ftruncate, ftruncate64
  linux-user: Split out getpriority, setpriority

 linux-user/syscall-defs.h      |  338 +++
 linux-user/syscall.h           |  103 +
 linux-user/strace.c            | 1569 +++-------
 linux-user/syscall-fcntl.inc.c |  322 ++
 linux-user/syscall-file.inc.c  | 1526 ++++++++++
 linux-user/syscall-ioctl.inc.c |  873 ++++++
 linux-user/syscall-ipc.inc.c   | 1088 +++++++
 linux-user/syscall-mem.inc.c   |  244 ++
 linux-user/syscall-proc.inc.c  |  758 +++++
 linux-user/syscall-sig.inc.c   |  549 ++++
 linux-user/syscall-time.inc.c  |   77 +
 linux-user/syscall.c           | 5045 ++------------------------------
 configure                      |   20 -
 linux-user/strace.list         |  414 ---
 14 files changed, 6512 insertions(+), 6414 deletions(-)
 create mode 100644 linux-user/syscall-defs.h
 create mode 100644 linux-user/syscall.h
 create mode 100644 linux-user/syscall-fcntl.inc.c
 create mode 100644 linux-user/syscall-file.inc.c
 create mode 100644 linux-user/syscall-ioctl.inc.c
 create mode 100644 linux-user/syscall-ipc.inc.c
 create mode 100644 linux-user/syscall-mem.inc.c
 create mode 100644 linux-user/syscall-proc.inc.c
 create mode 100644 linux-user/syscall-sig.inc.c
 create mode 100644 linux-user/syscall-time.inc.c

-- 
2.17.1



^ permalink raw reply	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 01/74] linux-user: Setup split syscall infrastructure
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 02/74] linux-user: Split out open, open_at Richard Henderson
                   ` (75 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Defines a unified structure for implementation and strace.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h |  17 ++
 linux-user/syscall.h      |  89 +++++++++
 linux-user/strace.c       | 388 +++++++++++++++++++++++++++-----------
 linux-user/syscall.c      | 103 +++++++++-
 4 files changed, 484 insertions(+), 113 deletions(-)
 create mode 100644 linux-user/syscall-defs.h
 create mode 100644 linux-user/syscall.h

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
new file mode 100644
index 0000000000..8c0490425a
--- /dev/null
+++ b/linux-user/syscall-defs.h
@@ -0,0 +1,17 @@
+/*
+ *  Linux syscall definitions
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
diff --git a/linux-user/syscall.h b/linux-user/syscall.h
new file mode 100644
index 0000000000..43b5dc0684
--- /dev/null
+++ b/linux-user/syscall.h
@@ -0,0 +1,89 @@
+/*
+ *  Linux syscalls internals
+ *  Copyright (c) 2018 Linaro, Limited.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LINUX_USER_SYSCALL_H
+#define LINUX_USER_SYSCALL_H 1
+
+typedef struct SyscallDef SyscallDef;
+
+/*
+ * This hook extracts max 6 arguments from max 8 input registers.
+ * In the process, register pairs that store 64-bit arguments are merged.
+ * Finally, syscalls are demultipliexed; e.g. the hook for socketcall will
+ * return the SyscallDef for bind, listen, etc.  In the process the hook
+ * may need to read from guest memory, or otherwise validate operands.
+ * On failure, set errno (to a host value) and return NULL;
+ * the (target adjusted) errno will be returned to the guest.
+ */
+typedef const SyscallDef *SyscallArgsFn(const SyscallDef *, int64_t out[6],
+                                        abi_long in[8]);
+
+/* This hook implements the syscall.  */
+typedef abi_long SyscallImplFn(CPUArchState *, int64_t, int64_t, int64_t,
+                               int64_t, int64_t, int64_t);
+
+/* This hook prints the arguments to the syscall for strace.  */
+typedef void SyscallPrintFn(const SyscallDef *, int64_t arg[6]);
+
+/* This hook print the return value from the syscall for strace.  */
+typedef void SyscallPrintRetFn(const SyscallDef *, abi_long);
+
+/*
+ * These flags describe the arguments for the generic fallback to
+ * SyscallPrintFn.  ARG_NONE indicates that the argument is not present.
+ */
+typedef enum {
+    ARG_NONE = 0,
+
+    /* These print as numbers of abi_long.  */
+    ARG_DEC,
+    ARG_HEX,
+    ARG_OCT,
+
+    /* These print as sets of flags.  */
+    ARG_ATDIRFD,
+    ARG_MODEFLAG,
+    ARG_OPENFLAG,
+
+    /* These are interpreted as pointers.  */
+    ARG_PTR,
+    ARG_STR,
+    ARG_BUF,
+
+    /* For a 32-bit host, force printing as a 64-bit operand.  */
+#if TARGET_ABI_BITS == 32
+    ARG_DEC64,
+#else
+    ARG_DEC64 = ARG_DEC,
+#endif
+} SyscallArgType;
+
+struct SyscallDef {
+    const char *name;
+    SyscallArgsFn *args;
+    SyscallImplFn *impl;
+    SyscallPrintFn *print;
+    SyscallPrintRetFn *print_ret;
+    SyscallArgType arg_type[6];
+};
+
+void print_syscall_def(const SyscallDef *def, int64_t args[6]);
+void print_syscall_def_ret(const SyscallDef *def, abi_long ret);
+void print_syscall_ptr_ret(const SyscallDef *def, abi_long ret);
+
+#endif
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 6f72a74c09..33a5b10c0a 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -10,6 +10,7 @@
 #include <linux/if_packet.h>
 #include <sched.h>
 #include "qemu.h"
+#include "syscall.h"
 
 int do_strace=0;
 
@@ -796,7 +797,7 @@ UNUSED static struct flags unlinkat_flags[] = {
     FLAG_END,
 };
 
-UNUSED static struct flags mode_flags[] = {
+static struct flags const mode_flags[] = {
     FLAG_GENERIC(S_IFSOCK),
     FLAG_GENERIC(S_IFLNK),
     FLAG_GENERIC(S_IFREG),
@@ -807,14 +808,14 @@ UNUSED static struct flags mode_flags[] = {
     FLAG_END,
 };
 
-UNUSED static struct flags open_access_flags[] = {
+static struct flags const open_access_flags[] = {
     FLAG_TARGET(O_RDONLY),
     FLAG_TARGET(O_WRONLY),
     FLAG_TARGET(O_RDWR),
     FLAG_END,
 };
 
-UNUSED static struct flags open_flags[] = {
+static struct flags const open_flags[] = {
     FLAG_TARGET(O_APPEND),
     FLAG_TARGET(O_CREAT),
     FLAG_TARGET(O_DIRECTORY),
@@ -989,84 +990,86 @@ get_comma(int last)
     return ((last) ? "" : ",");
 }
 
+static int add_flags(char *buf, int size, const struct flags *f,
+                     int flags, bool octal)
+{
+    const char *sep = "";
+    int off = 0;
+
+    if (flags == 0 && f->f_value == 0) {
+        return snprintf(buf, size, "%s", f->f_string);
+    }
+
+    for (; f->f_string != NULL; f++) {
+        if (f->f_value != 0 && (flags & f->f_value) == f->f_value) {
+            off += snprintf(buf + off, size - off, "%s%s", sep, f->f_string);
+            flags &= ~f->f_value;
+            sep = "|";
+        }
+    }
+
+    /* Print rest of the flags as numeric.  */
+    if (flags) {
+        if (octal) {
+            off += snprintf(buf + off, size - off, "%s%#o", sep, flags);
+        } else {
+            off += snprintf(buf + off, size - off, "%s%#x", sep, flags);
+        }
+    }
+    return off;
+}
+
 static void
 print_flags(const struct flags *f, abi_long flags, int last)
 {
-    const char *sep = "";
-    int n;
+    char buf[256];
+    add_flags(buf, sizeof(buf), f, flags, false);
+    gemu_log("%s%s", buf, get_comma(last));
+}
 
-    if ((flags == 0) && (f->f_value == 0)) {
-        gemu_log("%s%s", f->f_string, get_comma(last));
-        return;
-    }
-    for (n = 0; f->f_string != NULL; f++) {
-        if ((f->f_value != 0) && ((flags & f->f_value) == f->f_value)) {
-            gemu_log("%s%s", sep, f->f_string);
-            flags &= ~f->f_value;
-            sep = "|";
-            n++;
-        }
-    }
-
-    if (n > 0) {
-        /* print rest of the flags as numeric */
-        if (flags != 0) {
-            gemu_log("%s%#x%s", sep, (unsigned int)flags, get_comma(last));
-        } else {
-            gemu_log("%s", get_comma(last));
-        }
+static int add_atdirfd(char *buf, int size, int fd)
+{
+    if (fd == AT_FDCWD) {
+        return snprintf(buf, size, "AT_FDCWD");
     } else {
-        /* no string version of flags found, print them in hex then */
-        gemu_log("%#x%s", (unsigned int)flags, get_comma(last));
+        return snprintf(buf, size, "%d", fd);
     }
 }
 
 static void
 print_at_dirfd(abi_long dirfd, int last)
 {
-#ifdef AT_FDCWD
-    if (dirfd == AT_FDCWD) {
-        gemu_log("AT_FDCWD%s", get_comma(last));
-        return;
-    }
-#endif
-    gemu_log("%d%s", (int)dirfd, get_comma(last));
+    char buf[16];
+    add_atdirfd(buf, sizeof(buf), dirfd);
+    gemu_log("%s%s", buf, get_comma(last));
 }
 
 static void
 print_file_mode(abi_long mode, int last)
 {
-    const char *sep = "";
-    const struct flags *m;
+    char buf[256];
+    add_flags(buf, sizeof(buf), mode_flags, mode, true);
+    gemu_log("%s%s", buf, get_comma(last));
+}
 
-    for (m = &mode_flags[0]; m->f_string != NULL; m++) {
-        if ((m->f_value & mode) == m->f_value) {
-            gemu_log("%s%s", m->f_string, sep);
-            sep = "|";
-            mode &= ~m->f_value;
-            break;
-        }
+static int add_open_flags(char *buf, int size, int flags)
+{
+    int off = add_flags(buf, size, open_access_flags,
+                        flags & TARGET_O_ACCMODE, false);
+    flags &= ~TARGET_O_ACCMODE;
+    if (flags == 0 || off + 2 >= size) {
+        return off;
     }
-
-    mode &= ~S_IFMT;
-    /* print rest of the mode as octal */
-    if (mode != 0)
-        gemu_log("%s%#o", sep, (unsigned int)mode);
-
-    gemu_log("%s", get_comma(last));
+    buf[off++] = '|';
+    return off + add_flags(buf + off, size - off, open_flags, flags, true);
 }
 
 static void
 print_open_flags(abi_long flags, int last)
 {
-    print_flags(open_access_flags, flags & TARGET_O_ACCMODE, 1);
-    flags &= ~TARGET_O_ACCMODE;
-    if (flags == 0) {
-        gemu_log("%s", get_comma(last));
-        return;
-    }
-    gemu_log("|");
-    print_flags(open_flags, flags, last);
+    char buf[256];
+    add_open_flags(buf, sizeof(buf), flags);
+    gemu_log("%s%s", buf, get_comma(last));
 }
 
 static void
@@ -1083,48 +1086,86 @@ print_syscall_epilogue(const struct syscallname *sc)
     gemu_log(")");
 }
 
-static void
-print_string(abi_long addr, int last)
+static int add_pointer(char *buf, int size, abi_ulong addr)
 {
-    char *s;
-
-    if ((s = lock_user_string(addr)) != NULL) {
-        gemu_log("\"%s\"%s", s, get_comma(last));
-        unlock_user(s, addr, 0);
+    if (addr) {
+        return snprintf(buf, size, "0x" TARGET_ABI_FMT_lx, addr);
     } else {
-        /* can't get string out of it, so print it as pointer */
-        print_pointer(addr, last);
+        return snprintf(buf, size, "NULL");
     }
 }
 
+static int add_string(char *buf, int size, abi_ulong addr)
+{
+    char *s = lock_user_string(addr);
+    if (s) {
+        /* TODO: Escape special characters within the string.  */
+        /* TODO: Limit the string length for logging.  */
+        int len = snprintf(buf, size, "\"%s\"", s);
+        unlock_user(s, addr, 0);
+        return len;
+    }
+    return add_pointer(buf, size, addr);
+}
+
+static void
+print_string(abi_long addr, int last)
+{
+    char buf[256];
+    add_string(buf, sizeof(buf), addr);
+    gemu_log("%s%s", buf, get_comma(last));
+}
+
 #define MAX_PRINT_BUF 40
+
+static int add_buffer(char *buf, int size, abi_long addr, abi_ulong len)
+{
+    unsigned char *p;
+    int off = 0;
+    abi_ulong i;
+
+    p = lock_user(VERIFY_READ, addr, MIN(len, MAX_PRINT_BUF), 1);
+    if (!p) {
+        return add_pointer(buf, size, addr);
+    }
+
+    buf[0] = '"';
+    off = 1;
+
+    for (i = 0; i < MAX_PRINT_BUF; ++i) {
+        int len;
+
+        if (isprint(p[i])) {
+            buf[off] = p[i];
+            len = 1;
+        } else {
+            len = snprintf(buf + off, size - off, "\\%o", p[i]);
+        }
+        off += len;
+        if (off + 2 >= size) {
+            goto overflow;
+        }
+    }
+    unlock_user(p, addr, 0);
+
+    if (i == len && off + 2 < size) {
+        buf[off] = '"';
+        buf[off + 1] = 0;
+        return off + 1;
+    }
+
+ overflow:
+    off = MIN(off, size - 5);
+    strcpy(buf + off, "...\"");
+    return off + 4;
+}
+
 static void
 print_buf(abi_long addr, abi_long len, int last)
 {
-    uint8_t *s;
-    int i;
-
-    s = lock_user(VERIFY_READ, addr, len, 1);
-    if (s) {
-        gemu_log("\"");
-        for (i = 0; i < MAX_PRINT_BUF && i < len; i++) {
-            if (isprint(s[i])) {
-                gemu_log("%c", s[i]);
-            } else {
-                gemu_log("\\%o", s[i]);
-            }
-        }
-        gemu_log("\"");
-        if (i != len) {
-            gemu_log("...");
-        }
-        if (!last) {
-            gemu_log(",");
-        }
-        unlock_user(s, addr, 0);
-    } else {
-        print_pointer(addr, last);
-    }
+    char buf[256];
+    add_buffer(buf, sizeof(buf), addr, len);
+    gemu_log("%s%s", buf, get_comma(last));
 }
 
 /*
@@ -1143,10 +1184,9 @@ print_raw_param(const char *fmt, abi_long param, int last)
 static void
 print_pointer(abi_long p, int last)
 {
-    if (p == 0)
-        gemu_log("NULL%s", get_comma(last));
-    else
-        gemu_log("0x" TARGET_ABI_FMT_lx "%s", p, get_comma(last));
+    char buf[24];
+    add_pointer(buf, sizeof(buf), p);
+    gemu_log("%s%s", buf, get_comma(last));
 }
 
 /*
@@ -2650,32 +2690,170 @@ print_syscall(int num,
     gemu_log("Unknown syscall %d\n", num);
 }
 
+static void print_syscall_def1(const SyscallDef *def, int64_t args[6])
+{
+    char buf[1024], *b = buf;
+    int i, rest = sizeof(buf);
+
+    /*
+     * Render the argument list into BUF.  This allows us to log the
+     * entire syscall in one write statement at the end.
+     * While this is still not quite as good as separate files, a-la
+     * strace -ff, it can minimize confusion with a multithreaded guest.
+     */
+    buf[0] = 0;
+    for (i = 0; i < 6; ++i) {
+        SyscallArgType type = def->arg_type[i];
+        int64_t arg = args[i];
+        int len;
+
+        if (type == ARG_NONE) {
+            break;
+        }
+
+        /* Validate remaining space.  */
+        if (rest < 4) {
+            goto overflow;
+        }
+
+        /* Add separator.  */
+        if (i > 0) {
+            b[0] = ',';
+            b[1] = ' ';
+            b += 2;
+            rest -= 2;
+        }
+
+        switch (type) {
+#if TARGET_ABI_BITS == 32
+        /*
+         * ??? We don't have TARGET_ABI_FMT_* macros for exactly
+         * what we want here.  For this case it probably makes
+         * most sense to just special case.
+         */
+        case ARG_DEC:
+            len = snprintf(b, rest, "%d", (int32_t)arg);
+            break;
+        case ARG_HEX:
+            len = snprintf(b, rest, "%#x", (uint32_t)arg);
+            break;
+        case ARG_OCT:
+            len = snprintf(b, rest, "%#o", (uint32_t)arg);
+            break;
+        case ARG_DEC64:
+            len = snprintf(b, rest, "%" PRId64, arg);
+            break;
+#else
+        case ARG_DEC:
+            len = snprintf(b, rest, "%" PRId64, arg);
+            break;
+        case ARG_OCT:
+            len = snprintf(b, rest, "%" PRIo64, arg);
+            break;
+        case ARG_HEX:
+            len = snprintf(b, rest, "%" PRIx64, arg);
+            break;
+#endif
+        case ARG_ATDIRFD:
+            len = add_atdirfd(b, rest, arg);
+            break;
+        case ARG_MODEFLAG:
+            len = add_flags(b, rest, mode_flags, arg, true);
+            break;
+        case ARG_OPENFLAG:
+            len = add_open_flags(b, rest, arg);
+            break;
+        case ARG_PTR:
+            len = add_pointer(b, rest, arg);
+            break;
+        case ARG_STR:
+            len = add_string(b, rest, arg);
+            break;
+        case ARG_BUF:
+            len = add_buffer(b, rest, arg, MAX_PRINT_BUF);
+            break;
+        default:
+            g_assert_not_reached();
+        }
+
+        b += len;
+        rest -= len;
+        if (rest == 0) {
+            goto overflow;
+        }
+    }
+    goto done;
+
+ overflow:
+    strcpy(buf + sizeof(buf) - 4, "...");
+ done:
+    gemu_log("%d %s(%s)", getpid(), def->name, buf);
+}
+
+void print_syscall_def(const SyscallDef *def, int64_t args[6])
+{
+    SyscallPrintFn *print = def->print;
+    if (!print) {
+        print = print_syscall_def1;
+    }
+    print(def, args);
+}
+
+static void print_syscall_def_ret1(const SyscallDef *def, abi_long ret)
+{
+    if (is_error(ret)) {
+        const char *errstr = target_strerror(-ret);
+        if (errstr) {
+            gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n",
+                     -ret, errstr);
+        } else {
+            gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld "\n", -ret);
+        }
+    } else {
+        gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
+    }
+}
 
 void
 print_syscall_ret(int num, abi_long ret)
 {
     int i;
-    const char *errstr = NULL;
 
     for(i=0;i<nsyscalls;i++)
         if( scnames[i].nr == num ) {
             if( scnames[i].result != NULL ) {
                 scnames[i].result(&scnames[i],ret);
             } else {
-                if (ret < 0) {
-                    errstr = target_strerror(-ret);
-                }
-                if (errstr) {
-                    gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n",
-                             -ret, errstr);
-                } else {
-                    gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
-                }
+                print_syscall_def_ret1(NULL, ret);
             }
             break;
         }
 }
 
+void print_syscall_ptr_ret(const SyscallDef *def, abi_long ret)
+{
+    if (is_error(ret)) {
+        const char *errstr = target_strerror(-ret);
+        if (errstr) {
+            gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n",
+                     -ret, errstr);
+        } else {
+            gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld "\n", -ret);
+        }
+    } else {
+        gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
+    }
+}
+
+void print_syscall_def_ret(const SyscallDef *def, abi_long ret)
+{
+    SyscallPrintRetFn *print = def->print_ret;
+    if (!print) {
+        print = print_syscall_def_ret1;
+    }
+    print(def, ret);
+}
+
 void print_taken_signal(int target_signum, const target_siginfo_t *tinfo)
 {
     /* Print the strace output for a signal being taken:
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 1feb740f66..e27cab34af 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -108,6 +108,7 @@
 
 #include "qemu.h"
 #include "fd-trans.h"
+#include "syscall.h"
 
 #ifndef CLONE_IO
 #define CLONE_IO                0x80000000      /* Clone io context */
@@ -11631,12 +11632,70 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     return ret;
 }
 
+/* Emit the signature for a SyscallArgsFn.  */
+#define SYSCALL_ARGS(NAME) \
+    static const SyscallDef *args_##NAME(const SyscallDef *def, \
+                                         int64_t out[6], abi_long in[8])
+
+/* Emit the signature for a SyscallImplFn.  */
+#define SYSCALL_IMPL(NAME) \
+    static abi_long impl_##NAME(CPUArchState *cpu_env, int64_t arg1, \
+                                int64_t arg2, int64_t arg3, int64_t arg4, \
+                                int64_t arg5, int64_t arg6)
+
+
+#undef SYSCALL_IMPL
+#undef SYSCALL_ARGS
+
+/*
+ * Emit a complete SyscallDef structure.
+ */
+#define SYSCALL_DEF_FULL(NAME, ...) \
+    static const SyscallDef def_##NAME = { .name = #NAME, __VA_ARGS__ }
+
+/*
+ * Emit the definition for a "simple" syscall.  Such does not use
+ * SyscallArgsFn and only uses arg_type for strace.
+ */
+#define SYSCALL_DEF(NAME, ...) \
+    SYSCALL_DEF_FULL(NAME, .impl = impl_##NAME, .arg_type = { __VA_ARGS__ })
+
+/* Similarly, but also uses an args hook.  */
+#define SYSCALL_DEF_ARGS(NAME, ...) \
+    SYSCALL_DEF_FULL(NAME, .impl = impl_##NAME, .args = args_##NAME, \
+                     .arg_type = { __VA_ARGS__ })
+
+#include "syscall-defs.h"
+
+#undef SYSCALL_DEF
+#undef SYSCALL_DEF_ARGS
+#undef SYSCALL_DEF_FULL
+
+static const SyscallDef *syscall_table(int num)
+{
+#define SYSCALL_DEF(NAME, ...)  case TARGET_NR_##NAME: return &def_##NAME
+#define SYSCALL_DEF_ARGS(NAME, ...)  SYSCALL_DEF(NAME)
+#define SYSCALL_DEF_FULL(NAME, ...)  SYSCALL_DEF(NAME)
+
+    switch (num) {
+#include "syscall-defs.h"
+    }
+    return NULL;
+
+#undef SYSCALL_DEF
+#undef SYSCALL_DEF_ARGS
+#undef SYSCALL_DEF_FULL
+}
+
 abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                     abi_long arg2, abi_long arg3, abi_long arg4,
                     abi_long arg5, abi_long arg6, abi_long arg7,
                     abi_long arg8)
 {
     CPUState *cpu = ENV_GET_CPU(cpu_env);
+    const SyscallDef *def, *orig_def;
+    abi_long raw_args[8] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 };
+    int64_t  out_args[6] = { arg1, arg2, arg3, arg4, arg5, arg6 };
     abi_long ret;
 
 #ifdef DEBUG_ERESTARTSYS
@@ -11656,16 +11715,44 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     trace_guest_user_syscall(cpu, num, arg1, arg2, arg3, arg4,
                              arg5, arg6, arg7, arg8);
 
-    if (unlikely(do_strace)) {
-        print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
-        ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
-                          arg5, arg6, arg7, arg8);
-        print_syscall_ret(num, ret);
-    } else {
-        ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
-                          arg5, arg6, arg7, arg8);
+    orig_def = def = syscall_table(num);
+    if (def == NULL) {
+        /* Unconverted.  */
+        if (unlikely(do_strace)) {
+            print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
+            ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
+                              arg5, arg6, arg7, arg8);
+            print_syscall_ret(num, ret);
+        } else {
+            ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
+                              arg5, arg6, arg7, arg8);
+        }
+        goto fini;
     }
 
+    if (def->args) {
+        def = def->args(def, out_args, raw_args);
+        if (unlikely(def == NULL)) {
+            ret = -host_to_target_errno(errno);
+            if (unlikely(do_strace)) {
+                print_syscall_def(orig_def, out_args);
+                print_syscall_def_ret(orig_def, ret);
+            }
+            goto fini;
+        }
+    }
+
+    if (unlikely(do_strace)) {
+        print_syscall_def(def, out_args);
+        ret = def->impl(cpu_env, out_args[0], out_args[1], out_args[2],
+                        out_args[3], out_args[4], out_args[5]);
+        print_syscall_def_ret(def, ret);
+    } else {
+        ret = def->impl(cpu_env, out_args[0], out_args[1], out_args[2],
+                        out_args[3], out_args[4], out_args[5]);
+    }
+
+ fini:
     trace_guest_user_syscall_ret(cpu, num, ret);
     return ret;
 }
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 02/74] linux-user: Split out open, open_at
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 01/74] linux-user: Setup split syscall infrastructure Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 03/74] linux-user: Share more code for open and openat Richard Henderson
                   ` (74 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

For the moment, leave a forward declaration for is_proc_myself
until the readlink syscalls are also moved to syscall-file.inc.c.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |   5 +
 linux-user/strace.c           |  35 ----
 linux-user/syscall-file.inc.c | 325 ++++++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 288 +-----------------------------
 linux-user/strace.list        |   6 -
 5 files changed, 332 insertions(+), 327 deletions(-)
 create mode 100644 linux-user/syscall-file.inc.c

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 8c0490425a..1f3a9c47ab 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -15,3 +15,8 @@
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
+
+#ifdef TARGET_NR_open
+SYSCALL_DEF(open, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG);
+#endif
+SYSCALL_DEF(openat, ARG_ATDIRFD, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG);
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 33a5b10c0a..24ef14b5e6 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -2228,41 +2228,6 @@ print_mq_open(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_open
-static void
-print_open(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    int is_creat = (arg1 & TARGET_O_CREAT);
-
-    print_syscall_prologue(name);
-    print_string(arg0, 0);
-    print_open_flags(arg1, (is_creat == 0));
-    if (is_creat)
-        print_file_mode(arg2, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
-#ifdef TARGET_NR_openat
-static void
-print_openat(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    int is_creat = (arg2 & TARGET_O_CREAT);
-
-    print_syscall_prologue(name);
-    print_at_dirfd(arg0, 0);
-    print_string(arg1, 0);
-    print_open_flags(arg2, (is_creat == 0));
-    if (is_creat)
-        print_file_mode(arg3, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_mq_unlink
 static void
 print_mq_unlink(const struct syscallname *name,
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
new file mode 100644
index 0000000000..7974148ccb
--- /dev/null
+++ b/linux-user/syscall-file.inc.c
@@ -0,0 +1,325 @@
+/*
+ *  Linux file-related syscall implementations
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Helpers for do_openat, manipulating /proc/self/foo.
+ */
+
+static int open_self_cmdline(void *cpu_env, int fd)
+{
+    CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
+    struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm;
+    int i;
+
+    for (i = 0; i < bprm->argc; i++) {
+        size_t len = strlen(bprm->argv[i]) + 1;
+
+        if (write(fd, bprm->argv[i], len) != len) {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+static int open_self_maps(void *cpu_env, int fd)
+{
+    CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
+    TaskState *ts = cpu->opaque;
+    FILE *fp;
+    char *line = NULL;
+    size_t len = 0;
+    ssize_t read;
+
+    fp = fopen("/proc/self/maps", "r");
+    if (fp == NULL) {
+        return -1;
+    }
+
+    while ((read = getline(&line, &len, fp)) != -1) {
+        int fields, dev_maj, dev_min, inode;
+        uint64_t min, max, offset;
+        char flag_r, flag_w, flag_x, flag_p;
+        char path[512] = "";
+        fields = sscanf(line, "%"PRIx64"-%"PRIx64" %c%c%c%c %"PRIx64" %x:%x %d"
+                        " %512s", &min, &max, &flag_r, &flag_w, &flag_x,
+                        &flag_p, &offset, &dev_maj, &dev_min, &inode, path);
+
+        if ((fields < 10) || (fields > 11)) {
+            continue;
+        }
+        if (h2g_valid(min)) {
+            int flags = page_get_flags(h2g(min));
+            max = h2g_valid(max - 1) ? max : (uintptr_t)g2h(GUEST_ADDR_MAX) + 1;
+            if (page_check_range(h2g(min), max - min, flags) == -1) {
+                continue;
+            }
+            if (h2g(min) == ts->info->stack_limit) {
+                pstrcpy(path, sizeof(path), "      [stack]");
+            }
+            dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr
+                    " %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n",
+                    h2g(min), h2g(max - 1) + 1, flag_r, flag_w,
+                    flag_x, flag_p, offset, dev_maj, dev_min, inode,
+                    path[0] ? "         " : "", path);
+        }
+    }
+
+    free(line);
+    fclose(fp);
+
+    return 0;
+}
+
+static int open_self_stat(void *cpu_env, int fd)
+{
+    CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
+    TaskState *ts = cpu->opaque;
+    abi_ulong start_stack = ts->info->start_stack;
+    int i;
+
+    for (i = 0; i < 44; i++) {
+        char buf[128];
+        int len;
+        uint64_t val = 0;
+
+        if (i == 0) {
+            /* pid */
+            val = getpid();
+            snprintf(buf, sizeof(buf), "%"PRId64 " ", val);
+        } else if (i == 1) {
+            /* app name */
+            snprintf(buf, sizeof(buf), "(%s) ", ts->bprm->argv[0]);
+        } else if (i == 27) {
+            /* stack bottom */
+            val = start_stack;
+            snprintf(buf, sizeof(buf), "%"PRId64 " ", val);
+        } else {
+            /* for the rest, there is MasterCard */
+            snprintf(buf, sizeof(buf), "0%c", i == 43 ? '\n' : ' ');
+        }
+
+        len = strlen(buf);
+        if (write(fd, buf, len) != len) {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+static int open_self_auxv(void *cpu_env, int fd)
+{
+    CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
+    TaskState *ts = cpu->opaque;
+    abi_ulong auxv = ts->info->saved_auxv;
+    abi_ulong len = ts->info->auxv_len;
+    char *ptr;
+
+    /*
+     * Auxiliary vector is stored in target process stack.
+     * read in whole auxv vector and copy it to file
+     */
+    ptr = lock_user(VERIFY_READ, auxv, len, 0);
+    if (ptr != NULL) {
+        while (len > 0) {
+            ssize_t r;
+            r = write(fd, ptr, len);
+            if (r <= 0) {
+                break;
+            }
+            len -= r;
+            ptr += r;
+        }
+        lseek(fd, 0, SEEK_SET);
+        unlock_user(ptr, auxv, len);
+    }
+
+    return 0;
+}
+
+static int is_proc_myself(const char *filename, const char *entry)
+{
+    if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
+        filename += strlen("/proc/");
+        if (!strncmp(filename, "self/", strlen("self/"))) {
+            filename += strlen("self/");
+        } else if (*filename >= '1' && *filename <= '9') {
+            char myself[80];
+            snprintf(myself, sizeof(myself), "%d/", getpid());
+            if (!strncmp(filename, myself, strlen(myself))) {
+                filename += strlen(myself);
+            } else {
+                return 0;
+            }
+        } else {
+            return 0;
+        }
+        if (!strcmp(filename, entry)) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
+static int is_proc(const char *filename, const char *entry)
+{
+    return strcmp(filename, entry) == 0;
+}
+
+static int open_net_route(void *cpu_env, int fd)
+{
+    FILE *fp;
+    char *line = NULL;
+    size_t len = 0;
+    ssize_t read;
+
+    fp = fopen("/proc/net/route", "r");
+    if (fp == NULL) {
+        return -1;
+    }
+
+    /* read header */
+
+    read = getline(&line, &len, fp);
+    dprintf(fd, "%s", line);
+
+    /* read routes */
+
+    while ((read = getline(&line, &len, fp)) != -1) {
+        char iface[16];
+        uint32_t dest, gw, mask;
+        unsigned int flags, refcnt, use, metric, mtu, window, irtt;
+        int fields;
+
+        fields = sscanf(line,
+                        "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
+                        iface, &dest, &gw, &flags, &refcnt, &use, &metric,
+                        &mask, &mtu, &window, &irtt);
+        if (fields != 11) {
+            continue;
+        }
+        dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
+                iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
+                metric, tswap32(mask), mtu, window, irtt);
+    }
+
+    free(line);
+    fclose(fp);
+
+    return 0;
+}
+#endif
+
+static int do_openat(void *cpu_env, int dirfd, const char *pathname,
+                     int flags, mode_t mode)
+{
+    struct fake_open {
+        const char *filename;
+        int (*fill)(void *cpu_env, int fd);
+        int (*cmp)(const char *s1, const char *s2);
+    };
+    const struct fake_open *fake_open;
+    static const struct fake_open fakes[] = {
+        { "maps", open_self_maps, is_proc_myself },
+        { "stat", open_self_stat, is_proc_myself },
+        { "auxv", open_self_auxv, is_proc_myself },
+        { "cmdline", open_self_cmdline, is_proc_myself },
+#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
+        { "/proc/net/route", open_net_route, is_proc },
+#endif
+        { NULL, NULL, NULL }
+    };
+
+    if (is_proc_myself(pathname, "exe")) {
+        int execfd = qemu_getauxval(AT_EXECFD);
+        return execfd ? execfd : safe_openat(dirfd, exec_path, flags, mode);
+    }
+
+    for (fake_open = fakes; fake_open->filename; fake_open++) {
+        if (fake_open->cmp(pathname, fake_open->filename)) {
+            break;
+        }
+    }
+
+    if (fake_open->filename) {
+        const char *tmpdir;
+        char filename[PATH_MAX];
+        int fd, r;
+
+        /* create temporary file to map stat to */
+        tmpdir = getenv("TMPDIR");
+        if (!tmpdir) {
+            tmpdir = "/tmp";
+        }
+        snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
+        fd = mkstemp(filename);
+        if (fd < 0) {
+            return fd;
+        }
+        unlink(filename);
+
+        r = fake_open->fill(cpu_env, fd);
+        if (r) {
+            int e = errno;
+            close(fd);
+            errno = e;
+            return r;
+        }
+        lseek(fd, 0, SEEK_SET);
+
+        return fd;
+    }
+
+    return safe_openat(dirfd, path(pathname), flags, mode);
+}
+
+#ifdef TARGET_NR_open
+SYSCALL_IMPL(open)
+{
+    char *p = lock_user_string(arg1);
+    abi_long ret;
+
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
+                              target_to_host_bitmask(arg2, fcntl_flags_tbl),
+                              arg3));
+    fd_trans_unregister(ret);
+    unlock_user(p, arg1, 0);
+    return ret;
+}
+#endif
+
+SYSCALL_IMPL(openat)
+{
+    char *p = lock_user_string(arg2);
+    abi_long ret;
+
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(do_openat(cpu_env, arg1, p,
+                              target_to_host_bitmask(arg3, fcntl_flags_tbl),
+                              arg4));
+    fd_trans_unregister(ret);
+    unlock_user(p, arg2, 0);
+    return ret;
+}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index e27cab34af..fe52ac15c2 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6633,272 +6633,7 @@ int host_to_target_waitstatus(int status)
     return status;
 }
 
-static int open_self_cmdline(void *cpu_env, int fd)
-{
-    CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
-    struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm;
-    int i;
-
-    for (i = 0; i < bprm->argc; i++) {
-        size_t len = strlen(bprm->argv[i]) + 1;
-
-        if (write(fd, bprm->argv[i], len) != len) {
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-static int open_self_maps(void *cpu_env, int fd)
-{
-    CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
-    TaskState *ts = cpu->opaque;
-    FILE *fp;
-    char *line = NULL;
-    size_t len = 0;
-    ssize_t read;
-
-    fp = fopen("/proc/self/maps", "r");
-    if (fp == NULL) {
-        return -1;
-    }
-
-    while ((read = getline(&line, &len, fp)) != -1) {
-        int fields, dev_maj, dev_min, inode;
-        uint64_t min, max, offset;
-        char flag_r, flag_w, flag_x, flag_p;
-        char path[512] = "";
-        fields = sscanf(line, "%"PRIx64"-%"PRIx64" %c%c%c%c %"PRIx64" %x:%x %d"
-                        " %512s", &min, &max, &flag_r, &flag_w, &flag_x,
-                        &flag_p, &offset, &dev_maj, &dev_min, &inode, path);
-
-        if ((fields < 10) || (fields > 11)) {
-            continue;
-        }
-        if (h2g_valid(min)) {
-            int flags = page_get_flags(h2g(min));
-            max = h2g_valid(max - 1) ? max : (uintptr_t)g2h(GUEST_ADDR_MAX) + 1;
-            if (page_check_range(h2g(min), max - min, flags) == -1) {
-                continue;
-            }
-            if (h2g(min) == ts->info->stack_limit) {
-                pstrcpy(path, sizeof(path), "      [stack]");
-            }
-            dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr
-                    " %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n",
-                    h2g(min), h2g(max - 1) + 1, flag_r, flag_w,
-                    flag_x, flag_p, offset, dev_maj, dev_min, inode,
-                    path[0] ? "         " : "", path);
-        }
-    }
-
-    free(line);
-    fclose(fp);
-
-    return 0;
-}
-
-static int open_self_stat(void *cpu_env, int fd)
-{
-    CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
-    TaskState *ts = cpu->opaque;
-    abi_ulong start_stack = ts->info->start_stack;
-    int i;
-
-    for (i = 0; i < 44; i++) {
-      char buf[128];
-      int len;
-      uint64_t val = 0;
-
-      if (i == 0) {
-        /* pid */
-        val = getpid();
-        snprintf(buf, sizeof(buf), "%"PRId64 " ", val);
-      } else if (i == 1) {
-        /* app name */
-        snprintf(buf, sizeof(buf), "(%s) ", ts->bprm->argv[0]);
-      } else if (i == 27) {
-        /* stack bottom */
-        val = start_stack;
-        snprintf(buf, sizeof(buf), "%"PRId64 " ", val);
-      } else {
-        /* for the rest, there is MasterCard */
-        snprintf(buf, sizeof(buf), "0%c", i == 43 ? '\n' : ' ');
-      }
-
-      len = strlen(buf);
-      if (write(fd, buf, len) != len) {
-          return -1;
-      }
-    }
-
-    return 0;
-}
-
-static int open_self_auxv(void *cpu_env, int fd)
-{
-    CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
-    TaskState *ts = cpu->opaque;
-    abi_ulong auxv = ts->info->saved_auxv;
-    abi_ulong len = ts->info->auxv_len;
-    char *ptr;
-
-    /*
-     * Auxiliary vector is stored in target process stack.
-     * read in whole auxv vector and copy it to file
-     */
-    ptr = lock_user(VERIFY_READ, auxv, len, 0);
-    if (ptr != NULL) {
-        while (len > 0) {
-            ssize_t r;
-            r = write(fd, ptr, len);
-            if (r <= 0) {
-                break;
-            }
-            len -= r;
-            ptr += r;
-        }
-        lseek(fd, 0, SEEK_SET);
-        unlock_user(ptr, auxv, len);
-    }
-
-    return 0;
-}
-
-static int is_proc_myself(const char *filename, const char *entry)
-{
-    if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
-        filename += strlen("/proc/");
-        if (!strncmp(filename, "self/", strlen("self/"))) {
-            filename += strlen("self/");
-        } else if (*filename >= '1' && *filename <= '9') {
-            char myself[80];
-            snprintf(myself, sizeof(myself), "%d/", getpid());
-            if (!strncmp(filename, myself, strlen(myself))) {
-                filename += strlen(myself);
-            } else {
-                return 0;
-            }
-        } else {
-            return 0;
-        }
-        if (!strcmp(filename, entry)) {
-            return 1;
-        }
-    }
-    return 0;
-}
-
-#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
-static int is_proc(const char *filename, const char *entry)
-{
-    return strcmp(filename, entry) == 0;
-}
-
-static int open_net_route(void *cpu_env, int fd)
-{
-    FILE *fp;
-    char *line = NULL;
-    size_t len = 0;
-    ssize_t read;
-
-    fp = fopen("/proc/net/route", "r");
-    if (fp == NULL) {
-        return -1;
-    }
-
-    /* read header */
-
-    read = getline(&line, &len, fp);
-    dprintf(fd, "%s", line);
-
-    /* read routes */
-
-    while ((read = getline(&line, &len, fp)) != -1) {
-        char iface[16];
-        uint32_t dest, gw, mask;
-        unsigned int flags, refcnt, use, metric, mtu, window, irtt;
-        int fields;
-
-        fields = sscanf(line,
-                        "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
-                        iface, &dest, &gw, &flags, &refcnt, &use, &metric,
-                        &mask, &mtu, &window, &irtt);
-        if (fields != 11) {
-            continue;
-        }
-        dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
-                iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
-                metric, tswap32(mask), mtu, window, irtt);
-    }
-
-    free(line);
-    fclose(fp);
-
-    return 0;
-}
-#endif
-
-static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode)
-{
-    struct fake_open {
-        const char *filename;
-        int (*fill)(void *cpu_env, int fd);
-        int (*cmp)(const char *s1, const char *s2);
-    };
-    const struct fake_open *fake_open;
-    static const struct fake_open fakes[] = {
-        { "maps", open_self_maps, is_proc_myself },
-        { "stat", open_self_stat, is_proc_myself },
-        { "auxv", open_self_auxv, is_proc_myself },
-        { "cmdline", open_self_cmdline, is_proc_myself },
-#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
-        { "/proc/net/route", open_net_route, is_proc },
-#endif
-        { NULL, NULL, NULL }
-    };
-
-    if (is_proc_myself(pathname, "exe")) {
-        int execfd = qemu_getauxval(AT_EXECFD);
-        return execfd ? execfd : safe_openat(dirfd, exec_path, flags, mode);
-    }
-
-    for (fake_open = fakes; fake_open->filename; fake_open++) {
-        if (fake_open->cmp(pathname, fake_open->filename)) {
-            break;
-        }
-    }
-
-    if (fake_open->filename) {
-        const char *tmpdir;
-        char filename[PATH_MAX];
-        int fd, r;
-
-        /* create temporary file to map stat to */
-        tmpdir = getenv("TMPDIR");
-        if (!tmpdir)
-            tmpdir = "/tmp";
-        snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
-        fd = mkstemp(filename);
-        if (fd < 0) {
-            return fd;
-        }
-        unlink(filename);
-
-        if ((r = fake_open->fill(cpu_env, fd))) {
-            int e = errno;
-            close(fd);
-            errno = e;
-            return r;
-        }
-        lseek(fd, 0, SEEK_SET);
-
-        return fd;
-    }
-
-    return safe_openat(dirfd, path(pathname), flags, mode);
-}
+static int is_proc_myself(const char *filename, const char *entry);
 
 #define TIMER_MAGIC 0x0caf0000
 #define TIMER_MAGIC_MASK 0xffff0000
@@ -7083,26 +6818,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         unlock_user(p, arg2, 0);
         return ret;
 
-#ifdef TARGET_NR_open
-    case TARGET_NR_open:
-        if (!(p = lock_user_string(arg1)))
-            return -TARGET_EFAULT;
-        ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
-                                  target_to_host_bitmask(arg2, fcntl_flags_tbl),
-                                  arg3));
-        fd_trans_unregister(ret);
-        unlock_user(p, arg1, 0);
-        return ret;
-#endif
-    case TARGET_NR_openat:
-        if (!(p = lock_user_string(arg2)))
-            return -TARGET_EFAULT;
-        ret = get_errno(do_openat(cpu_env, arg1, p,
-                                  target_to_host_bitmask(arg3, fcntl_flags_tbl),
-                                  arg4));
-        fd_trans_unregister(ret);
-        unlock_user(p, arg2, 0);
-        return ret;
 #if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
     case TARGET_NR_name_to_handle_at:
         ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
@@ -11643,6 +11358,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
                                 int64_t arg2, int64_t arg3, int64_t arg4, \
                                 int64_t arg5, int64_t arg6)
 
+#include "syscall-file.inc.c"
 
 #undef SYSCALL_IMPL
 #undef SYSCALL_ARGS
diff --git a/linux-user/strace.list b/linux-user/strace.list
index db21ce4177..2c7a595e19 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -677,12 +677,6 @@
 #ifdef TARGET_NR_olduname
 { TARGET_NR_olduname, "olduname" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_open
-{ TARGET_NR_open, "open" , NULL, print_open, NULL },
-#endif
-#ifdef TARGET_NR_openat
-{ TARGET_NR_openat, "openat" , NULL, print_openat, NULL },
-#endif
 #ifdef TARGET_NR_osf_adjtime
 { TARGET_NR_osf_adjtime, "osf_adjtime" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 03/74] linux-user: Share more code for open and openat
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 01/74] linux-user: Setup split syscall infrastructure Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 02/74] linux-user: Split out open, open_at Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 04/74] linux-user: Tidy do_openat loop over fakes Richard Henderson
                   ` (73 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

The do_openat helper can have all of the code that is not directly
related to the argument ordering of these two syscalls.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-file.inc.c | 69 ++++++++++++++++-------------------
 1 file changed, 31 insertions(+), 38 deletions(-)

diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 7974148ccb..961eed13ae 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -227,8 +227,8 @@ static int open_net_route(void *cpu_env, int fd)
 }
 #endif
 
-static int do_openat(void *cpu_env, int dirfd, const char *pathname,
-                     int flags, mode_t mode)
+static abi_long do_openat(void *cpu_env, int dirfd, abi_ulong target_path,
+                          int target_flags, mode_t mode)
 {
     struct fake_open {
         const char *filename;
@@ -247,9 +247,20 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname,
         { NULL, NULL, NULL }
     };
 
+    char *pathname = lock_user_string(target_path);
+    int flags = target_to_host_bitmask(target_flags, fcntl_flags_tbl);
+    abi_long ret;
+
+    if (!pathname) {
+        return -TARGET_EFAULT;
+    }
+
     if (is_proc_myself(pathname, "exe")) {
-        int execfd = qemu_getauxval(AT_EXECFD);
-        return execfd ? execfd : safe_openat(dirfd, exec_path, flags, mode);
+        ret = qemu_getauxval(AT_EXECFD);
+        if (ret == 0) {
+            ret = get_errno(safe_openat(dirfd, exec_path, flags, mode));
+        }
+        goto done;
     }
 
     for (fake_open = fakes; fake_open->filename; fake_open++) {
@@ -261,7 +272,7 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname,
     if (fake_open->filename) {
         const char *tmpdir;
         char filename[PATH_MAX];
-        int fd, r;
+        int fd;
 
         /* create temporary file to map stat to */
         tmpdir = getenv("TMPDIR");
@@ -271,55 +282,37 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname,
         snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
         fd = mkstemp(filename);
         if (fd < 0) {
-            return fd;
+            ret = -TARGET_ENOENT;
+            goto done;
         }
         unlink(filename);
 
-        r = fake_open->fill(cpu_env, fd);
-        if (r) {
-            int e = errno;
+        ret = fake_open->fill(cpu_env, fd);
+        if (ret) {
+            ret = get_errno(ret);
             close(fd);
-            errno = e;
-            return r;
+            goto done;
         }
         lseek(fd, 0, SEEK_SET);
-
-        return fd;
+        ret = fd;
+        goto done;
     }
 
-    return safe_openat(dirfd, path(pathname), flags, mode);
+    ret = get_errno(safe_openat(dirfd, path(pathname), flags, mode));
+ done:
+    fd_trans_unregister(ret);
+    unlock_user(pathname, target_path, 0);
+    return ret;
 }
 
 #ifdef TARGET_NR_open
 SYSCALL_IMPL(open)
 {
-    char *p = lock_user_string(arg1);
-    abi_long ret;
-
-    if (!p) {
-        return -TARGET_EFAULT;
-    }
-    ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
-                              target_to_host_bitmask(arg2, fcntl_flags_tbl),
-                              arg3));
-    fd_trans_unregister(ret);
-    unlock_user(p, arg1, 0);
-    return ret;
+    return do_openat(cpu_env, AT_FDCWD, arg1, arg2, arg3);
 }
 #endif
 
 SYSCALL_IMPL(openat)
 {
-    char *p = lock_user_string(arg2);
-    abi_long ret;
-
-    if (!p) {
-        return -TARGET_EFAULT;
-    }
-    ret = get_errno(do_openat(cpu_env, arg1, p,
-                              target_to_host_bitmask(arg3, fcntl_flags_tbl),
-                              arg4));
-    fd_trans_unregister(ret);
-    unlock_user(p, arg2, 0);
-    return ret;
+    return do_openat(cpu_env, arg1, arg2, arg3, arg4);
 }
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 04/74] linux-user: Tidy do_openat loop over fakes
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (2 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 03/74] linux-user: Share more code for open and openat Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 05/74] linux-user: Split out readlink, readlinkat Richard Henderson
                   ` (72 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Cleaner to use ARRAY_SIZE to loop over elements instead of
using a sentinel within the data structure.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-file.inc.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 961eed13ae..30f8e35cdd 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -235,7 +235,6 @@ static abi_long do_openat(void *cpu_env, int dirfd, abi_ulong target_path,
         int (*fill)(void *cpu_env, int fd);
         int (*cmp)(const char *s1, const char *s2);
     };
-    const struct fake_open *fake_open;
     static const struct fake_open fakes[] = {
         { "maps", open_self_maps, is_proc_myself },
         { "stat", open_self_stat, is_proc_myself },
@@ -244,12 +243,12 @@ static abi_long do_openat(void *cpu_env, int dirfd, abi_ulong target_path,
 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
         { "/proc/net/route", open_net_route, is_proc },
 #endif
-        { NULL, NULL, NULL }
     };
 
     char *pathname = lock_user_string(target_path);
     int flags = target_to_host_bitmask(target_flags, fcntl_flags_tbl);
     abi_long ret;
+    size_t i;
 
     if (!pathname) {
         return -TARGET_EFAULT;
@@ -263,17 +262,16 @@ static abi_long do_openat(void *cpu_env, int dirfd, abi_ulong target_path,
         goto done;
     }
 
-    for (fake_open = fakes; fake_open->filename; fake_open++) {
-        if (fake_open->cmp(pathname, fake_open->filename)) {
-            break;
-        }
-    }
-
-    if (fake_open->filename) {
+    for (i = 0; i < ARRAY_SIZE(fakes); ++i) {
+        const struct fake_open *fake_open = &fakes[i];
         const char *tmpdir;
         char filename[PATH_MAX];
         int fd;
 
+        if (!fake_open->cmp(pathname, fake_open->filename)) {
+            continue;
+        }
+
         /* create temporary file to map stat to */
         tmpdir = getenv("TMPDIR");
         if (!tmpdir) {
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 05/74] linux-user: Split out readlink, readlinkat
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (3 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 04/74] linux-user: Tidy do_openat loop over fakes Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 06/74] linux-user: Split out close Richard Henderson
                   ` (71 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Split out a shared implementation for both of these;
unify the best parts of /proc/self/exe checking.

Remove the temporary forward declaration for is_proc_self.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  6 ++++
 linux-user/strace.c           | 29 ------------------
 linux-user/syscall-file.inc.c | 45 ++++++++++++++++++++++++++++
 linux-user/syscall.c          | 55 -----------------------------------
 linux-user/strace.list        |  6 ----
 5 files changed, 51 insertions(+), 90 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 1f3a9c47ab..d1a6c6fa3c 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -20,3 +20,9 @@
 SYSCALL_DEF(open, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG);
 #endif
 SYSCALL_DEF(openat, ARG_ATDIRFD, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG);
+#ifdef TARGET_NR_readlink
+SYSCALL_DEF(readlink, ARG_STR, ARG_PTR, ARG_DEC);
+#endif
+#ifdef TARGET_NR_readlinkat
+SYSCALL_DEF(readlinkat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_DEC);
+#endif
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 24ef14b5e6..2f1c7e537f 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -2256,35 +2256,6 @@ print_fstatat64(const struct syscallname *name,
 #define print_newfstatat    print_fstatat64
 #endif
 
-#ifdef TARGET_NR_readlink
-static void
-print_readlink(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 0);
-    print_pointer(arg1, 0);
-    print_raw_param("%u", arg2, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
-#ifdef TARGET_NR_readlinkat
-static void
-print_readlinkat(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_at_dirfd(arg0, 0);
-    print_string(arg1, 0);
-    print_pointer(arg2, 0);
-    print_raw_param("%u", arg3, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_rename
 static void
 print_rename(const struct syscallname *name,
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 30f8e35cdd..4ef0be2c6f 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -314,3 +314,48 @@ SYSCALL_IMPL(openat)
 {
     return do_openat(cpu_env, arg1, arg2, arg3, arg4);
 }
+
+static abi_long do_readlinkat(int dirfd, abi_ulong target_path,
+                              abi_ulong target_buf, abi_ulong bufsiz)
+{
+    char *p = lock_user_string(target_path);
+    void *buf = lock_user(VERIFY_WRITE, target_buf, bufsiz, 0);
+    abi_long ret;
+
+    if (!p || !buf) {
+        ret = -TARGET_EFAULT;
+    } else if (!bufsiz) {
+        /* Short circuit this for the magic exe check. */
+        ret = -TARGET_EINVAL;
+    } else if (is_proc_myself((const char *)p, "exe")) {
+        char real[PATH_MAX];
+        char *temp = realpath(exec_path, real);
+
+        if (temp == NULL) {
+            ret = -host_to_target_errno(errno);
+        } else {
+            ret = MIN(strlen(real), bufsiz);
+            /* We cannot NUL terminate the string. */
+            memcpy(buf, real, ret);
+        }
+    } else {
+        ret = get_errno(readlinkat(dirfd, path(p), buf, bufsiz));
+    }
+    unlock_user(buf, target_buf, ret);
+    unlock_user(p, target_path, 0);
+    return ret;
+}
+
+#ifdef TARGET_NR_readlink
+SYSCALL_IMPL(readlink)
+{
+    return do_readlinkat(AT_FDCWD, arg1, arg2, arg3);
+}
+#endif
+
+#ifdef TARGET_NR_readlinkat
+SYSCALL_IMPL(readlinkat)
+{
+    return do_readlinkat(arg1, arg2, arg3, arg4);
+}
+#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index fe52ac15c2..53fb211f16 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6633,8 +6633,6 @@ int host_to_target_waitstatus(int status)
     return status;
 }
 
-static int is_proc_myself(const char *filename, const char *entry);
-
 #define TIMER_MAGIC 0x0caf0000
 #define TIMER_MAGIC_MASK 0xffff0000
 
@@ -8108,59 +8106,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         }
         return ret;
 #endif
-#ifdef TARGET_NR_readlink
-    case TARGET_NR_readlink:
-        {
-            void *p2;
-            p = lock_user_string(arg1);
-            p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
-            if (!p || !p2) {
-                ret = -TARGET_EFAULT;
-            } else if (!arg3) {
-                /* Short circuit this for the magic exe check. */
-                ret = -TARGET_EINVAL;
-            } else if (is_proc_myself((const char *)p, "exe")) {
-                char real[PATH_MAX], *temp;
-                temp = realpath(exec_path, real);
-                /* Return value is # of bytes that we wrote to the buffer. */
-                if (temp == NULL) {
-                    ret = get_errno(-1);
-                } else {
-                    /* Don't worry about sign mismatch as earlier mapping
-                     * logic would have thrown a bad address error. */
-                    ret = MIN(strlen(real), arg3);
-                    /* We cannot NUL terminate the string. */
-                    memcpy(p2, real, ret);
-                }
-            } else {
-                ret = get_errno(readlink(path(p), p2, arg3));
-            }
-            unlock_user(p2, arg2, ret);
-            unlock_user(p, arg1, 0);
-        }
-        return ret;
-#endif
-#if defined(TARGET_NR_readlinkat)
-    case TARGET_NR_readlinkat:
-        {
-            void *p2;
-            p  = lock_user_string(arg2);
-            p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
-            if (!p || !p2) {
-                ret = -TARGET_EFAULT;
-            } else if (is_proc_myself((const char *)p, "exe")) {
-                char real[PATH_MAX], *temp;
-                temp = realpath(exec_path, real);
-                ret = temp == NULL ? get_errno(-1) : strlen(real) ;
-                snprintf((char *)p2, arg4, "%s", real);
-            } else {
-                ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
-            }
-            unlock_user(p2, arg3, ret);
-            unlock_user(p, arg2, 0);
-        }
-        return ret;
-#endif
 #ifdef TARGET_NR_swapon
     case TARGET_NR_swapon:
         if (!(p = lock_user_string(arg1)))
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 2c7a595e19..53cee3db92 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1079,12 +1079,6 @@
 #ifdef TARGET_NR_readdir
 { TARGET_NR_readdir, "readdir" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_readlink
-{ TARGET_NR_readlink, "readlink" , NULL, print_readlink, NULL },
-#endif
-#ifdef TARGET_NR_readlinkat
-{ TARGET_NR_readlinkat, "readlinkat" , NULL, print_readlinkat, NULL },
-#endif
 #ifdef TARGET_NR_readv
 { TARGET_NR_readv, "readv" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 06/74] linux-user: Split out close
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (4 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 05/74] linux-user: Split out readlink, readlinkat Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 07/74] linux-user: Split out read, write Richard Henderson
                   ` (70 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     | 1 +
 linux-user/syscall-file.inc.c | 8 ++++++++
 linux-user/syscall.c          | 4 ----
 linux-user/strace.list        | 3 ---
 4 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index d1a6c6fa3c..797426ae6f 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -16,6 +16,7 @@
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+SYSCALL_DEF(close, ARG_DEC);
 #ifdef TARGET_NR_open
 SYSCALL_DEF(open, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG);
 #endif
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 4ef0be2c6f..d9b09c2cd2 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -16,6 +16,14 @@
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+SYSCALL_IMPL(close)
+{
+    int fd = arg1;
+
+    fd_trans_unregister(fd);
+    return get_errno(close(fd));
+}
+
 /*
  * Helpers for do_openat, manipulating /proc/self/foo.
  */
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 53fb211f16..d2b1bb76c4 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6827,10 +6827,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         fd_trans_unregister(ret);
         return ret;
 #endif
-    case TARGET_NR_close:
-        fd_trans_unregister(arg1);
-        return get_errno(close(arg1));
-
     case TARGET_NR_brk:
         return do_brk(arg1);
 #ifdef TARGET_NR_fork
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 53cee3db92..43d3088669 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -97,9 +97,6 @@
 #ifdef TARGET_NR_clone
 { TARGET_NR_clone, "clone" , NULL, print_clone, NULL },
 #endif
-#ifdef TARGET_NR_close
-{ TARGET_NR_close, "close" , "%s(%d)", NULL, NULL },
-#endif
 #ifdef TARGET_NR_connect
 { TARGET_NR_connect, "connect" , "%s(%d,%#x,%d)", NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 07/74] linux-user: Split out read, write
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (5 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 06/74] linux-user: Split out close Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 08/74] linux-user: Reduce regpairs_aligned & target_offset64 ifdefs Richard Henderson
                   ` (69 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  2 ++
 linux-user/syscall-file.inc.c | 58 +++++++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 34 --------------------
 linux-user/strace.list        |  6 ----
 4 files changed, 60 insertions(+), 40 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 797426ae6f..b031de1375 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -21,9 +21,11 @@ SYSCALL_DEF(close, ARG_DEC);
 SYSCALL_DEF(open, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG);
 #endif
 SYSCALL_DEF(openat, ARG_ATDIRFD, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG);
+SYSCALL_DEF(read, ARG_DEC, ARG_PTR, ARG_DEC);
 #ifdef TARGET_NR_readlink
 SYSCALL_DEF(readlink, ARG_STR, ARG_PTR, ARG_DEC);
 #endif
 #ifdef TARGET_NR_readlinkat
 SYSCALL_DEF(readlinkat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_DEC);
 #endif
+SYSCALL_DEF(write, ARG_DEC, ARG_PTR, ARG_DEC);
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index d9b09c2cd2..e6adcc351c 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -323,6 +323,32 @@ SYSCALL_IMPL(openat)
     return do_openat(cpu_env, arg1, arg2, arg3, arg4);
 }
 
+SYSCALL_IMPL(read)
+{
+    int fd = arg1;
+    abi_ulong target_p = arg2;
+    abi_ulong size = arg3;
+    void *p;
+    abi_long ret;
+
+    if (target_p == 0 && size == 0) {
+        return get_errno(safe_read(fd, NULL, 0));
+    }
+    p = lock_user(VERIFY_WRITE, target_p, size, 0);
+    if (p == NULL) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(safe_read(fd, p, size));
+    if (!is_error(ret)) {
+        TargetFdDataFunc trans = fd_trans_host_to_target_data(fd);
+        if (trans) {
+            ret = trans(p, ret);
+        }
+    }
+    unlock_user(p, target_p, ret);
+    return ret;
+}
+
 static abi_long do_readlinkat(int dirfd, abi_ulong target_path,
                               abi_ulong target_buf, abi_ulong bufsiz)
 {
@@ -367,3 +393,35 @@ SYSCALL_IMPL(readlinkat)
     return do_readlinkat(arg1, arg2, arg3, arg4);
 }
 #endif
+
+SYSCALL_IMPL(write)
+{
+    int fd = arg1;
+    abi_ulong target_p = arg2;
+    abi_ulong size = arg3;
+    TargetFdDataFunc trans;
+    abi_long ret;
+    void *p;
+
+    if (target_p == 0 && size == 0) {
+        return get_errno(safe_write(fd, NULL, 0));
+    }
+    p = lock_user(VERIFY_READ, target_p, size, 1);
+    if (p == NULL) {
+        return -TARGET_EFAULT;
+    }
+    trans = fd_trans_target_to_host_data(fd);
+    if (trans) {
+        void *copy = g_malloc(size);
+        memcpy(copy, p, size);
+        ret = trans(copy, size);
+        if (ret >= 0) {
+            ret = get_errno(safe_write(fd, copy, ret));
+        }
+        g_free(copy);
+    } else {
+        ret = get_errno(safe_write(fd, p, size));
+    }
+    unlock_user(p, target_p, 0);
+    return ret;
+}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index d2b1bb76c4..de80ddb330 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6782,40 +6782,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         preexit_cleanup(cpu_env, arg1);
         _exit(arg1);
         return 0; /* avoid warning */
-    case TARGET_NR_read:
-        if (arg2 == 0 && arg3 == 0) {
-            return get_errno(safe_read(arg1, 0, 0));
-        } else {
-            if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
-                return -TARGET_EFAULT;
-            ret = get_errno(safe_read(arg1, p, arg3));
-            if (ret >= 0 &&
-                fd_trans_host_to_target_data(arg1)) {
-                ret = fd_trans_host_to_target_data(arg1)(p, ret);
-            }
-            unlock_user(p, arg2, ret);
-        }
-        return ret;
-    case TARGET_NR_write:
-        if (arg2 == 0 && arg3 == 0) {
-            return get_errno(safe_write(arg1, 0, 0));
-        }
-        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
-            return -TARGET_EFAULT;
-        if (fd_trans_target_to_host_data(arg1)) {
-            void *copy = g_malloc(arg3);
-            memcpy(copy, p, arg3);
-            ret = fd_trans_target_to_host_data(arg1)(copy, arg3);
-            if (ret >= 0) {
-                ret = get_errno(safe_write(arg1, copy, ret));
-            }
-            g_free(copy);
-        } else {
-            ret = get_errno(safe_write(arg1, p, arg3));
-        }
-        unlock_user(p, arg2, 0);
-        return ret;
-
 #if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
     case TARGET_NR_name_to_handle_at:
         ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 43d3088669..2d6bfec692 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1067,9 +1067,6 @@
 #ifdef TARGET_NR_quotactl
 { TARGET_NR_quotactl, "quotactl" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_read
-{ TARGET_NR_read, "read" , "%s(%d,%#x,%d)", NULL, NULL },
-#endif
 #ifdef TARGET_NR_readahead
 { TARGET_NR_readahead, "readahead" , NULL, NULL, NULL },
 #endif
@@ -1611,9 +1608,6 @@
 #ifdef TARGET_NR_waitpid
 { TARGET_NR_waitpid, "waitpid" , "%s(%d,%p,%#x)", NULL, NULL },
 #endif
-#ifdef TARGET_NR_write
-{ TARGET_NR_write, "write" , "%s(%d,%#x,%d)", NULL, NULL },
-#endif
 #ifdef TARGET_NR_writev
 { TARGET_NR_writev, "writev" , "%s(%d,%p,%#x)", NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 08/74] linux-user: Reduce regpairs_aligned & target_offset64 ifdefs
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (6 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 07/74] linux-user: Split out read, write Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 09/74] linux-user: Split out readv, writev Richard Henderson
                   ` (68 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall.c | 54 ++++++++++++++++++++------------------------
 1 file changed, 25 insertions(+), 29 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index de80ddb330..61cd73db26 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -464,37 +464,38 @@ static inline int next_free_host_timer(void)
 }
 #endif
 
-/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
+/*
+ * Returns true if syscall NUM expects 64bit types aligned even
+ * on pairs of registers.
+ */
+static inline bool regpairs_aligned(void *cpu_env, int num)
+{
 #ifdef TARGET_ARM
-static inline int regpairs_aligned(void *cpu_env, int num)
-{
-    return ((((CPUARMState *)cpu_env)->eabi) == 1) ;
-}
-#elif defined(TARGET_MIPS) && (TARGET_ABI_BITS == 32)
-static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
+    return ((CPUARMState *)cpu_env)->eabi;
+#elif defined(TARGET_MIPS) && TARGET_ABI_BITS == 32
+    return true;
 #elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
-/* SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs
- * of registers which translates to the same as ARM/MIPS, because we start with
- * r3 as arg1 */
-static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
+    /*
+     * SysV AVI for PPC32 expects 64bit parameters to be passed on
+     * odd/even pairs of registers which translates to the same as
+     * we start with r3 as arg1.
+     */
+    return true;
 #elif defined(TARGET_SH4)
-/* SH4 doesn't align register pairs, except for p{read,write}64 */
-static inline int regpairs_aligned(void *cpu_env, int num)
-{
+    /* SH4 doesn't align register pairs, except for p{read,write}64.  */
     switch (num) {
     case TARGET_NR_pread64:
     case TARGET_NR_pwrite64:
-        return 1;
-
+        return true;
     default:
-        return 0;
+        return false;
     }
-}
 #elif defined(TARGET_XTENSA)
-static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
+    return true;
 #else
-static inline int regpairs_aligned(void *cpu_env, int num) { return 0; }
+    return false;
 #endif
+}
 
 #define ERRNO_TABLE_SIZE 1200
 
@@ -6161,21 +6162,16 @@ void syscall_init(void)
     }
 }
 
-#if TARGET_ABI_BITS == 32
-static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
+static inline uint64_t target_offset64(abi_ulong word0, abi_ulong word1)
 {
-#ifdef TARGET_WORDS_BIGENDIAN
+#if TARGET_ABI_BITS == 64
+    return word0;
+#elif defined(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 */
 
 #ifdef TARGET_NR_truncate64
 static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 09/74] linux-user: Split out readv, writev
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (7 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 08/74] linux-user: Reduce regpairs_aligned & target_offset64 ifdefs Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 10/74] linux-user: Split out pread64, pwrite64 Richard Henderson
                   ` (67 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  2 ++
 linux-user/syscall-file.inc.c | 34 ++++++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 22 ----------------------
 linux-user/strace.list        |  6 ------
 4 files changed, 36 insertions(+), 28 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index b031de1375..130ba7e344 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -28,4 +28,6 @@ SYSCALL_DEF(readlink, ARG_STR, ARG_PTR, ARG_DEC);
 #ifdef TARGET_NR_readlinkat
 SYSCALL_DEF(readlinkat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_DEC);
 #endif
+SYSCALL_DEF(readv, ARG_DEC, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(write, ARG_DEC, ARG_PTR, ARG_DEC);
+SYSCALL_DEF(writev, ARG_DEC, ARG_PTR, ARG_DEC);
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index e6adcc351c..2297ca1760 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -349,6 +349,23 @@ SYSCALL_IMPL(read)
     return ret;
 }
 
+SYSCALL_IMPL(readv)
+{
+    int fd = arg1;
+    abi_ulong target_vec = arg2;
+    int count = arg3;
+    struct iovec *vec = lock_iovec(VERIFY_WRITE, target_vec, count, 0);
+    abi_long ret;
+
+    if (vec != NULL) {
+        ret = get_errno(safe_readv(fd, vec, count));
+        unlock_iovec(vec, target_vec, count, 1);
+    } else {
+        ret = -host_to_target_errno(errno);
+    }
+    return ret;
+}
+
 static abi_long do_readlinkat(int dirfd, abi_ulong target_path,
                               abi_ulong target_buf, abi_ulong bufsiz)
 {
@@ -425,3 +442,20 @@ SYSCALL_IMPL(write)
     unlock_user(p, target_p, 0);
     return ret;
 }
+
+SYSCALL_IMPL(writev)
+{
+    int fd = arg1;
+    abi_ulong target_vec = arg2;
+    int count = arg3;
+    struct iovec *vec = lock_iovec(VERIFY_READ, target_vec, count, 1);
+    abi_long ret;
+
+    if (vec != NULL) {
+        ret = get_errno(safe_writev(fd, vec, count));
+        unlock_iovec(vec, target_vec, count, 0);
+    } else {
+        ret = -host_to_target_errno(errno);
+    }
+    return ret;
+}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 61cd73db26..8086626707 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -9005,28 +9005,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         /* NOTE: the flock constant seems to be the same for every
            Linux platform */
         return get_errno(safe_flock(arg1, arg2));
-    case TARGET_NR_readv:
-        {
-            struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
-            if (vec != NULL) {
-                ret = get_errno(safe_readv(arg1, vec, arg3));
-                unlock_iovec(vec, arg2, arg3, 1);
-            } else {
-                ret = -host_to_target_errno(errno);
-            }
-        }
-        return ret;
-    case TARGET_NR_writev:
-        {
-            struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
-            if (vec != NULL) {
-                ret = get_errno(safe_writev(arg1, vec, arg3));
-                unlock_iovec(vec, arg2, arg3, 0);
-            } else {
-                ret = -host_to_target_errno(errno);
-            }
-        }
-        return ret;
 #if defined(TARGET_NR_preadv)
     case TARGET_NR_preadv:
         {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 2d6bfec692..c4ae70b485 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1073,9 +1073,6 @@
 #ifdef TARGET_NR_readdir
 { TARGET_NR_readdir, "readdir" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_readv
-{ TARGET_NR_readv, "readv" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_reboot
 { TARGET_NR_reboot, "reboot" , NULL, NULL, NULL },
 #endif
@@ -1608,9 +1605,6 @@
 #ifdef TARGET_NR_waitpid
 { TARGET_NR_waitpid, "waitpid" , "%s(%d,%p,%#x)", NULL, NULL },
 #endif
-#ifdef TARGET_NR_writev
-{ TARGET_NR_writev, "writev" , "%s(%d,%p,%#x)", NULL, NULL },
-#endif
 #ifdef TARGET_NR_utimensat
 { TARGET_NR_utimensat, "utimensat", NULL, print_utimensat, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 10/74] linux-user: Split out pread64, pwrite64
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (8 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 09/74] linux-user: Split out readv, writev Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 11/74] linux-user: Split out preadv, pwritev Richard Henderson
                   ` (66 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  6 ++++
 linux-user/syscall-file.inc.c | 62 +++++++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 36 --------------------
 linux-user/strace.list        |  6 ----
 4 files changed, 68 insertions(+), 42 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 130ba7e344..027793d5d0 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -21,6 +21,12 @@ SYSCALL_DEF(close, ARG_DEC);
 SYSCALL_DEF(open, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG);
 #endif
 SYSCALL_DEF(openat, ARG_ATDIRFD, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG);
+SYSCALL_DEF_FULL(pread64, .impl = impl_pread64,
+                 .args = args_pread64_pwrite64,
+                 .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 });
+SYSCALL_DEF_FULL(pwrite64, .impl = impl_pwrite64,
+                 .args = args_pread64_pwrite64,
+                 .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 });
 SYSCALL_DEF(read, ARG_DEC, ARG_PTR, ARG_DEC);
 #ifdef TARGET_NR_readlink
 SYSCALL_DEF(readlink, ARG_STR, ARG_PTR, ARG_DEC);
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 2297ca1760..43aa6eeeb8 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -323,6 +323,68 @@ SYSCALL_IMPL(openat)
     return do_openat(cpu_env, arg1, arg2, arg3, arg4);
 }
 
+/*
+ * Both pread64 and pwrite64 merge args into a 64-bit offset,
+ * but the input registers and ordering are target specific.
+ */
+#if TARGET_ABI_BITS == 32
+SYSCALL_ARGS(pread64_pwrite64)
+{
+    /* We have already assigned out[0-2].  */
+    int off = regpairs_aligned(cpu_env, TARGET_NR_pread64);
+    out[3] = target_offset64(in[3 + off], in[4 + off]);
+    return def;
+}
+#else
+#define args_pread64_pwrite64 NULL
+#endif
+
+SYSCALL_IMPL(pread64)
+{
+    int fd = arg1;
+    abi_ulong target_buf = arg2;
+    abi_ulong len = arg3;
+    uint64_t off = arg4;
+    void *p;
+    abi_long ret;
+
+    if (target_buf == 0 && len == 0) {
+        /* Special-case NULL buffer and zero length, which should succeed */
+        p = NULL;
+    } else {
+        p = lock_user(VERIFY_WRITE, target_buf, len, 0);
+        if (!p) {
+            return -TARGET_EFAULT;
+        }
+    }
+    ret = get_errno(pread64(fd, p, len, off));
+    unlock_user(p, target_buf, ret);
+    return ret;
+}
+
+SYSCALL_IMPL(pwrite64)
+{
+    int fd = arg1;
+    abi_ulong target_buf = arg2;
+    abi_ulong len = arg3;
+    uint64_t off = arg4;
+    void *p;
+    abi_long ret;
+
+    if (target_buf == 0 && len == 0) {
+        /* Special-case NULL buffer and zero length, which should succeed */
+        p = 0;
+    } else {
+        p = lock_user(VERIFY_READ, target_buf, len, 1);
+        if (!p) {
+            return -TARGET_EFAULT;
+        }
+    }
+    ret = get_errno(pwrite64(fd, p, len, off));
+    unlock_user(p, target_buf, 0);
+    return ret;
+}
+
 SYSCALL_IMPL(read)
 {
     int fd = arg1;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 8086626707..f636fb8bb3 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -9404,42 +9404,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
 #else
 #error unreachable
 #endif
-#endif
-#ifdef TARGET_NR_pread64
-    case TARGET_NR_pread64:
-        if (regpairs_aligned(cpu_env, num)) {
-            arg4 = arg5;
-            arg5 = arg6;
-        }
-        if (arg2 == 0 && arg3 == 0) {
-            /* Special-case NULL buffer and zero length, which should succeed */
-            p = 0;
-        } else {
-            p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
-            if (!p) {
-                return -TARGET_EFAULT;
-            }
-        }
-        ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
-        unlock_user(p, arg2, ret);
-        return ret;
-    case TARGET_NR_pwrite64:
-        if (regpairs_aligned(cpu_env, num)) {
-            arg4 = arg5;
-            arg5 = arg6;
-        }
-        if (arg2 == 0 && arg3 == 0) {
-            /* Special-case NULL buffer and zero length, which should succeed */
-            p = 0;
-        } else {
-            p = lock_user(VERIFY_READ, arg2, arg3, 1);
-            if (!p) {
-                return -TARGET_EFAULT;
-            }
-        }
-        ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
-        unlock_user(p, arg2, 0);
-        return ret;
 #endif
     case TARGET_NR_getcwd:
         if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
diff --git a/linux-user/strace.list b/linux-user/strace.list
index c4ae70b485..a11ad3c3c7 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1025,9 +1025,6 @@
 #ifdef TARGET_NR_prctl
 { TARGET_NR_prctl, "prctl" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_pread64
-{ TARGET_NR_pread64, "pread64" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_preadv
 { TARGET_NR_preadv, "preadv" , NULL, NULL, NULL },
 #endif
@@ -1055,9 +1052,6 @@
 #ifdef TARGET_NR_putpmsg
 { TARGET_NR_putpmsg, "putpmsg" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_pwrite64
-{ TARGET_NR_pwrite64, "pwrite64" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_pwritev
 { TARGET_NR_pwritev, "pwritev" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 11/74] linux-user: Split out preadv, pwritev
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (9 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 10/74] linux-user: Split out pread64, pwrite64 Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 12/74] linux-user: Split out name_to_handle_at, open_by_handle_at Richard Henderson
                   ` (65 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  6 ++++
 linux-user/syscall-file.inc.c | 64 +++++++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 49 ---------------------------
 linux-user/strace.list        |  6 ----
 4 files changed, 70 insertions(+), 55 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 027793d5d0..ae89be0e87 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -27,6 +27,12 @@ SYSCALL_DEF_FULL(pread64, .impl = impl_pread64,
 SYSCALL_DEF_FULL(pwrite64, .impl = impl_pwrite64,
                  .args = args_pread64_pwrite64,
                  .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 });
+SYSCALL_DEF_FULL(preadv, .impl = impl_preadv,
+                 .args = args_preadv_pwritev,
+                 .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 });
+SYSCALL_DEF_FULL(pwritev, .impl = impl_pwritev,
+                 .args = args_preadv_pwritev,
+                 .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 });
 SYSCALL_DEF(read, ARG_DEC, ARG_PTR, ARG_DEC);
 #ifdef TARGET_NR_readlink
 SYSCALL_DEF(readlink, ARG_STR, ARG_PTR, ARG_DEC);
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 43aa6eeeb8..61cfe2acb7 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -385,6 +385,70 @@ SYSCALL_IMPL(pwrite64)
     return ret;
 }
 
+/*
+ * Both preadv and pwritev merge args 4/5 into a 64-bit offset.
+ * Moreover, the parts are *always* in little-endian order.
+ */
+#if TARGET_ABI_BITS == 32
+SYSCALL_ARGS(preadv_pwritev)
+{
+    /* We have already assigned out[0-2].  */
+    abi_ulong lo = in[3], hi = in[4];
+    out[3] = (((uint64_t)hi << (TARGET_ABI_BITS - 1)) << 1) | lo;
+    return def;
+}
+#else
+#define args_preadv_pwritev NULL
+#endif
+
+/* Perform the inverse operation for the host.  */
+static inline void host_offset64_low_high(unsigned long *l, unsigned long *h,
+                                          uint64_t off)
+{
+    *l = off;
+    *h = (off >> (HOST_LONG_BITS - 1)) >> 1;
+}
+
+SYSCALL_IMPL(preadv)
+{
+    int fd = arg1;
+    abi_ulong target_vec = arg2;
+    int count = arg3;
+    uint64_t off = arg4;
+    struct iovec *vec = lock_iovec(VERIFY_WRITE, target_vec, count, 0);
+    unsigned long lo, hi;
+    abi_long ret;
+
+    if (vec == NULL) {
+        return -TARGET_EFAULT;
+    }
+
+    host_offset64_low_high(&lo, &hi, off);
+    ret = get_errno(safe_preadv(fd, vec, count, lo, hi));
+    unlock_iovec(vec, target_vec, count, 1);
+    return ret;
+}
+
+SYSCALL_IMPL(pwritev)
+{
+    int fd = arg1;
+    abi_ulong target_vec = arg2;
+    int count = arg3;
+    uint64_t off = arg4;
+    struct iovec *vec = lock_iovec(VERIFY_READ, target_vec, count, 1);
+    unsigned long lo, hi;
+    abi_long ret;
+
+    if (vec == NULL) {
+        return -TARGET_EFAULT;
+    }
+
+    host_offset64_low_high(&lo, &hi, off);
+    ret = get_errno(safe_pwritev(fd, vec, count, lo, hi));
+    unlock_iovec(vec, target_vec, count, 0);
+    return ret;
+}
+
 SYSCALL_IMPL(read)
 {
     int fd = arg1;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f636fb8bb3..817c4a7296 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2437,23 +2437,6 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
     return ret;
 }
 
-/* Convert target low/high pair representing file offset into the host
- * low/high pair. This function doesn't handle offsets bigger than 64 bits
- * as the kernel doesn't handle them either.
- */
-static void target_to_host_low_high(abi_ulong tlow,
-                                    abi_ulong thigh,
-                                    unsigned long *hlow,
-                                    unsigned long *hhigh)
-{
-    uint64_t off = tlow |
-        ((unsigned long long)thigh << TARGET_LONG_BITS / 2) <<
-        TARGET_LONG_BITS / 2;
-
-    *hlow = off;
-    *hhigh = (off >> HOST_LONG_BITS / 2) >> HOST_LONG_BITS / 2;
-}
-
 static struct iovec *lock_iovec(int type, abi_ulong target_addr,
                                 abi_ulong count, int copy)
 {
@@ -9005,38 +8988,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         /* NOTE: the flock constant seems to be the same for every
            Linux platform */
         return get_errno(safe_flock(arg1, arg2));
-#if defined(TARGET_NR_preadv)
-    case TARGET_NR_preadv:
-        {
-            struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
-            if (vec != NULL) {
-                unsigned long low, high;
-
-                target_to_host_low_high(arg4, arg5, &low, &high);
-                ret = get_errno(safe_preadv(arg1, vec, arg3, low, high));
-                unlock_iovec(vec, arg2, arg3, 1);
-            } else {
-                ret = -host_to_target_errno(errno);
-           }
-        }
-        return ret;
-#endif
-#if defined(TARGET_NR_pwritev)
-    case TARGET_NR_pwritev:
-        {
-            struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
-            if (vec != NULL) {
-                unsigned long low, high;
-
-                target_to_host_low_high(arg4, arg5, &low, &high);
-                ret = get_errno(safe_pwritev(arg1, vec, arg3, low, high));
-                unlock_iovec(vec, arg2, arg3, 0);
-            } else {
-                ret = -host_to_target_errno(errno);
-           }
-        }
-        return ret;
-#endif
     case TARGET_NR_getsid:
         return get_errno(getsid(arg1));
 #if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
diff --git a/linux-user/strace.list b/linux-user/strace.list
index a11ad3c3c7..f326613934 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1025,9 +1025,6 @@
 #ifdef TARGET_NR_prctl
 { TARGET_NR_prctl, "prctl" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_preadv
-{ TARGET_NR_preadv, "preadv" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_prlimit64
 { TARGET_NR_prlimit64, "prlimit64" , NULL, NULL, NULL },
 #endif
@@ -1052,9 +1049,6 @@
 #ifdef TARGET_NR_putpmsg
 { TARGET_NR_putpmsg, "putpmsg" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_pwritev
-{ TARGET_NR_pwritev, "pwritev" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_query_module
 { TARGET_NR_query_module, "query_module" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 12/74] linux-user: Split out name_to_handle_at, open_by_handle_at
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (10 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 11/74] linux-user: Split out preadv, pwritev Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 13/74] linux-user: Split out ipc syscalls Richard Henderson
                   ` (64 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

All targets have these syscalls, so they need not be ifdefed.
If we provide safe syscalls for the host, we can remove the
configure test for this too.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |   3 +
 linux-user/syscall.h          |   1 +
 linux-user/strace.c           |   5 +-
 linux-user/syscall-file.inc.c |  81 +++++++++++++++++++++++++++
 linux-user/syscall.c          | 102 ++--------------------------------
 configure                     |  20 -------
 linux-user/strace.list        |   3 -
 7 files changed, 93 insertions(+), 122 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index ae89be0e87..1fc89c1b08 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -17,10 +17,13 @@
  */
 
 SYSCALL_DEF(close, ARG_DEC);
+SYSCALL_DEF(name_to_handle_at,
+            ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_PTR, ARG_ATFLAG);
 #ifdef TARGET_NR_open
 SYSCALL_DEF(open, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG);
 #endif
 SYSCALL_DEF(openat, ARG_ATDIRFD, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG);
+SYSCALL_DEF(open_by_handle_at, ARG_DEC, ARG_PTR, ARG_OPENFLAG);
 SYSCALL_DEF_FULL(pread64, .impl = impl_pread64,
                  .args = args_pread64_pwrite64,
                  .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 });
diff --git a/linux-user/syscall.h b/linux-user/syscall.h
index 43b5dc0684..83f602f8e7 100644
--- a/linux-user/syscall.h
+++ b/linux-user/syscall.h
@@ -57,6 +57,7 @@ typedef enum {
 
     /* These print as sets of flags.  */
     ARG_ATDIRFD,
+    ARG_ATFLAG,
     ARG_MODEFLAG,
     ARG_OPENFLAG,
 
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 2f1c7e537f..e92b2c298e 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -780,7 +780,7 @@ UNUSED static struct flags access_flags[] = {
     FLAG_END,
 };
 
-UNUSED static struct flags at_file_flags[] = {
+static struct flags const at_file_flags[] = {
 #ifdef AT_EACCESS
     FLAG_GENERIC(AT_EACCESS),
 #endif
@@ -2693,6 +2693,9 @@ static void print_syscall_def1(const SyscallDef *def, int64_t args[6])
         case ARG_ATDIRFD:
             len = add_atdirfd(b, rest, arg);
             break;
+        case ARG_ATFLAG:
+            len = add_flags(b, rest, at_file_flags, arg, false);
+            break;
         case ARG_MODEFLAG:
             len = add_flags(b, rest, mode_flags, arg, true);
             break;
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 61cfe2acb7..dd44d5b804 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -323,6 +323,87 @@ SYSCALL_IMPL(openat)
     return do_openat(cpu_env, arg1, arg2, arg3, arg4);
 }
 
+SYSCALL_IMPL(name_to_handle_at)
+{
+    struct file_handle *target_fh;
+    struct file_handle *fh;
+    int mid = 0;
+    abi_long ret;
+    char *name;
+    uint32_t size, total_size;
+
+    if (get_user_s32(size, arg3)) {
+        return -TARGET_EFAULT;
+    }
+    total_size = sizeof(struct file_handle) + size;
+    target_fh = lock_user(VERIFY_WRITE, arg3, total_size, 0);
+    if (!target_fh) {
+        return -TARGET_EFAULT;
+    }
+
+    name = lock_user_string(arg2);
+    if (!name) {
+        unlock_user(target_fh, arg3, 0);
+        return -TARGET_EFAULT;
+    }
+
+    fh = g_malloc0(total_size);
+    fh->handle_bytes = size;
+
+    ret = get_errno(safe_name_to_handle_at(arg1, path(name), fh, &mid, arg5));
+    unlock_user(name, arg2, 0);
+
+    /*
+     * man name_to_handle_at(2):
+     * Other than the use of the handle_bytes field, the caller should treat
+     * the file_handle structure as an opaque data type
+     */
+    if (!is_error(ret)) {
+        memcpy(target_fh, fh, total_size);
+        target_fh->handle_bytes = tswap32(fh->handle_bytes);
+        target_fh->handle_type = tswap32(fh->handle_type);
+        g_free(fh);
+        unlock_user(target_fh, arg3, total_size);
+
+        if (put_user_s32(mid, arg4)) {
+            return -TARGET_EFAULT;
+        }
+    }
+    return ret;
+}
+
+SYSCALL_IMPL(open_by_handle_at)
+{
+    abi_long mount_fd = arg1;
+    abi_long handle = arg2;
+    int host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl);
+    struct file_handle *target_fh;
+    struct file_handle *fh;
+    unsigned int size, total_size;
+    abi_long ret;
+
+    if (get_user_s32(size, handle)) {
+        return -TARGET_EFAULT;
+    }
+    total_size = sizeof(struct file_handle) + size;
+    target_fh = lock_user(VERIFY_READ, handle, total_size, 1);
+    if (!target_fh) {
+        return -TARGET_EFAULT;
+    }
+
+    fh = g_memdup(target_fh, total_size);
+    fh->handle_bytes = size;
+    fh->handle_type = tswap32(target_fh->handle_type);
+
+    ret = get_errno(safe_open_by_handle_at(mount_fd, fh, host_flags));
+
+    g_free(fh);
+    unlock_user(target_fh, handle, total_size);
+
+    fd_trans_unregister(ret);
+    return ret;
+}
+
 /*
  * Both pread64 and pwrite64 merge args into a 64-bit offset,
  * but the input registers and ordering are target specific.
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 817c4a7296..c49f8aebd2 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -806,6 +806,10 @@ safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr,
 safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr,
               size_t, len, unsigned *, prio, const struct timespec *, timeout)
 #endif
+safe_syscall5(int, name_to_handle_at, int, dirfd, const char *, pathname,
+              struct file_handle *, handle, int *, mount_id, int, flags)
+safe_syscall3(int, open_by_handle_at, int, mount_fd,
+              struct file_handle *, handle, int, flags)
 /* We do ioctl like this rather than via safe_syscall3 to preserve the
  * "third argument might be integer or pointer or not present" behaviour of
  * the libc function.
@@ -6479,93 +6483,6 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
         return -TARGET_ENOSYS;
     }
 }
-#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
-static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
-                                     abi_long handle, abi_long mount_id,
-                                     abi_long flags)
-{
-    struct file_handle *target_fh;
-    struct file_handle *fh;
-    int mid = 0;
-    abi_long ret;
-    char *name;
-    unsigned int size, total_size;
-
-    if (get_user_s32(size, handle)) {
-        return -TARGET_EFAULT;
-    }
-
-    name = lock_user_string(pathname);
-    if (!name) {
-        return -TARGET_EFAULT;
-    }
-
-    total_size = sizeof(struct file_handle) + size;
-    target_fh = lock_user(VERIFY_WRITE, handle, total_size, 0);
-    if (!target_fh) {
-        unlock_user(name, pathname, 0);
-        return -TARGET_EFAULT;
-    }
-
-    fh = g_malloc0(total_size);
-    fh->handle_bytes = size;
-
-    ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags));
-    unlock_user(name, pathname, 0);
-
-    /* man name_to_handle_at(2):
-     * Other than the use of the handle_bytes field, the caller should treat
-     * the file_handle structure as an opaque data type
-     */
-
-    memcpy(target_fh, fh, total_size);
-    target_fh->handle_bytes = tswap32(fh->handle_bytes);
-    target_fh->handle_type = tswap32(fh->handle_type);
-    g_free(fh);
-    unlock_user(target_fh, handle, total_size);
-
-    if (put_user_s32(mid, mount_id)) {
-        return -TARGET_EFAULT;
-    }
-
-    return ret;
-
-}
-#endif
-
-#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
-static abi_long do_open_by_handle_at(abi_long mount_fd, abi_long handle,
-                                     abi_long flags)
-{
-    struct file_handle *target_fh;
-    struct file_handle *fh;
-    unsigned int size, total_size;
-    abi_long ret;
-
-    if (get_user_s32(size, handle)) {
-        return -TARGET_EFAULT;
-    }
-
-    total_size = sizeof(struct file_handle) + size;
-    target_fh = lock_user(VERIFY_READ, handle, total_size, 1);
-    if (!target_fh) {
-        return -TARGET_EFAULT;
-    }
-
-    fh = g_memdup(target_fh, total_size);
-    fh->handle_bytes = size;
-    fh->handle_type = tswap32(target_fh->handle_type);
-
-    ret = get_errno(open_by_handle_at(mount_fd, fh,
-                    target_to_host_bitmask(flags, fcntl_flags_tbl)));
-
-    g_free(fh);
-
-    unlock_user(target_fh, handle, total_size);
-
-    return ret;
-}
-#endif
 
 #if defined(TARGET_NR_signalfd) || defined(TARGET_NR_signalfd4)
 
@@ -6761,17 +6678,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         preexit_cleanup(cpu_env, arg1);
         _exit(arg1);
         return 0; /* avoid warning */
-#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
-    case TARGET_NR_name_to_handle_at:
-        ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
-        return ret;
-#endif
-#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
-    case TARGET_NR_open_by_handle_at:
-        ret = do_open_by_handle_at(arg1, arg2, arg3);
-        fd_trans_unregister(ret);
-        return ret;
-#endif
     case TARGET_NR_brk:
         return do_brk(arg1);
 #ifdef TARGET_NR_fork
diff --git a/configure b/configure
index d2fc346302..6573fcefcb 100755
--- a/configure
+++ b/configure
@@ -5243,22 +5243,6 @@ if test "$debug_stack_usage" = "yes"; then
 fi
 
 
-##########################################
-# check if we have open_by_handle_at
-
-open_by_handle_at=no
-cat > $TMPC << EOF
-#include <fcntl.h>
-#if !defined(AT_EMPTY_PATH)
-# error missing definition
-#else
-int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
-#endif
-EOF
-if compile_prog "" "" ; then
-    open_by_handle_at=yes
-fi
-
 ########################################
 # check if we have linux/magic.h
 
@@ -7012,10 +6996,6 @@ if test "$crypto_afalg" = "yes" ; then
   echo "CONFIG_AF_ALG=y" >> $config_host_mak
 fi
 
-if test "$open_by_handle_at" = "yes" ; then
-  echo "CONFIG_OPEN_BY_HANDLE=y" >> $config_host_mak
-fi
-
 if test "$linux_magic_h" = "yes" ; then
   echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak
 fi
diff --git a/linux-user/strace.list b/linux-user/strace.list
index f326613934..bf239cb9a3 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -635,9 +635,6 @@
 #ifdef TARGET_NR_munmap
 { TARGET_NR_munmap, "munmap" , NULL, print_munmap, NULL },
 #endif
-#ifdef TARGET_NR_name_to_handle_at
-{ TARGET_NR_name_to_handle_at, "name_to_handle_at" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_nanosleep
 { TARGET_NR_nanosleep, "nanosleep" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 13/74] linux-user: Split out ipc syscalls
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (11 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 12/74] linux-user: Split out name_to_handle_at, open_by_handle_at Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 14/74] linux-user: Split out memory syscalls Richard Henderson
                   ` (63 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Because of the ipc multiplex syscall, these must be done all at once.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h    |   38 ++
 linux-user/strace.c          |   83 ---
 linux-user/syscall-ipc.inc.c | 1088 ++++++++++++++++++++++++++++++++++
 linux-user/syscall.c         |  973 +-----------------------------
 linux-user/strace.list       |   42 --
 5 files changed, 1129 insertions(+), 1095 deletions(-)
 create mode 100644 linux-user/syscall-ipc.inc.c

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 1fc89c1b08..6d6349da01 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -17,6 +17,21 @@
  */
 
 SYSCALL_DEF(close, ARG_DEC);
+#ifdef TARGET_NR_ipc
+SYSCALL_DEF_ARGS(ipc, ARG_HEX, ARG_DEC, ARG_DEC, ARG_HEX, ARG_PTR, ARG_HEX);
+#endif
+#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_msgctl)
+SYSCALL_DEF(msgctl, ARG_DEC, ARG_DEC, ARG_PTR);
+#endif
+#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_msgget)
+SYSCALL_DEF(msgget, ARG_DEC, ARG_DEC);
+#endif
+#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_msgrcv)
+SYSCALL_DEF(msgrcv, ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC, ARG_HEX);
+#endif
+#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_msgsnd)
+SYSCALL_DEF(msgsnd, ARG_DEC, ARG_PTR, ARG_DEC, ARG_HEX);
+#endif
 SYSCALL_DEF(name_to_handle_at,
             ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_PTR, ARG_ATFLAG);
 #ifdef TARGET_NR_open
@@ -44,5 +59,28 @@ SYSCALL_DEF(readlink, ARG_STR, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(readlinkat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_DEC);
 #endif
 SYSCALL_DEF(readv, ARG_DEC, ARG_PTR, ARG_DEC);
+#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semctl)
+SYSCALL_DEF(semctl, ARG_DEC, ARG_DEC, ARG_DEC, ARG_HEX);
+#endif
+#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semget)
+SYSCALL_DEF(semget, ARG_DEC, ARG_DEC, ARG_HEX);
+#endif
+#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semop)
+SYSCALL_DEF(semop, ARG_DEC, ARG_PTR, ARG_DEC);
+#endif
+#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_shmat)
+SYSCALL_DEF_FULL(shmat, .impl = impl_shmat,
+                 .print_ret = print_syscall_ptr_ret,
+                 .arg_type = { ARG_DEC, ARG_PTR, ARG_HEX });
+#endif
+#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_shmctl)
+SYSCALL_DEF(shmctl, ARG_DEC, ARG_DEC, ARG_PTR);
+#endif
+#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_shmdt)
+SYSCALL_DEF(shmdt, ARG_PTR);
+#endif
+#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_shmget)
+SYSCALL_DEF(shmget, ARG_DEC, ARG_DEC, ARG_HEX);
+#endif
 SYSCALL_DEF(write, ARG_DEC, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(writev, ARG_DEC, ARG_PTR, ARG_DEC);
diff --git a/linux-user/strace.c b/linux-user/strace.c
index e92b2c298e..e1c4859a95 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1,8 +1,4 @@
 #include "qemu/osdep.h"
-#include <sys/ipc.h>
-#include <sys/msg.h>
-#include <sys/sem.h>
-#include <sys/shm.h>
 #include <sys/select.h>
 #include <sys/mount.h>
 #include <arpa/inet.h>
@@ -74,54 +70,6 @@ UNUSED static void print_socket_protocol(int domain, int type, int protocol);
 /*
  * Utility functions
  */
-static void
-print_ipc_cmd(int cmd)
-{
-#define output_cmd(val) \
-if( cmd == val ) { \
-    gemu_log(#val); \
-    return; \
-}
-
-    cmd &= 0xff;
-
-    /* General IPC commands */
-    output_cmd( IPC_RMID );
-    output_cmd( IPC_SET );
-    output_cmd( IPC_STAT );
-    output_cmd( IPC_INFO );
-    /* msgctl() commands */
-    output_cmd( MSG_STAT );
-    output_cmd( MSG_INFO );
-    /* shmctl() commands */
-    output_cmd( SHM_LOCK );
-    output_cmd( SHM_UNLOCK );
-    output_cmd( SHM_STAT );
-    output_cmd( SHM_INFO );
-    /* semctl() commands */
-    output_cmd( GETPID );
-    output_cmd( GETVAL );
-    output_cmd( GETALL );
-    output_cmd( GETNCNT );
-    output_cmd( GETZCNT );
-    output_cmd( SETVAL );
-    output_cmd( SETALL );
-    output_cmd( SEM_STAT );
-    output_cmd( SEM_INFO );
-    output_cmd( IPC_RMID );
-    output_cmd( IPC_RMID );
-    output_cmd( IPC_RMID );
-    output_cmd( IPC_RMID );
-    output_cmd( IPC_RMID );
-    output_cmd( IPC_RMID );
-    output_cmd( IPC_RMID );
-    output_cmd( IPC_RMID );
-    output_cmd( IPC_RMID );
-
-    /* Some value we don't recognize */
-    gemu_log("%d",cmd);
-}
-
 static void
 print_signal(abi_ulong arg, int last)
 {
@@ -620,18 +568,6 @@ print_newselect(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_semctl
-static void
-print_semctl(const struct syscallname *name,
-             abi_long arg1, abi_long arg2, abi_long arg3,
-             abi_long arg4, abi_long arg5, abi_long arg6)
-{
-    gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", name->name, arg1, arg2);
-    print_ipc_cmd(arg3);
-    gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4);
-}
-#endif
-
 static void
 print_execve(const struct syscallname *name,
              abi_long arg1, abi_long arg2, abi_long arg3,
@@ -664,25 +600,6 @@ print_execve(const struct syscallname *name,
     gemu_log("NULL})");
 }
 
-#ifdef TARGET_NR_ipc
-static void
-print_ipc(const struct syscallname *name,
-          abi_long arg1, abi_long arg2, abi_long arg3,
-          abi_long arg4, abi_long arg5, abi_long arg6)
-{
-    switch(arg1) {
-    case IPCOP_semctl:
-        gemu_log("semctl(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", arg1, arg2);
-        print_ipc_cmd(arg3);
-        gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4);
-        break;
-    default:
-        gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")",
-                 name->name, arg1, arg2, arg3, arg4);
-    }
-}
-#endif
-
 /*
  * Variants for the return value output function
  */
diff --git a/linux-user/syscall-ipc.inc.c b/linux-user/syscall-ipc.inc.c
new file mode 100644
index 0000000000..26ee3be8bf
--- /dev/null
+++ b/linux-user/syscall-ipc.inc.c
@@ -0,0 +1,1088 @@
+/*
+ *  Linux ipc-related syscalls
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifdef __NR_msgsnd
+safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz,
+              int, flags)
+safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz,
+              long, msgtype, int, flags)
+safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops,
+              unsigned, nsops, const struct timespec *, timeout)
+#else
+/*
+ * This host kernel architecture uses a single ipc syscall; fake up
+ * wrappers for the sub-operations to hide this implementation detail.
+ * Annoyingly we can't include linux/ipc.h to get the constant definitions
+ * for the call parameter because some structs in there conflict with the
+ * sys/ipc.h ones. So we just define them here, and rely on them being
+ * the same for all host architectures.
+ */
+#define Q_SEMTIMEDOP 4
+#define Q_MSGSND 11
+#define Q_MSGRCV 12
+#define Q_IPCCALL(VERSION, OP) ((VERSION) << 16 | (OP))
+
+safe_syscall6(int, ipc, int, call, long, first, long, second, long, third,
+              void *, ptr, long, fifth)
+
+static int safe_msgsnd(int msgid, const void *msgp, size_t sz, int flags)
+{
+    return safe_ipc(Q_IPCCALL(0, Q_MSGSND), msgid, sz, flags, (void *)msgp, 0);
+}
+
+static int safe_msgrcv(int msgid, void *msgp, size_t sz, long type, int flags)
+{
+    return safe_ipc(Q_IPCCALL(1, Q_MSGRCV), msgid, sz, flags, msgp, type);
+}
+
+static int safe_semtimedop(int semid, struct sembuf *tsops, unsigned nsops,
+                           const struct timespec *timeout)
+{
+    return safe_ipc(Q_IPCCALL(0, Q_SEMTIMEDOP), semid, nsops, 0, tsops,
+                    (long)timeout);
+}
+#endif
+
+/* See <linux/ipc.h> comment above.  */
+#define SEMOPM  500
+
+#define N_SHM_REGIONS  32
+
+static struct shm_region {
+    abi_ulong start;
+    abi_ulong size;
+    bool in_use;
+} shm_regions[N_SHM_REGIONS];
+
+#ifndef TARGET_SEMID64_DS
+/* asm-generic version of this struct */
+struct target_semid64_ds {
+    struct target_ipc_perm sem_perm;
+    abi_ulong sem_otime;
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused1;
+#endif
+    abi_ulong sem_ctime;
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused2;
+#endif
+    abi_ulong sem_nsems;
+    abi_ulong __unused3;
+    abi_ulong __unused4;
+};
+#endif
+
+static abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
+                                        abi_ulong target_addr)
+{
+    struct target_ipc_perm *target_ip;
+    struct target_semid64_ds *target_sd;
+
+    if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) {
+        return -TARGET_EFAULT;
+    }
+    target_ip = &target_sd->sem_perm;
+    host_ip->__key = tswap32(target_ip->__key);
+    host_ip->uid = tswap32(target_ip->uid);
+    host_ip->gid = tswap32(target_ip->gid);
+    host_ip->cuid = tswap32(target_ip->cuid);
+    host_ip->cgid = tswap32(target_ip->cgid);
+#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
+    host_ip->mode = tswap32(target_ip->mode);
+#else
+    host_ip->mode = tswap16(target_ip->mode);
+#endif
+#if defined(TARGET_PPC)
+    host_ip->__seq = tswap32(target_ip->__seq);
+#else
+    host_ip->__seq = tswap16(target_ip->__seq);
+#endif
+    unlock_user_struct(target_sd, target_addr, 0);
+    return 0;
+}
+
+static abi_long host_to_target_ipc_perm(abi_ulong target_addr,
+                                        struct ipc_perm *host_ip)
+{
+    struct target_ipc_perm *target_ip;
+    struct target_semid64_ds *target_sd;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+    target_ip = &target_sd->sem_perm;
+    target_ip->__key = tswap32(host_ip->__key);
+    target_ip->uid = tswap32(host_ip->uid);
+    target_ip->gid = tswap32(host_ip->gid);
+    target_ip->cuid = tswap32(host_ip->cuid);
+    target_ip->cgid = tswap32(host_ip->cgid);
+#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
+    target_ip->mode = tswap32(host_ip->mode);
+#else
+    target_ip->mode = tswap16(host_ip->mode);
+#endif
+#if defined(TARGET_PPC)
+    target_ip->__seq = tswap32(host_ip->__seq);
+#else
+    target_ip->__seq = tswap16(host_ip->__seq);
+#endif
+    unlock_user_struct(target_sd, target_addr, 1);
+    return 0;
+}
+
+static abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
+                                        abi_ulong target_addr)
+{
+    struct target_semid64_ds *target_sd;
+
+    if (target_to_host_ipc_perm(&host_sd->sem_perm, target_addr)) {
+        return -TARGET_EFAULT;
+    }
+    if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) {
+        return -TARGET_EFAULT;
+    }
+    host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
+    host_sd->sem_otime = tswapal(target_sd->sem_otime);
+    host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
+    unlock_user_struct(target_sd, target_addr, 0);
+    return 0;
+}
+
+static abi_long host_to_target_semid_ds(abi_ulong target_addr,
+                                        struct semid_ds *host_sd)
+{
+    struct target_semid64_ds *target_sd;
+
+    if (host_to_target_ipc_perm(target_addr, &host_sd->sem_perm)) {
+        return -TARGET_EFAULT;
+    }
+    if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+    target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
+    target_sd->sem_otime = tswapal(host_sd->sem_otime);
+    target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
+    unlock_user_struct(target_sd, target_addr, 1);
+    return 0;
+}
+
+struct target_seminfo {
+    int semmap;
+    int semmni;
+    int semmns;
+    int semmnu;
+    int semmsl;
+    int semopm;
+    int semume;
+    int semusz;
+    int semvmx;
+    int semaem;
+};
+
+static abi_long host_to_target_seminfo(abi_ulong target_addr,
+                                       struct seminfo *host_seminfo)
+{
+    struct target_seminfo *target_seminfo;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+    __put_user(host_seminfo->semmap, &target_seminfo->semmap);
+    __put_user(host_seminfo->semmni, &target_seminfo->semmni);
+    __put_user(host_seminfo->semmns, &target_seminfo->semmns);
+    __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
+    __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
+    __put_user(host_seminfo->semopm, &target_seminfo->semopm);
+    __put_user(host_seminfo->semume, &target_seminfo->semume);
+    __put_user(host_seminfo->semusz, &target_seminfo->semusz);
+    __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
+    __put_user(host_seminfo->semaem, &target_seminfo->semaem);
+    unlock_user_struct(target_seminfo, target_addr, 1);
+    return 0;
+}
+
+union semun {
+    int val;
+    struct semid_ds *buf;
+    unsigned short *array;
+    struct seminfo *__buf;
+};
+
+union target_semun {
+    int val;
+    abi_ulong buf;
+    abi_ulong array;
+    abi_ulong __buf;
+};
+
+static abi_long target_to_host_semarray(int semid,
+                                        unsigned short **host_array,
+                                        abi_ulong target_addr)
+{
+    int nsems;
+    unsigned short *array;
+    union semun semun;
+    struct semid_ds semid_ds;
+    int i, ret;
+
+    semun.buf = &semid_ds;
+
+    ret = semctl(semid, 0, IPC_STAT, semun);
+    if (ret == -1) {
+        return get_errno(ret);
+    }
+
+    nsems = semid_ds.sem_nsems;
+
+    *host_array = g_try_new(unsigned short, nsems);
+    if (!*host_array) {
+        return -TARGET_ENOMEM;
+    }
+    array = lock_user(VERIFY_READ, target_addr,
+                      nsems * sizeof(unsigned short), 1);
+    if (!array) {
+        g_free(*host_array);
+        return -TARGET_EFAULT;
+    }
+    for (i = 0; i < nsems; i++) {
+        __get_user((*host_array)[i], &array[i]);
+    }
+    unlock_user(array, target_addr, 0);
+
+    return 0;
+}
+
+static abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
+                                        unsigned short **host_array)
+{
+    int nsems;
+    unsigned short *array;
+    union semun semun;
+    struct semid_ds semid_ds;
+    int i, ret;
+
+    semun.buf = &semid_ds;
+
+    ret = semctl(semid, 0, IPC_STAT, semun);
+    if (ret == -1) {
+        return get_errno(ret);
+    }
+
+    nsems = semid_ds.sem_nsems;
+
+    array = lock_user(VERIFY_WRITE, target_addr,
+                      nsems * sizeof(unsigned short), 0);
+    if (!array) {
+        return -TARGET_EFAULT;
+    }
+    for (i = 0; i < nsems; i++) {
+        __put_user((*host_array)[i], &array[i]);
+    }
+    g_free(*host_array);
+    unlock_user(array, target_addr, 1);
+
+    return 0;
+}
+
+struct target_sembuf {
+    unsigned short sem_num;
+    short sem_op;
+    short sem_flg;
+};
+
+static abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
+                                      abi_ulong target_addr,
+                                      unsigned nsops)
+{
+    struct target_sembuf *target_sembuf;
+    int i;
+
+    target_sembuf = lock_user(VERIFY_READ, target_addr,
+                              nsops * sizeof(struct target_sembuf), 1);
+    if (!target_sembuf) {
+        return -TARGET_EFAULT;
+    }
+    for (i = 0; i < nsops; i++) {
+        __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
+        __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
+        __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
+    }
+    unlock_user(target_sembuf, target_addr, 0);
+    return 0;
+}
+
+struct target_msqid_ds {
+    struct target_ipc_perm msg_perm;
+    abi_ulong msg_stime;
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused1;
+#endif
+    abi_ulong msg_rtime;
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused2;
+#endif
+    abi_ulong msg_ctime;
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused3;
+#endif
+    abi_ulong __msg_cbytes;
+    abi_ulong msg_qnum;
+    abi_ulong msg_qbytes;
+    abi_ulong msg_lspid;
+    abi_ulong msg_lrpid;
+    abi_ulong __unused4;
+    abi_ulong __unused5;
+};
+
+static abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
+                                        abi_ulong target_addr)
+{
+    struct target_msqid_ds *target_md;
+
+    if (target_to_host_ipc_perm(&host_md->msg_perm, target_addr)) {
+        return -TARGET_EFAULT;
+    }
+    if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1)) {
+        return -TARGET_EFAULT;
+    }
+    host_md->msg_stime = tswapal(target_md->msg_stime);
+    host_md->msg_rtime = tswapal(target_md->msg_rtime);
+    host_md->msg_ctime = tswapal(target_md->msg_ctime);
+    host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes);
+    host_md->msg_qnum = tswapal(target_md->msg_qnum);
+    host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
+    host_md->msg_lspid = tswapal(target_md->msg_lspid);
+    host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
+    unlock_user_struct(target_md, target_addr, 0);
+    return 0;
+}
+
+static abi_long host_to_target_msqid_ds(abi_ulong target_addr,
+                                        struct msqid_ds *host_md)
+{
+    struct target_msqid_ds *target_md;
+
+    if (host_to_target_ipc_perm(target_addr, &host_md->msg_perm)) {
+        return -TARGET_EFAULT;
+    }
+    if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+    target_md->msg_stime = tswapal(host_md->msg_stime);
+    target_md->msg_rtime = tswapal(host_md->msg_rtime);
+    target_md->msg_ctime = tswapal(host_md->msg_ctime);
+    target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes);
+    target_md->msg_qnum = tswapal(host_md->msg_qnum);
+    target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
+    target_md->msg_lspid = tswapal(host_md->msg_lspid);
+    target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
+    unlock_user_struct(target_md, target_addr, 1);
+    return 0;
+}
+
+struct target_msginfo {
+    int msgpool;
+    int msgmap;
+    int msgmax;
+    int msgmnb;
+    int msgmni;
+    int msgssz;
+    int msgtql;
+    unsigned short int msgseg;
+};
+
+static abi_long host_to_target_msginfo(abi_ulong target_addr,
+                                       struct msginfo *host_msginfo)
+{
+    struct target_msginfo *target_msginfo;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+    __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
+    __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
+    __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
+    __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
+    __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
+    __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
+    __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
+    __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
+    unlock_user_struct(target_msginfo, target_addr, 1);
+    return 0;
+}
+
+struct target_msgbuf {
+    abi_long mtype;
+    char mtext[1];
+};
+
+static abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
+                                        abi_ulong target_addr)
+{
+    struct target_shmid_ds *target_sd;
+
+    if (target_to_host_ipc_perm(&host_sd->shm_perm, target_addr)) {
+        return -TARGET_EFAULT;
+    }
+    if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) {
+        return -TARGET_EFAULT;
+    }
+    __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
+    __get_user(host_sd->shm_atime, &target_sd->shm_atime);
+    __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
+    __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
+    __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
+    __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
+    __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
+    unlock_user_struct(target_sd, target_addr, 0);
+    return 0;
+}
+
+static abi_long host_to_target_shmid_ds(abi_ulong target_addr,
+                                        struct shmid_ds *host_sd)
+{
+    struct target_shmid_ds *target_sd;
+
+    if (host_to_target_ipc_perm(target_addr, &host_sd->shm_perm)) {
+        return -TARGET_EFAULT;
+    }
+    if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+    __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
+    __put_user(host_sd->shm_atime, &target_sd->shm_atime);
+    __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
+    __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
+    __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
+    __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
+    __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
+    unlock_user_struct(target_sd, target_addr, 1);
+    return 0;
+}
+
+struct target_shminfo {
+    abi_ulong shmmax;
+    abi_ulong shmmin;
+    abi_ulong shmmni;
+    abi_ulong shmseg;
+    abi_ulong shmall;
+};
+
+static abi_long host_to_target_shminfo(abi_ulong target_addr,
+                                       struct shminfo *host_shminfo)
+{
+    struct target_shminfo *target_shminfo;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+    __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
+    __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
+    __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
+    __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
+    __put_user(host_shminfo->shmall, &target_shminfo->shmall);
+    unlock_user_struct(target_shminfo, target_addr, 1);
+    return 0;
+}
+
+struct target_shm_info {
+    int used_ids;
+    abi_ulong shm_tot;
+    abi_ulong shm_rss;
+    abi_ulong shm_swp;
+    abi_ulong swap_attempts;
+    abi_ulong swap_successes;
+};
+
+static abi_long host_to_target_shm_info(abi_ulong target_addr,
+                                        struct shm_info *host_shm_info)
+{
+    struct target_shm_info *target_shm_info;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+    __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
+    __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
+    __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
+    __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
+    __put_user(host_shm_info->swap_attempts,
+               &target_shm_info->swap_attempts);
+    __put_user(host_shm_info->swap_successes,
+               &target_shm_info->swap_successes);
+    unlock_user_struct(target_shm_info, target_addr, 1);
+    return 0;
+}
+
+#ifndef TARGET_FORCE_SHMLBA
+/*
+ * For most architectures, SHMLBA is the same as the page size;
+ * some architectures have larger values, in which case they should
+ * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function.
+ * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA
+ * and defining its own value for SHMLBA.
+ *
+ * The kernel also permits SHMLBA to be set by the architecture to a
+ * value larger than the page size without setting __ARCH_FORCE_SHMLBA;
+ * this means that addresses are rounded to the large size if
+ * SHM_RND is set but addresses not aligned to that size are not rejected
+ * as long as they are at least page-aligned. Since the only architecture
+ * which uses this is ia64 this code doesn't provide for that oddity.
+ */
+static abi_ulong target_shmlba(CPUArchState *cpu_env)
+{
+    return TARGET_PAGE_SIZE;
+}
+#endif
+
+
+SYSCALL_IMPL(msgctl)
+{
+    abi_long msgid = arg1;
+    int cmd = arg2 & 0xff;
+    abi_ulong ptr = arg3;
+    struct msqid_ds dsarg;
+    struct msginfo msginfo;
+    abi_long ret;
+
+    switch (cmd) {
+    case IPC_STAT:
+    case IPC_SET:
+    case MSG_STAT:
+        if (target_to_host_msqid_ds(&dsarg, ptr)) {
+            return -TARGET_EFAULT;
+        }
+        ret = get_errno(msgctl(msgid, cmd, &dsarg));
+        if (!is_error(ret) && host_to_target_msqid_ds(ptr, &dsarg)) {
+            return -TARGET_EFAULT;
+        }
+        return ret;
+
+    case IPC_RMID:
+        return get_errno(msgctl(msgid, cmd, NULL));
+
+    case IPC_INFO:
+    case MSG_INFO:
+        ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
+        if (host_to_target_msginfo(ptr, &msginfo)) {
+            return -TARGET_EFAULT;
+        }
+        return ret;
+
+    default:
+        return -TARGET_EINVAL;
+    }
+}
+
+SYSCALL_IMPL(msgget)
+{
+    return get_errno(msgget(arg1, arg2));
+}
+
+SYSCALL_IMPL(msgrcv)
+{
+    int msqid = arg1;
+    abi_ulong msgp = arg2;
+    abi_long msgsz = arg3;
+    abi_long msgtyp = arg4;
+    int msgflg = arg5;
+    struct target_msgbuf *target_mb;
+    char *target_mtext;
+    struct msgbuf *host_mb;
+    abi_long ret = 0;
+
+    if (msgsz < 0) {
+        return -TARGET_EINVAL;
+    }
+    if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0)) {
+        return -TARGET_EFAULT;
+    }
+
+    host_mb = g_try_malloc(msgsz + sizeof(long));
+    if (!host_mb) {
+        ret = -TARGET_ENOMEM;
+        goto end;
+    }
+    ret = get_errno(safe_msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
+
+    if (ret > 0) {
+        abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
+        target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
+        if (!target_mtext) {
+            ret = -TARGET_EFAULT;
+            goto end;
+        }
+        memcpy(target_mb->mtext, host_mb->mtext, ret);
+        unlock_user(target_mtext, target_mtext_addr, ret);
+    }
+    target_mb->mtype = tswapal(host_mb->mtype);
+
+ end:
+    unlock_user_struct(target_mb, msgp, 1);
+    g_free(host_mb);
+    return ret;
+}
+
+SYSCALL_IMPL(msgsnd)
+{
+    int msqid = arg1;
+    abi_ulong msgp = arg2;
+    abi_long msgsz = arg3;
+    int msgflg = arg4;
+    struct target_msgbuf *target_mb;
+    struct msgbuf *host_mb;
+    abi_long ret = 0;
+
+    if (msgsz < 0) {
+        return -TARGET_EINVAL;
+    }
+    if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0)) {
+        return -TARGET_EFAULT;
+    }
+    host_mb = g_try_malloc(msgsz + sizeof(long));
+    if (!host_mb) {
+        unlock_user_struct(target_mb, msgp, 0);
+        return -TARGET_ENOMEM;
+    }
+
+    host_mb->mtype = (abi_long)tswapal(target_mb->mtype);
+    memcpy(host_mb->mtext, target_mb->mtext, msgsz);
+    ret = get_errno(safe_msgsnd(msqid, host_mb, msgsz, msgflg));
+
+    g_free(host_mb);
+    unlock_user_struct(target_mb, msgp, 0);
+    return ret;
+}
+
+SYSCALL_IMPL(semctl)
+{
+    abi_long semid = arg1;
+    abi_long semnum = arg2;
+    int cmd = arg3 & 0xff;
+    abi_ulong target_arg = arg4;
+    union target_semun target_su = { .buf = target_arg };
+    union semun arg;
+    struct semid_ds dsarg;
+    unsigned short *array = NULL;
+    struct seminfo seminfo;
+    abi_long ret, err;
+
+    switch (cmd) {
+    case GETVAL:
+    case SETVAL:
+        /*
+         * In 64 bit cross-endian situations, we will erroneously pick up
+         * the wrong half of the union for the "val" element.  To rectify
+         * this, the entire 8-byte structure is byteswapped, followed by
+         * a swap of the 4 byte val field. In other cases, the data is
+         * already in proper host byte order.
+         */
+        if (sizeof(target_su.val) != sizeof(target_su.buf)) {
+            target_su.buf = tswapal(target_su.buf);
+            arg.val = tswap32(target_su.val);
+        } else {
+            arg.val = target_su.val;
+        }
+        return get_errno(semctl(semid, semnum, cmd, arg));
+
+    case GETALL:
+    case SETALL:
+        err = target_to_host_semarray(semid, &array, target_su.array);
+        if (err) {
+            return err;
+        }
+        arg.array = array;
+        ret = get_errno(semctl(semid, semnum, cmd, arg));
+        if (!is_error(ret)) {
+            err = host_to_target_semarray(semid, target_su.array, &array);
+            if (err) {
+                return err;
+            }
+        }
+        return ret;
+
+    case IPC_STAT:
+    case IPC_SET:
+    case SEM_STAT:
+        err = target_to_host_semid_ds(&dsarg, target_su.buf);
+        if (err) {
+            return err;
+        }
+        arg.buf = &dsarg;
+        ret = get_errno(semctl(semid, semnum, cmd, arg));
+        if (!is_error(ret)) {
+            err = host_to_target_semid_ds(target_su.buf, &dsarg);
+            if (err) {
+                return err;
+            }
+        }
+        return ret;
+
+    case IPC_INFO:
+    case SEM_INFO:
+        arg.__buf = &seminfo;
+        ret = get_errno(semctl(semid, semnum, cmd, arg));
+        if (!is_error(ret)) {
+            err = host_to_target_seminfo(target_su.__buf, &seminfo);
+            if (err) {
+                return err;
+            }
+        }
+        return ret;
+
+    case IPC_RMID:
+    case GETPID:
+    case GETNCNT:
+    case GETZCNT:
+        return get_errno(semctl(semid, semnum, cmd, NULL));
+
+    default:
+        return -TARGET_EINVAL;
+    }
+}
+
+SYSCALL_IMPL(semget)
+{
+    return get_errno(semget(arg1, arg2, arg3));
+}
+
+SYSCALL_IMPL(semop)
+{
+    abi_long semid = arg1;
+    abi_ulong ptr = arg2;
+    abi_ulong nsops = arg3;
+    struct sembuf sops[SEMOPM];
+
+    if (nsops > SEMOPM) {
+        return -TARGET_E2BIG;
+    }
+    if (target_to_host_sembuf(sops, ptr, nsops)) {
+        return -TARGET_EFAULT;
+    }
+    return get_errno(safe_semtimedop(semid, sops, nsops, NULL));
+}
+
+SYSCALL_IMPL(shmat)
+{
+    int shmid = arg1;
+    abi_ulong shmaddr = arg2;
+    int shmflg = arg3;
+    abi_ulong raddr;
+    void *host_raddr;
+    struct shmid_ds shm_info;
+    int i, ret;
+    abi_ulong shmlba;
+
+    /* Find out the length of the shared memory segment.  */
+    ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
+    if (is_error(ret)) {
+        /* can't get length, bail out */
+        return ret;
+    }
+
+    /* Validate memory placement and alignment for the guest.  */
+    shmlba = target_shmlba(cpu_env);
+    if (shmaddr & (shmlba - 1)) {
+        if (shmflg & SHM_RND) {
+            shmaddr &= ~(shmlba - 1);
+        } else {
+            return -TARGET_EINVAL;
+        }
+    }
+    if (!guest_range_valid(shmaddr, shm_info.shm_segsz)) {
+        return -TARGET_EINVAL;
+    }
+
+    mmap_lock();
+
+    if (shmaddr) {
+        host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
+    } else {
+        /* In order to use the host shmat, we need to honor host SHMLBA.  */
+        abi_ulong mmap_start = mmap_find_vma(0, shm_info.shm_segsz,
+                                             MAX(SHMLBA, shmlba));
+        if (mmap_start == -1) {
+            errno = ENOMEM;
+            host_raddr = (void *)-1;
+        } else {
+            host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP);
+        }
+    }
+    if (host_raddr == (void *)-1) {
+        mmap_unlock();
+        return get_errno((intptr_t)host_raddr);
+    }
+
+    raddr = h2g((uintptr_t)host_raddr);
+    page_set_flags(raddr, raddr + shm_info.shm_segsz,
+                   PAGE_VALID | PAGE_READ |
+                   (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
+
+    for (i = 0; i < N_SHM_REGIONS; i++) {
+        if (!shm_regions[i].in_use) {
+            shm_regions[i].in_use = true;
+            shm_regions[i].start = raddr;
+            shm_regions[i].size = shm_info.shm_segsz;
+            break;
+        }
+    }
+    mmap_unlock();
+    return raddr;
+}
+
+SYSCALL_IMPL(shmctl)
+{
+    int shmid = arg1;
+    int cmd = arg2 & 0xff;
+    abi_ulong buf = arg3;
+    struct shmid_ds dsarg;
+    struct shminfo shminfo;
+    struct shm_info shm_info;
+    abi_long ret;
+
+    switch (cmd) {
+    case IPC_STAT:
+    case IPC_SET:
+    case SHM_STAT:
+        if (target_to_host_shmid_ds(&dsarg, buf)) {
+            return -TARGET_EFAULT;
+        }
+        ret = get_errno(shmctl(shmid, cmd, &dsarg));
+        if (!is_error(ret) && host_to_target_shmid_ds(buf, &dsarg)) {
+            return -TARGET_EFAULT;
+        }
+        return ret;
+
+    case IPC_INFO:
+        ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
+        if (!is_error(ret) && host_to_target_shminfo(buf, &shminfo)) {
+            return -TARGET_EFAULT;
+        }
+        return ret;
+
+    case SHM_INFO:
+        ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
+        if (!is_error(ret) && host_to_target_shm_info(buf, &shm_info)) {
+            return -TARGET_EFAULT;
+        }
+        return ret;
+
+    case IPC_RMID:
+    case SHM_LOCK:
+    case SHM_UNLOCK:
+        return get_errno(shmctl(shmid, cmd, NULL));
+
+    default:
+        return -TARGET_EINVAL;
+    }
+}
+
+SYSCALL_IMPL(shmdt)
+{
+    abi_ulong shmaddr = arg1;
+    abi_long ret;
+    int i;
+
+    mmap_lock();
+
+    for (i = 0; i < N_SHM_REGIONS; ++i) {
+        if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
+            shm_regions[i].in_use = false;
+            page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
+            break;
+        }
+    }
+    ret = get_errno(shmdt(g2h(shmaddr)));
+
+    mmap_unlock();
+
+    return ret;
+}
+
+SYSCALL_IMPL(shmget)
+{
+    return get_errno(shmget(arg1, arg2, arg3));
+}
+
+#ifdef TARGET_NR_ipc
+/*
+ * This differs from normal shmat in returning the result via a pointer.
+ * Here we have shifted that pointer to arg4.
+ */
+SYSCALL_IMPL(ipc_shmat)
+{
+    abi_long ret = impl_shmat(cpu_env, arg1, arg2, arg3, 0, 0, 0);
+
+    if (is_error(ret)) {
+        return ret;
+    }
+    if (put_user_ual(ret, arg4)) {
+        return -TARGET_EFAULT;
+    }
+    return 0;
+}
+
+static const SyscallDef def_ipc_shmat = {
+    .name = "shmat",
+    .impl = impl_ipc_shmat,
+    .arg_type = { ARG_DEC, ARG_PTR, ARG_HEX, ARG_PTR },
+};
+
+/* These get defined later via syscall-defs.h.  */
+static const SyscallDef def_semop;
+static const SyscallDef def_semget;
+static const SyscallDef def_semctl;
+static const SyscallDef def_msgget;
+static const SyscallDef def_msgsnd;
+static const SyscallDef def_msgctl;
+static const SyscallDef def_msgrcv;
+static const SyscallDef def_shmdt;
+static const SyscallDef def_shmget;
+static const SyscallDef def_shmctl;
+
+/*
+ * Demultiplex the IPC syscall and shuffle the arguments around
+ * into the "normal" ordering.
+ */
+SYSCALL_ARGS(ipc)
+{
+    int call = extract32(in[0], 0, 16);
+    int version = extract32(in[0], 16, 16);
+    abi_long first = in[1];
+    abi_long second = in[2];
+    abi_long third = in[3];
+    abi_ulong ptr = in[4];
+    abi_long fifth = in[5];
+    abi_ulong atptr;
+
+    /* IPC_* and SHM_* command values are the same on all linux platforms */
+    switch (call) {
+    case IPCOP_semop:
+        out[0] = first;
+        out[1] = ptr;
+        out[2] = second;
+        return &def_semop;
+
+    case IPCOP_semget:
+        out[0] = first;
+        out[1] = second;
+        out[2] = third;
+        return &def_semget;
+
+    case IPCOP_semctl:
+        /*
+         * The semun argument to semctl is passed by value,
+         * so dereference the ptr argument.
+         */
+        if (get_user_ual(atptr, ptr)) {
+            errno = EFAULT;
+            return NULL;
+        }
+        out[0] = first;
+        out[1] = second;
+        out[2] = third;
+        out[3] = atptr;
+        return &def_semctl;
+
+    case IPCOP_msgget:
+        out[0] = first;
+        out[1] = second;
+        return &def_msgget;
+
+    case IPCOP_msgsnd:
+        out[0] = first;
+        out[1] = ptr;
+        out[2] = second;
+        out[3] = third;
+        return &def_msgsnd;
+
+    case IPCOP_msgctl:
+        out[0] = first;
+        out[1] = second;
+        out[2] = ptr;
+        return &def_msgctl;
+
+    case IPCOP_msgrcv:
+        if (version == 0) {
+            struct target_ipc_kludge {
+                abi_long msgp;
+                abi_long msgtyp;
+            } *tmp;
+
+            if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
+                errno = EFAULT;
+                return NULL;
+            }
+            out[0] = first;
+            out[1] = tswapal(tmp->msgp);
+            out[2] = second;
+            out[3] = tswapal(tmp->msgtyp);
+            out[4] = third;
+            unlock_user_struct(tmp, ptr, 0);
+        } else {
+            out[0] = first;
+            out[1] = ptr;
+            out[2] = second;
+            out[3] = fifth;
+            out[4] = third;
+        }
+        return &def_msgrcv;
+
+    case IPCOP_shmat:
+        if (version == 1) {
+            errno = EINVAL;
+            return NULL;
+        }
+        out[0] = first;
+        out[1] = ptr;
+        out[2] = second;
+        out[3] = third;
+        return &def_ipc_shmat;
+
+    case IPCOP_shmdt:
+        out[0] = ptr;
+        return &def_shmdt;
+
+    case IPCOP_shmget:
+        out[0] = first;
+        out[1] = second;
+        out[2] = third;
+        return &def_shmget;
+
+    case IPCOP_shmctl:
+        out[0] = first;
+        out[1] = second;
+        out[2] = ptr;
+        return &def_shmctl;
+
+    default:
+        /* Invalid syscall.  Continue to impl_ipc for logging.  */
+        return def;
+    }
+}
+
+SYSCALL_IMPL(ipc)
+{
+    int call = extract32(arg1, 0, 16);
+    int version = extract32(arg1, 16, 16);
+
+    gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
+    return -TARGET_ENOSYS;
+}
+#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index c49f8aebd2..ca345ffb4c 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -763,43 +763,6 @@ safe_syscall2(int, nanosleep, const struct timespec *, req,
 safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags,
               const struct timespec *, req, struct timespec *, rem)
 #endif
-#ifdef __NR_msgsnd
-safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz,
-              int, flags)
-safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz,
-              long, msgtype, int, flags)
-safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops,
-              unsigned, nsops, const struct timespec *, timeout)
-#else
-/* This host kernel architecture uses a single ipc syscall; fake up
- * wrappers for the sub-operations to hide this implementation detail.
- * Annoyingly we can't include linux/ipc.h to get the constant definitions
- * for the call parameter because some structs in there conflict with the
- * sys/ipc.h ones. So we just define them here, and rely on them being
- * the same for all host architectures.
- */
-#define Q_SEMTIMEDOP 4
-#define Q_MSGSND 11
-#define Q_MSGRCV 12
-#define Q_IPCCALL(VERSION, OP) ((VERSION) << 16 | (OP))
-
-safe_syscall6(int, ipc, int, call, long, first, long, second, long, third,
-              void *, ptr, long, fifth)
-static int safe_msgsnd(int msgid, const void *msgp, size_t sz, int flags)
-{
-    return safe_ipc(Q_IPCCALL(0, Q_MSGSND), msgid, sz, flags, (void *)msgp, 0);
-}
-static int safe_msgrcv(int msgid, void *msgp, size_t sz, long type, int flags)
-{
-    return safe_ipc(Q_IPCCALL(1, Q_MSGRCV), msgid, sz, flags, msgp, type);
-}
-static int safe_semtimedop(int semid, struct sembuf *tsops, unsigned nsops,
-                           const struct timespec *timeout)
-{
-    return safe_ipc(Q_IPCCALL(0, Q_SEMTIMEDOP), semid, nsops, 0, tsops,
-                    (long)timeout);
-}
-#endif
 #if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
 safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr,
               size_t, len, unsigned, prio, const struct timespec *, timeout)
@@ -3178,891 +3141,6 @@ static abi_long do_socketcall(int num, abi_ulong vptr)
 }
 #endif
 
-#define N_SHM_REGIONS	32
-
-static struct shm_region {
-    abi_ulong start;
-    abi_ulong size;
-    bool in_use;
-} shm_regions[N_SHM_REGIONS];
-
-#ifndef TARGET_SEMID64_DS
-/* asm-generic version of this struct */
-struct target_semid64_ds
-{
-  struct target_ipc_perm sem_perm;
-  abi_ulong sem_otime;
-#if TARGET_ABI_BITS == 32
-  abi_ulong __unused1;
-#endif
-  abi_ulong sem_ctime;
-#if TARGET_ABI_BITS == 32
-  abi_ulong __unused2;
-#endif
-  abi_ulong sem_nsems;
-  abi_ulong __unused3;
-  abi_ulong __unused4;
-};
-#endif
-
-static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
-                                               abi_ulong target_addr)
-{
-    struct target_ipc_perm *target_ip;
-    struct target_semid64_ds *target_sd;
-
-    if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
-        return -TARGET_EFAULT;
-    target_ip = &(target_sd->sem_perm);
-    host_ip->__key = tswap32(target_ip->__key);
-    host_ip->uid = tswap32(target_ip->uid);
-    host_ip->gid = tswap32(target_ip->gid);
-    host_ip->cuid = tswap32(target_ip->cuid);
-    host_ip->cgid = tswap32(target_ip->cgid);
-#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
-    host_ip->mode = tswap32(target_ip->mode);
-#else
-    host_ip->mode = tswap16(target_ip->mode);
-#endif
-#if defined(TARGET_PPC)
-    host_ip->__seq = tswap32(target_ip->__seq);
-#else
-    host_ip->__seq = tswap16(target_ip->__seq);
-#endif
-    unlock_user_struct(target_sd, target_addr, 0);
-    return 0;
-}
-
-static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
-                                               struct ipc_perm *host_ip)
-{
-    struct target_ipc_perm *target_ip;
-    struct target_semid64_ds *target_sd;
-
-    if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
-        return -TARGET_EFAULT;
-    target_ip = &(target_sd->sem_perm);
-    target_ip->__key = tswap32(host_ip->__key);
-    target_ip->uid = tswap32(host_ip->uid);
-    target_ip->gid = tswap32(host_ip->gid);
-    target_ip->cuid = tswap32(host_ip->cuid);
-    target_ip->cgid = tswap32(host_ip->cgid);
-#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
-    target_ip->mode = tswap32(host_ip->mode);
-#else
-    target_ip->mode = tswap16(host_ip->mode);
-#endif
-#if defined(TARGET_PPC)
-    target_ip->__seq = tswap32(host_ip->__seq);
-#else
-    target_ip->__seq = tswap16(host_ip->__seq);
-#endif
-    unlock_user_struct(target_sd, target_addr, 1);
-    return 0;
-}
-
-static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
-                                               abi_ulong target_addr)
-{
-    struct target_semid64_ds *target_sd;
-
-    if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
-        return -TARGET_EFAULT;
-    if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
-        return -TARGET_EFAULT;
-    host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
-    host_sd->sem_otime = tswapal(target_sd->sem_otime);
-    host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
-    unlock_user_struct(target_sd, target_addr, 0);
-    return 0;
-}
-
-static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
-                                               struct semid_ds *host_sd)
-{
-    struct target_semid64_ds *target_sd;
-
-    if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
-        return -TARGET_EFAULT;
-    if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
-        return -TARGET_EFAULT;
-    target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
-    target_sd->sem_otime = tswapal(host_sd->sem_otime);
-    target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
-    unlock_user_struct(target_sd, target_addr, 1);
-    return 0;
-}
-
-struct target_seminfo {
-    int semmap;
-    int semmni;
-    int semmns;
-    int semmnu;
-    int semmsl;
-    int semopm;
-    int semume;
-    int semusz;
-    int semvmx;
-    int semaem;
-};
-
-static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
-                                              struct seminfo *host_seminfo)
-{
-    struct target_seminfo *target_seminfo;
-    if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
-        return -TARGET_EFAULT;
-    __put_user(host_seminfo->semmap, &target_seminfo->semmap);
-    __put_user(host_seminfo->semmni, &target_seminfo->semmni);
-    __put_user(host_seminfo->semmns, &target_seminfo->semmns);
-    __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
-    __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
-    __put_user(host_seminfo->semopm, &target_seminfo->semopm);
-    __put_user(host_seminfo->semume, &target_seminfo->semume);
-    __put_user(host_seminfo->semusz, &target_seminfo->semusz);
-    __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
-    __put_user(host_seminfo->semaem, &target_seminfo->semaem);
-    unlock_user_struct(target_seminfo, target_addr, 1);
-    return 0;
-}
-
-union semun {
-	int val;
-	struct semid_ds *buf;
-	unsigned short *array;
-	struct seminfo *__buf;
-};
-
-union target_semun {
-	int val;
-	abi_ulong buf;
-	abi_ulong array;
-	abi_ulong __buf;
-};
-
-static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
-                                               abi_ulong target_addr)
-{
-    int nsems;
-    unsigned short *array;
-    union semun semun;
-    struct semid_ds semid_ds;
-    int i, ret;
-
-    semun.buf = &semid_ds;
-
-    ret = semctl(semid, 0, IPC_STAT, semun);
-    if (ret == -1)
-        return get_errno(ret);
-
-    nsems = semid_ds.sem_nsems;
-
-    *host_array = g_try_new(unsigned short, nsems);
-    if (!*host_array) {
-        return -TARGET_ENOMEM;
-    }
-    array = lock_user(VERIFY_READ, target_addr,
-                      nsems*sizeof(unsigned short), 1);
-    if (!array) {
-        g_free(*host_array);
-        return -TARGET_EFAULT;
-    }
-
-    for(i=0; i<nsems; i++) {
-        __get_user((*host_array)[i], &array[i]);
-    }
-    unlock_user(array, target_addr, 0);
-
-    return 0;
-}
-
-static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
-                                               unsigned short **host_array)
-{
-    int nsems;
-    unsigned short *array;
-    union semun semun;
-    struct semid_ds semid_ds;
-    int i, ret;
-
-    semun.buf = &semid_ds;
-
-    ret = semctl(semid, 0, IPC_STAT, semun);
-    if (ret == -1)
-        return get_errno(ret);
-
-    nsems = semid_ds.sem_nsems;
-
-    array = lock_user(VERIFY_WRITE, target_addr,
-                      nsems*sizeof(unsigned short), 0);
-    if (!array)
-        return -TARGET_EFAULT;
-
-    for(i=0; i<nsems; i++) {
-        __put_user((*host_array)[i], &array[i]);
-    }
-    g_free(*host_array);
-    unlock_user(array, target_addr, 1);
-
-    return 0;
-}
-
-static inline abi_long do_semctl(int semid, int semnum, int cmd,
-                                 abi_ulong target_arg)
-{
-    union target_semun target_su = { .buf = target_arg };
-    union semun arg;
-    struct semid_ds dsarg;
-    unsigned short *array = NULL;
-    struct seminfo seminfo;
-    abi_long ret = -TARGET_EINVAL;
-    abi_long err;
-    cmd &= 0xff;
-
-    switch( cmd ) {
-	case GETVAL:
-	case SETVAL:
-            /* In 64 bit cross-endian situations, we will erroneously pick up
-             * the wrong half of the union for the "val" element.  To rectify
-             * this, the entire 8-byte structure is byteswapped, followed by
-	     * a swap of the 4 byte val field. In other cases, the data is
-	     * already in proper host byte order. */
-	    if (sizeof(target_su.val) != (sizeof(target_su.buf))) {
-		target_su.buf = tswapal(target_su.buf);
-		arg.val = tswap32(target_su.val);
-	    } else {
-		arg.val = target_su.val;
-	    }
-            ret = get_errno(semctl(semid, semnum, cmd, arg));
-            break;
-	case GETALL:
-	case SETALL:
-            err = target_to_host_semarray(semid, &array, target_su.array);
-            if (err)
-                return err;
-            arg.array = array;
-            ret = get_errno(semctl(semid, semnum, cmd, arg));
-            err = host_to_target_semarray(semid, target_su.array, &array);
-            if (err)
-                return err;
-            break;
-	case IPC_STAT:
-	case IPC_SET:
-	case SEM_STAT:
-            err = target_to_host_semid_ds(&dsarg, target_su.buf);
-            if (err)
-                return err;
-            arg.buf = &dsarg;
-            ret = get_errno(semctl(semid, semnum, cmd, arg));
-            err = host_to_target_semid_ds(target_su.buf, &dsarg);
-            if (err)
-                return err;
-            break;
-	case IPC_INFO:
-	case SEM_INFO:
-            arg.__buf = &seminfo;
-            ret = get_errno(semctl(semid, semnum, cmd, arg));
-            err = host_to_target_seminfo(target_su.__buf, &seminfo);
-            if (err)
-                return err;
-            break;
-	case IPC_RMID:
-	case GETPID:
-	case GETNCNT:
-	case GETZCNT:
-            ret = get_errno(semctl(semid, semnum, cmd, NULL));
-            break;
-    }
-
-    return ret;
-}
-
-struct target_sembuf {
-    unsigned short sem_num;
-    short sem_op;
-    short sem_flg;
-};
-
-static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
-                                             abi_ulong target_addr,
-                                             unsigned nsops)
-{
-    struct target_sembuf *target_sembuf;
-    int i;
-
-    target_sembuf = lock_user(VERIFY_READ, target_addr,
-                              nsops*sizeof(struct target_sembuf), 1);
-    if (!target_sembuf)
-        return -TARGET_EFAULT;
-
-    for(i=0; i<nsops; i++) {
-        __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
-        __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
-        __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
-    }
-
-    unlock_user(target_sembuf, target_addr, 0);
-
-    return 0;
-}
-
-static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
-{
-    struct sembuf sops[nsops];
-
-    if (target_to_host_sembuf(sops, ptr, nsops))
-        return -TARGET_EFAULT;
-
-    return get_errno(safe_semtimedop(semid, sops, nsops, NULL));
-}
-
-struct target_msqid_ds
-{
-    struct target_ipc_perm msg_perm;
-    abi_ulong msg_stime;
-#if TARGET_ABI_BITS == 32
-    abi_ulong __unused1;
-#endif
-    abi_ulong msg_rtime;
-#if TARGET_ABI_BITS == 32
-    abi_ulong __unused2;
-#endif
-    abi_ulong msg_ctime;
-#if TARGET_ABI_BITS == 32
-    abi_ulong __unused3;
-#endif
-    abi_ulong __msg_cbytes;
-    abi_ulong msg_qnum;
-    abi_ulong msg_qbytes;
-    abi_ulong msg_lspid;
-    abi_ulong msg_lrpid;
-    abi_ulong __unused4;
-    abi_ulong __unused5;
-};
-
-static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
-                                               abi_ulong target_addr)
-{
-    struct target_msqid_ds *target_md;
-
-    if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
-        return -TARGET_EFAULT;
-    if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
-        return -TARGET_EFAULT;
-    host_md->msg_stime = tswapal(target_md->msg_stime);
-    host_md->msg_rtime = tswapal(target_md->msg_rtime);
-    host_md->msg_ctime = tswapal(target_md->msg_ctime);
-    host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes);
-    host_md->msg_qnum = tswapal(target_md->msg_qnum);
-    host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
-    host_md->msg_lspid = tswapal(target_md->msg_lspid);
-    host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
-    unlock_user_struct(target_md, target_addr, 0);
-    return 0;
-}
-
-static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
-                                               struct msqid_ds *host_md)
-{
-    struct target_msqid_ds *target_md;
-
-    if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
-        return -TARGET_EFAULT;
-    if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
-        return -TARGET_EFAULT;
-    target_md->msg_stime = tswapal(host_md->msg_stime);
-    target_md->msg_rtime = tswapal(host_md->msg_rtime);
-    target_md->msg_ctime = tswapal(host_md->msg_ctime);
-    target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes);
-    target_md->msg_qnum = tswapal(host_md->msg_qnum);
-    target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
-    target_md->msg_lspid = tswapal(host_md->msg_lspid);
-    target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
-    unlock_user_struct(target_md, target_addr, 1);
-    return 0;
-}
-
-struct target_msginfo {
-    int msgpool;
-    int msgmap;
-    int msgmax;
-    int msgmnb;
-    int msgmni;
-    int msgssz;
-    int msgtql;
-    unsigned short int msgseg;
-};
-
-static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
-                                              struct msginfo *host_msginfo)
-{
-    struct target_msginfo *target_msginfo;
-    if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
-        return -TARGET_EFAULT;
-    __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
-    __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
-    __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
-    __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
-    __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
-    __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
-    __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
-    __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
-    unlock_user_struct(target_msginfo, target_addr, 1);
-    return 0;
-}
-
-static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
-{
-    struct msqid_ds dsarg;
-    struct msginfo msginfo;
-    abi_long ret = -TARGET_EINVAL;
-
-    cmd &= 0xff;
-
-    switch (cmd) {
-    case IPC_STAT:
-    case IPC_SET:
-    case MSG_STAT:
-        if (target_to_host_msqid_ds(&dsarg,ptr))
-            return -TARGET_EFAULT;
-        ret = get_errno(msgctl(msgid, cmd, &dsarg));
-        if (host_to_target_msqid_ds(ptr,&dsarg))
-            return -TARGET_EFAULT;
-        break;
-    case IPC_RMID:
-        ret = get_errno(msgctl(msgid, cmd, NULL));
-        break;
-    case IPC_INFO:
-    case MSG_INFO:
-        ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
-        if (host_to_target_msginfo(ptr, &msginfo))
-            return -TARGET_EFAULT;
-        break;
-    }
-
-    return ret;
-}
-
-struct target_msgbuf {
-    abi_long mtype;
-    char	mtext[1];
-};
-
-static inline abi_long do_msgsnd(int msqid, abi_long msgp,
-                                 ssize_t msgsz, int msgflg)
-{
-    struct target_msgbuf *target_mb;
-    struct msgbuf *host_mb;
-    abi_long ret = 0;
-
-    if (msgsz < 0) {
-        return -TARGET_EINVAL;
-    }
-
-    if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
-        return -TARGET_EFAULT;
-    host_mb = g_try_malloc(msgsz + sizeof(long));
-    if (!host_mb) {
-        unlock_user_struct(target_mb, msgp, 0);
-        return -TARGET_ENOMEM;
-    }
-    host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
-    memcpy(host_mb->mtext, target_mb->mtext, msgsz);
-    ret = get_errno(safe_msgsnd(msqid, host_mb, msgsz, msgflg));
-    g_free(host_mb);
-    unlock_user_struct(target_mb, msgp, 0);
-
-    return ret;
-}
-
-static inline abi_long do_msgrcv(int msqid, abi_long msgp,
-                                 ssize_t msgsz, abi_long msgtyp,
-                                 int msgflg)
-{
-    struct target_msgbuf *target_mb;
-    char *target_mtext;
-    struct msgbuf *host_mb;
-    abi_long ret = 0;
-
-    if (msgsz < 0) {
-        return -TARGET_EINVAL;
-    }
-
-    if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
-        return -TARGET_EFAULT;
-
-    host_mb = g_try_malloc(msgsz + sizeof(long));
-    if (!host_mb) {
-        ret = -TARGET_ENOMEM;
-        goto end;
-    }
-    ret = get_errno(safe_msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
-
-    if (ret > 0) {
-        abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
-        target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
-        if (!target_mtext) {
-            ret = -TARGET_EFAULT;
-            goto end;
-        }
-        memcpy(target_mb->mtext, host_mb->mtext, ret);
-        unlock_user(target_mtext, target_mtext_addr, ret);
-    }
-
-    target_mb->mtype = tswapal(host_mb->mtype);
-
-end:
-    if (target_mb)
-        unlock_user_struct(target_mb, msgp, 1);
-    g_free(host_mb);
-    return ret;
-}
-
-static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
-                                               abi_ulong target_addr)
-{
-    struct target_shmid_ds *target_sd;
-
-    if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
-        return -TARGET_EFAULT;
-    if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
-        return -TARGET_EFAULT;
-    __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
-    __get_user(host_sd->shm_atime, &target_sd->shm_atime);
-    __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
-    __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
-    __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
-    __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
-    __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
-    unlock_user_struct(target_sd, target_addr, 0);
-    return 0;
-}
-
-static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
-                                               struct shmid_ds *host_sd)
-{
-    struct target_shmid_ds *target_sd;
-
-    if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
-        return -TARGET_EFAULT;
-    if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
-        return -TARGET_EFAULT;
-    __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
-    __put_user(host_sd->shm_atime, &target_sd->shm_atime);
-    __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
-    __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
-    __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
-    __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
-    __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
-    unlock_user_struct(target_sd, target_addr, 1);
-    return 0;
-}
-
-struct  target_shminfo {
-    abi_ulong shmmax;
-    abi_ulong shmmin;
-    abi_ulong shmmni;
-    abi_ulong shmseg;
-    abi_ulong shmall;
-};
-
-static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
-                                              struct shminfo *host_shminfo)
-{
-    struct target_shminfo *target_shminfo;
-    if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
-        return -TARGET_EFAULT;
-    __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
-    __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
-    __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
-    __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
-    __put_user(host_shminfo->shmall, &target_shminfo->shmall);
-    unlock_user_struct(target_shminfo, target_addr, 1);
-    return 0;
-}
-
-struct target_shm_info {
-    int used_ids;
-    abi_ulong shm_tot;
-    abi_ulong shm_rss;
-    abi_ulong shm_swp;
-    abi_ulong swap_attempts;
-    abi_ulong swap_successes;
-};
-
-static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
-                                               struct shm_info *host_shm_info)
-{
-    struct target_shm_info *target_shm_info;
-    if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
-        return -TARGET_EFAULT;
-    __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
-    __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
-    __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
-    __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
-    __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
-    __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
-    unlock_user_struct(target_shm_info, target_addr, 1);
-    return 0;
-}
-
-static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
-{
-    struct shmid_ds dsarg;
-    struct shminfo shminfo;
-    struct shm_info shm_info;
-    abi_long ret = -TARGET_EINVAL;
-
-    cmd &= 0xff;
-
-    switch(cmd) {
-    case IPC_STAT:
-    case IPC_SET:
-    case SHM_STAT:
-        if (target_to_host_shmid_ds(&dsarg, buf))
-            return -TARGET_EFAULT;
-        ret = get_errno(shmctl(shmid, cmd, &dsarg));
-        if (host_to_target_shmid_ds(buf, &dsarg))
-            return -TARGET_EFAULT;
-        break;
-    case IPC_INFO:
-        ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
-        if (host_to_target_shminfo(buf, &shminfo))
-            return -TARGET_EFAULT;
-        break;
-    case SHM_INFO:
-        ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
-        if (host_to_target_shm_info(buf, &shm_info))
-            return -TARGET_EFAULT;
-        break;
-    case IPC_RMID:
-    case SHM_LOCK:
-    case SHM_UNLOCK:
-        ret = get_errno(shmctl(shmid, cmd, NULL));
-        break;
-    }
-
-    return ret;
-}
-
-#ifndef TARGET_FORCE_SHMLBA
-/* For most architectures, SHMLBA is the same as the page size;
- * some architectures have larger values, in which case they should
- * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function.
- * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA
- * and defining its own value for SHMLBA.
- *
- * The kernel also permits SHMLBA to be set by the architecture to a
- * value larger than the page size without setting __ARCH_FORCE_SHMLBA;
- * this means that addresses are rounded to the large size if
- * SHM_RND is set but addresses not aligned to that size are not rejected
- * as long as they are at least page-aligned. Since the only architecture
- * which uses this is ia64 this code doesn't provide for that oddity.
- */
-static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
-{
-    return TARGET_PAGE_SIZE;
-}
-#endif
-
-static inline abi_ulong do_shmat(CPUArchState *cpu_env,
-                                 int shmid, abi_ulong shmaddr, int shmflg)
-{
-    abi_long raddr;
-    void *host_raddr;
-    struct shmid_ds shm_info;
-    int i,ret;
-    abi_ulong shmlba;
-
-    /* find out the length of the shared memory segment */
-    ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
-    if (is_error(ret)) {
-        /* can't get length, bail out */
-        return ret;
-    }
-
-    shmlba = target_shmlba(cpu_env);
-
-    if (shmaddr & (shmlba - 1)) {
-        if (shmflg & SHM_RND) {
-            shmaddr &= ~(shmlba - 1);
-        } else {
-            return -TARGET_EINVAL;
-        }
-    }
-    if (!guest_range_valid(shmaddr, shm_info.shm_segsz)) {
-        return -TARGET_EINVAL;
-    }
-
-    mmap_lock();
-
-    if (shmaddr)
-        host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
-    else {
-        abi_ulong mmap_start;
-
-        /* In order to use the host shmat, we need to honor host SHMLBA.  */
-        mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
-
-        if (mmap_start == -1) {
-            errno = ENOMEM;
-            host_raddr = (void *)-1;
-        } else
-            host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP);
-    }
-
-    if (host_raddr == (void *)-1) {
-        mmap_unlock();
-        return get_errno((long)host_raddr);
-    }
-    raddr=h2g((unsigned long)host_raddr);
-
-    page_set_flags(raddr, raddr + shm_info.shm_segsz,
-                   PAGE_VALID | PAGE_READ |
-                   ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
-
-    for (i = 0; i < N_SHM_REGIONS; i++) {
-        if (!shm_regions[i].in_use) {
-            shm_regions[i].in_use = true;
-            shm_regions[i].start = raddr;
-            shm_regions[i].size = shm_info.shm_segsz;
-            break;
-        }
-    }
-
-    mmap_unlock();
-    return raddr;
-
-}
-
-static inline abi_long do_shmdt(abi_ulong shmaddr)
-{
-    int i;
-    abi_long rv;
-
-    mmap_lock();
-
-    for (i = 0; i < N_SHM_REGIONS; ++i) {
-        if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
-            shm_regions[i].in_use = false;
-            page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
-            break;
-        }
-    }
-    rv = get_errno(shmdt(g2h(shmaddr)));
-
-    mmap_unlock();
-
-    return rv;
-}
-
-#ifdef TARGET_NR_ipc
-/* ??? This only works with linear mappings.  */
-/* do_ipc() must return target values and target errnos. */
-static abi_long do_ipc(CPUArchState *cpu_env,
-                       unsigned int call, abi_long first,
-                       abi_long second, abi_long third,
-                       abi_long ptr, abi_long fifth)
-{
-    int version;
-    abi_long ret = 0;
-
-    version = call >> 16;
-    call &= 0xffff;
-
-    switch (call) {
-    case IPCOP_semop:
-        ret = do_semop(first, ptr, second);
-        break;
-
-    case IPCOP_semget:
-        ret = get_errno(semget(first, second, third));
-        break;
-
-    case IPCOP_semctl: {
-        /* The semun argument to semctl is passed by value, so dereference the
-         * ptr argument. */
-        abi_ulong atptr;
-        get_user_ual(atptr, ptr);
-        ret = do_semctl(first, second, third, atptr);
-        break;
-    }
-
-    case IPCOP_msgget:
-        ret = get_errno(msgget(first, second));
-        break;
-
-    case IPCOP_msgsnd:
-        ret = do_msgsnd(first, ptr, second, third);
-        break;
-
-    case IPCOP_msgctl:
-        ret = do_msgctl(first, second, ptr);
-        break;
-
-    case IPCOP_msgrcv:
-        switch (version) {
-        case 0:
-            {
-                struct target_ipc_kludge {
-                    abi_long msgp;
-                    abi_long msgtyp;
-                } *tmp;
-
-                if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
-                    ret = -TARGET_EFAULT;
-                    break;
-                }
-
-                ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third);
-
-                unlock_user_struct(tmp, ptr, 0);
-                break;
-            }
-        default:
-            ret = do_msgrcv(first, ptr, second, fifth, third);
-        }
-        break;
-
-    case IPCOP_shmat:
-        switch (version) {
-        default:
-        {
-            abi_ulong raddr;
-            raddr = do_shmat(cpu_env, first, ptr, second);
-            if (is_error(raddr))
-                return get_errno(raddr);
-            if (put_user_ual(raddr, third))
-                return -TARGET_EFAULT;
-            break;
-        }
-        case 1:
-            ret = -TARGET_EINVAL;
-            break;
-        }
-	break;
-    case IPCOP_shmdt:
-        ret = do_shmdt(ptr);
-	break;
-
-    case IPCOP_shmget:
-	/* IPC_* flag values are the same on all linux platforms */
-	ret = get_errno(shmget(first, second, third));
-	break;
-
-	/* IPC_* and SHM_* command values are the same on all linux platforms */
-    case IPCOP_shmctl:
-        ret = do_shmctl(first, second, ptr);
-        break;
-    default:
-	gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
-	ret = -TARGET_ENOSYS;
-	break;
-    }
-    return ret;
-}
-#endif
-
 /* kernel structure types definitions */
 
 #define STRUCT(name, ...) STRUCT_ ## name,
@@ -8451,54 +7529,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
             }
         }
         return ret;
-#ifdef TARGET_NR_ipc
-    case TARGET_NR_ipc:
-        return do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
-#endif
-#ifdef TARGET_NR_semget
-    case TARGET_NR_semget:
-        return get_errno(semget(arg1, arg2, arg3));
-#endif
-#ifdef TARGET_NR_semop
-    case TARGET_NR_semop:
-        return do_semop(arg1, arg2, arg3);
-#endif
-#ifdef TARGET_NR_semctl
-    case TARGET_NR_semctl:
-        return do_semctl(arg1, arg2, arg3, arg4);
-#endif
-#ifdef TARGET_NR_msgctl
-    case TARGET_NR_msgctl:
-        return do_msgctl(arg1, arg2, arg3);
-#endif
-#ifdef TARGET_NR_msgget
-    case TARGET_NR_msgget:
-        return get_errno(msgget(arg1, arg2));
-#endif
-#ifdef TARGET_NR_msgrcv
-    case TARGET_NR_msgrcv:
-        return do_msgrcv(arg1, arg2, arg3, arg4, arg5);
-#endif
-#ifdef TARGET_NR_msgsnd
-    case TARGET_NR_msgsnd:
-        return do_msgsnd(arg1, arg2, arg3, arg4);
-#endif
-#ifdef TARGET_NR_shmget
-    case TARGET_NR_shmget:
-        return get_errno(shmget(arg1, arg2, arg3));
-#endif
-#ifdef TARGET_NR_shmctl
-    case TARGET_NR_shmctl:
-        return do_shmctl(arg1, arg2, arg3);
-#endif
-#ifdef TARGET_NR_shmat
-    case TARGET_NR_shmat:
-        return do_shmat(cpu_env, arg1, arg2, arg3);
-#endif
-#ifdef TARGET_NR_shmdt
-    case TARGET_NR_shmdt:
-        return do_shmdt(arg1);
-#endif
     case TARGET_NR_fsync:
         return get_errno(fsync(arg1));
     case TARGET_NR_clone:
@@ -11061,6 +10091,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
                                 int64_t arg5, int64_t arg6)
 
 #include "syscall-file.inc.c"
+#include "syscall-ipc.inc.c"
 
 #undef SYSCALL_IMPL
 #undef SYSCALL_ARGS
@@ -11094,6 +10125,7 @@ static const SyscallDef *syscall_table(int num)
 #define SYSCALL_DEF(NAME, ...)  case TARGET_NR_##NAME: return &def_##NAME
 #define SYSCALL_DEF_ARGS(NAME, ...)  SYSCALL_DEF(NAME)
 #define SYSCALL_DEF_FULL(NAME, ...)  SYSCALL_DEF(NAME)
+#define SYSCALL_TABLE
 
     switch (num) {
 #include "syscall-defs.h"
@@ -11103,6 +10135,7 @@ static const SyscallDef *syscall_table(int num)
 #undef SYSCALL_DEF
 #undef SYSCALL_DEF_ARGS
 #undef SYSCALL_DEF_FULL
+#undef SYSCALL_TABLE
 }
 
 abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
diff --git a/linux-user/strace.list b/linux-user/strace.list
index bf239cb9a3..f99bd57c09 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -452,9 +452,6 @@
 #ifdef TARGET_NR_io_submit
 { TARGET_NR_io_submit, "io_submit" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_ipc
-{ TARGET_NR_ipc, "ipc" , NULL, print_ipc, NULL },
-#endif
 #ifdef TARGET_NR_kcmp
 { TARGET_NR_kcmp, "kcmp" , NULL, NULL, NULL },
 #endif
@@ -608,18 +605,6 @@
 #ifdef TARGET_NR_mremap
 { TARGET_NR_mremap, "mremap" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_msgctl
-{ TARGET_NR_msgctl, "msgctl" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_msgget
-{ TARGET_NR_msgget, "msgget" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_msgrcv
-{ TARGET_NR_msgrcv, "msgrcv" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_msgsnd
-{ TARGET_NR_msgsnd, "msgsnd" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_msync
 { TARGET_NR_msync, "msync" , NULL, NULL, NULL },
 #endif
@@ -917,9 +902,6 @@
 #ifdef TARGET_NR_osf_settimeofday
 { TARGET_NR_osf_settimeofday, "osf_settimeofday" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_osf_shmat
-{ TARGET_NR_osf_shmat, "osf_shmat" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_osf_signal
 { TARGET_NR_osf_signal, "osf_signal" , NULL, NULL, NULL },
 #endif
@@ -1184,18 +1166,6 @@
 #ifdef TARGET_NR_select
 { TARGET_NR_select, "select" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_semctl
-{ TARGET_NR_semctl, "semctl" , NULL, print_semctl, NULL },
-#endif
-#ifdef TARGET_NR_semget
-{ TARGET_NR_semget, "semget" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_semop
-{ TARGET_NR_semop, "semop" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_semtimedop
-{ TARGET_NR_semtimedop, "semtimedop" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_send
 { TARGET_NR_send, "send" , NULL, NULL, NULL },
 #endif
@@ -1323,18 +1293,6 @@
 #ifdef TARGET_NR_sgetmask
 { TARGET_NR_sgetmask, "sgetmask" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_shmat
-{ TARGET_NR_shmat, "shmat" , NULL, NULL, print_syscall_ret_addr },
-#endif
-#ifdef TARGET_NR_shmctl
-{ TARGET_NR_shmctl, "shmctl" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_shmdt
-{ TARGET_NR_shmdt, "shmdt" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_shmget
-{ TARGET_NR_shmget, "shmget" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_shutdown
 { TARGET_NR_shutdown, "shutdown" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 14/74] linux-user: Split out memory syscalls
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (12 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 13/74] linux-user: Split out ipc syscalls Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 15/74] linux-user: Split out exit Richard Henderson
                   ` (62 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

This includes mmap, mmap2, munmap, mlock, mlockall, munlock,
munlockall, mprotect, mremap, msync.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h    |  24 ++++++
 linux-user/syscall.h         |   2 +
 linux-user/strace.c          |  55 ++-----------
 linux-user/syscall-mem.inc.c | 154 +++++++++++++++++++++++++++++++++++
 linux-user/syscall.c         | 119 +--------------------------
 linux-user/strace.list       |  33 --------
 6 files changed, 189 insertions(+), 198 deletions(-)
 create mode 100644 linux-user/syscall-mem.inc.c

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 6d6349da01..88f433e998 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -20,6 +20,26 @@ SYSCALL_DEF(close, ARG_DEC);
 #ifdef TARGET_NR_ipc
 SYSCALL_DEF_ARGS(ipc, ARG_HEX, ARG_DEC, ARG_DEC, ARG_HEX, ARG_PTR, ARG_HEX);
 #endif
+SYSCALL_DEF(mlock, ARG_PTR, ARG_DEC);
+SYSCALL_DEF(mlockall, ARG_HEX);
+#ifdef TARGET_NR_mmap
+SYSCALL_DEF_FULL(mmap, .impl = impl_mmap,
+                 .args = args_mmap,
+                 .print_ret = print_syscall_ptr_ret,
+                 .arg_type = { ARG_PTR, ARG_DEC, ARG_MMAPPROT,
+                               ARG_MMAPFLAG, ARG_DEC, ARG_DEC });
+#endif
+#ifdef TARGET_NR_mmap2
+SYSCALL_DEF_FULL(mmap2, .impl = impl_mmap,
+                 .args = args_mmap2,
+                 .print_ret = print_syscall_ptr_ret,
+                 .arg_type = { ARG_PTR, ARG_DEC, ARG_MMAPPROT,
+                               ARG_MMAPFLAG, ARG_DEC, ARG_DEC64 });
+#endif
+SYSCALL_DEF(mprotect, ARG_PTR, ARG_DEC, ARG_MMAPPROT);
+SYSCALL_DEF_FULL(mremap, .impl = impl_mremap,
+                 .print_ret = print_syscall_ptr_ret,
+                 .arg_type = { ARG_PTR, ARG_DEC, ARG_DEC, ARG_HEX, ARG_PTR });
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_msgctl)
 SYSCALL_DEF(msgctl, ARG_DEC, ARG_DEC, ARG_PTR);
 #endif
@@ -32,6 +52,10 @@ SYSCALL_DEF(msgrcv, ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC, ARG_HEX);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_msgsnd)
 SYSCALL_DEF(msgsnd, ARG_DEC, ARG_PTR, ARG_DEC, ARG_HEX);
 #endif
+SYSCALL_DEF(msync, ARG_PTR, ARG_DEC, ARG_HEX);
+SYSCALL_DEF(munlock, ARG_PTR, ARG_DEC);
+SYSCALL_DEF(munlockall);
+SYSCALL_DEF(munmap, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(name_to_handle_at,
             ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_PTR, ARG_ATFLAG);
 #ifdef TARGET_NR_open
diff --git a/linux-user/syscall.h b/linux-user/syscall.h
index 83f602f8e7..8175de4c31 100644
--- a/linux-user/syscall.h
+++ b/linux-user/syscall.h
@@ -58,6 +58,8 @@ typedef enum {
     /* These print as sets of flags.  */
     ARG_ATDIRFD,
     ARG_ATFLAG,
+    ARG_MMAPFLAG,
+    ARG_MMAPPROT,
     ARG_MODEFLAG,
     ARG_OPENFLAG,
 
diff --git a/linux-user/strace.c b/linux-user/strace.c
index e1c4859a95..a767227ac1 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -801,7 +801,7 @@ UNUSED static struct flags umount2_flags[] = {
     FLAG_END,
 };
 
-UNUSED static struct flags mmap_prot_flags[] = {
+static struct flags const mmap_prot_flags[] = {
     FLAG_GENERIC(PROT_NONE),
     FLAG_GENERIC(PROT_EXEC),
     FLAG_GENERIC(PROT_READ),
@@ -812,7 +812,7 @@ UNUSED static struct flags mmap_prot_flags[] = {
     FLAG_END,
 };
 
-UNUSED static struct flags mmap_flags[] = {
+static struct flags const mmap_flags[] = {
     FLAG_TARGET(MAP_SHARED),
     FLAG_TARGET(MAP_PRIVATE),
     FLAG_TARGET(MAP_ANONYMOUS),
@@ -2362,51 +2362,6 @@ print_utimensat(const struct syscallname *name,
 }
 #endif
 
-#if defined(TARGET_NR_mmap) || defined(TARGET_NR_mmap2)
-static void
-print_mmap(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_pointer(arg0, 0);
-    print_raw_param("%d", arg1, 0);
-    print_flags(mmap_prot_flags, arg2, 0);
-    print_flags(mmap_flags, arg3, 0);
-    print_raw_param("%d", arg4, 0);
-    print_raw_param("%#x", arg5, 1);
-    print_syscall_epilogue(name);
-}
-#define print_mmap2     print_mmap
-#endif
-
-#ifdef TARGET_NR_mprotect
-static void
-print_mprotect(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_pointer(arg0, 0);
-    print_raw_param("%d", arg1, 0);
-    print_flags(mmap_prot_flags, arg2, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
-#ifdef TARGET_NR_munmap
-static void
-print_munmap(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_pointer(arg0, 0);
-    print_raw_param("%d", arg1, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_futex
 static void print_futex_op(abi_long tflag, int last)
 {
@@ -2613,6 +2568,12 @@ static void print_syscall_def1(const SyscallDef *def, int64_t args[6])
         case ARG_ATFLAG:
             len = add_flags(b, rest, at_file_flags, arg, false);
             break;
+        case ARG_MMAPFLAG:
+            len = add_flags(b, rest, mmap_flags, arg, false);
+            break;
+        case ARG_MMAPPROT:
+            len = add_flags(b, rest, mmap_prot_flags, arg, false);
+            break;
         case ARG_MODEFLAG:
             len = add_flags(b, rest, mode_flags, arg, true);
             break;
diff --git a/linux-user/syscall-mem.inc.c b/linux-user/syscall-mem.inc.c
new file mode 100644
index 0000000000..d2ce0cb8cc
--- /dev/null
+++ b/linux-user/syscall-mem.inc.c
@@ -0,0 +1,154 @@
+/*
+ *  Linux memory-related syscalls
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+static bitmask_transtbl const mmap_flags_tbl[] = {
+    { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
+    { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
+    { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
+    { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS,
+      MAP_ANONYMOUS, MAP_ANONYMOUS },
+    { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN,
+      MAP_GROWSDOWN, MAP_GROWSDOWN },
+    { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE,
+      MAP_DENYWRITE, MAP_DENYWRITE },
+    { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE,
+      MAP_EXECUTABLE, MAP_EXECUTABLE },
+    { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
+    { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE,
+      MAP_NORESERVE, MAP_NORESERVE },
+    { TARGET_MAP_HUGETLB, TARGET_MAP_HUGETLB, MAP_HUGETLB, MAP_HUGETLB },
+    /*
+     * MAP_STACK had been ignored by the kernel for quite some time.
+     * Recognize it for the target insofar as we do not want to pass
+     * it through to the host.
+     */
+    { TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 },
+    { 0, 0, 0, 0 }
+};
+
+
+SYSCALL_IMPL(mlock)
+{
+    return get_errno(mlock(g2h(arg1), arg2));
+}
+
+SYSCALL_IMPL(mlockall)
+{
+    int host_flag = 0;
+    if (arg1 & TARGET_MLOCKALL_MCL_CURRENT) {
+        host_flag |= MCL_CURRENT;
+    }
+    if (arg1 & TARGET_MLOCKALL_MCL_FUTURE) {
+        host_flag |= MCL_FUTURE;
+    }
+    return get_errno(mlockall(host_flag));
+}
+
+#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
+    (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
+    defined(TARGET_M68K) || defined(TARGET_CRIS) || \
+    defined(TARGET_MICROBLAZE) || defined(TARGET_S390X)
+SYSCALL_ARGS(mmap)
+{
+    abi_ulong ptr = in[0];
+    abi_long *v = lock_user(VERIFY_READ, ptr, 6 * sizeof(abi_long), 1);
+    if (v == NULL) {
+        errno = EFAULT;
+        return NULL;
+    }
+    out[0] = tswapal(v[0]);
+    out[1] = tswapal(v[1]);
+    out[2] = tswapal(v[2]);
+    out[3] = tswapal(v[3]);
+    out[4] = tswapal(v[4]);
+    out[5] = tswapal(v[5]);
+    unlock_user(v, ptr, 0);
+    return def;
+}
+#else
+# define args_mmap NULL
+#endif
+
+SYSCALL_IMPL(mmap)
+{
+    int host_flags = target_to_host_bitmask(arg4, mmap_flags_tbl);
+    return get_errno(target_mmap(arg1, arg2, arg3, host_flags, arg5, arg6));
+}
+
+#ifdef TARGET_NR_mmap2
+/*
+ * Define mmap2 in terms of mmap.
+ * !!! Note that there is a fundamental problem here in that
+ * target_mmap has an offset parameter that is abi_ulong
+ * and not off_t.  This means that we cannot actually pass
+ * through a 64-bit file offset as intended.
+ */
+
+#ifndef MMAP_SHIFT
+# define MMAP_SHIFT 12
+#endif
+
+SYSCALL_ARGS(mmap2)
+{
+    /* We have already assigned out[0-4].  */
+    out[5] = (uint64_t)(abi_ulong)in[5] << MMAP_SHIFT;
+    return def;
+}
+#endif
+
+SYSCALL_IMPL(mprotect)
+{
+    CPUState *cpu = ENV_GET_CPU(cpu_env);
+    TaskState *ts = cpu->opaque;
+
+    /* Special hack to detect libc making the stack executable.  */
+    if ((arg3 & PROT_GROWSDOWN)
+        && arg1 >= ts->info->stack_limit
+        && arg1 <= ts->info->start_stack) {
+        arg3 &= ~PROT_GROWSDOWN;
+        arg2 = arg2 + arg1 - ts->info->stack_limit;
+        arg1 = ts->info->stack_limit;
+    }
+    return get_errno(target_mprotect(arg1, arg2, arg3));
+}
+
+SYSCALL_IMPL(mremap)
+{
+    return get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
+}
+
+SYSCALL_IMPL(msync)
+{
+    return get_errno(msync(g2h(arg1), arg2, arg3));
+}
+
+SYSCALL_IMPL(munlock)
+{
+    return get_errno(munlock(g2h(arg1), arg2));
+}
+
+SYSCALL_IMPL(munlockall)
+{
+    return get_errno(munlockall());
+}
+
+SYSCALL_IMPL(munmap)
+{
+    return get_errno(target_munmap(arg1, arg2));
+}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ca345ffb4c..876426dd9c 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4183,29 +4183,6 @@ static const StructEntry struct_termios_def = {
     .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
 };
 
-static bitmask_transtbl mmap_flags_tbl[] = {
-    { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
-    { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
-    { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
-    { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS,
-      MAP_ANONYMOUS, MAP_ANONYMOUS },
-    { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN,
-      MAP_GROWSDOWN, MAP_GROWSDOWN },
-    { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE,
-      MAP_DENYWRITE, MAP_DENYWRITE },
-    { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE,
-      MAP_EXECUTABLE, MAP_EXECUTABLE },
-    { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
-    { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE,
-      MAP_NORESERVE, MAP_NORESERVE },
-    { TARGET_MAP_HUGETLB, TARGET_MAP_HUGETLB, MAP_HUGETLB, MAP_HUGETLB },
-    /* MAP_STACK had been ignored by the kernel for quite some time.
-       Recognize it for the target insofar as we do not want to pass
-       it through to the host.  */
-    { TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 },
-    { 0, 0, 0, 0 }
-};
-
 #if defined(TARGET_I386)
 
 /* NOTE: there is really one LDT for all the threads */
@@ -5428,21 +5405,6 @@ static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
     return 0;
 }
 
-#if defined(TARGET_NR_mlockall)
-static inline int target_to_host_mlockall_arg(int arg)
-{
-    int result = 0;
-
-    if (arg & TARGET_MLOCKALL_MCL_CURRENT) {
-        result |= MCL_CURRENT;
-    }
-    if (arg & TARGET_MLOCKALL_MCL_FUTURE) {
-        result |= MCL_FUTURE;
-    }
-    return result;
-}
-#endif
-
 #if (defined(TARGET_NR_stat64) || defined(TARGET_NR_lstat64) ||     \
      defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) ||  \
      defined(TARGET_NR_newfstatat))
@@ -7052,86 +7014,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
            ret = get_errno(reboot(arg1, arg2, arg3, NULL));
         }
         return ret;
-#ifdef TARGET_NR_mmap
-    case TARGET_NR_mmap:
-#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
-    (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
-    defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
-    || defined(TARGET_S390X)
-        {
-            abi_ulong *v;
-            abi_ulong v1, v2, v3, v4, v5, v6;
-            if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
-                return -TARGET_EFAULT;
-            v1 = tswapal(v[0]);
-            v2 = tswapal(v[1]);
-            v3 = tswapal(v[2]);
-            v4 = tswapal(v[3]);
-            v5 = tswapal(v[4]);
-            v6 = tswapal(v[5]);
-            unlock_user(v, arg1, 0);
-            ret = get_errno(target_mmap(v1, v2, v3,
-                                        target_to_host_bitmask(v4, mmap_flags_tbl),
-                                        v5, v6));
-        }
-#else
-        ret = get_errno(target_mmap(arg1, arg2, arg3,
-                                    target_to_host_bitmask(arg4, mmap_flags_tbl),
-                                    arg5,
-                                    arg6));
-#endif
-        return ret;
-#endif
-#ifdef TARGET_NR_mmap2
-    case TARGET_NR_mmap2:
-#ifndef MMAP_SHIFT
-#define MMAP_SHIFT 12
-#endif
-        ret = target_mmap(arg1, arg2, arg3,
-                          target_to_host_bitmask(arg4, mmap_flags_tbl),
-                          arg5, arg6 << MMAP_SHIFT);
-        return get_errno(ret);
-#endif
-    case TARGET_NR_munmap:
-        return get_errno(target_munmap(arg1, arg2));
-    case TARGET_NR_mprotect:
-        {
-            TaskState *ts = cpu->opaque;
-            /* Special hack to detect libc making the stack executable.  */
-            if ((arg3 & PROT_GROWSDOWN)
-                && arg1 >= ts->info->stack_limit
-                && arg1 <= ts->info->start_stack) {
-                arg3 &= ~PROT_GROWSDOWN;
-                arg2 = arg2 + arg1 - ts->info->stack_limit;
-                arg1 = ts->info->stack_limit;
-            }
-        }
-        return get_errno(target_mprotect(arg1, arg2, arg3));
-#ifdef TARGET_NR_mremap
-    case TARGET_NR_mremap:
-        return get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
-#endif
-        /* ??? msync/mlock/munlock are broken for softmmu.  */
-#ifdef TARGET_NR_msync
-    case TARGET_NR_msync:
-        return get_errno(msync(g2h(arg1), arg2, arg3));
-#endif
-#ifdef TARGET_NR_mlock
-    case TARGET_NR_mlock:
-        return get_errno(mlock(g2h(arg1), arg2));
-#endif
-#ifdef TARGET_NR_munlock
-    case TARGET_NR_munlock:
-        return get_errno(munlock(g2h(arg1), arg2));
-#endif
-#ifdef TARGET_NR_mlockall
-    case TARGET_NR_mlockall:
-        return get_errno(mlockall(target_to_host_mlockall_arg(arg1)));
-#endif
-#ifdef TARGET_NR_munlockall
-    case TARGET_NR_munlockall:
-        return get_errno(munlockall());
-#endif
 #ifdef TARGET_NR_truncate
     case TARGET_NR_truncate:
         if (!(p = lock_user_string(arg1)))
@@ -10092,6 +9974,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
 
 #include "syscall-file.inc.c"
 #include "syscall-ipc.inc.c"
+#include "syscall-mem.inc.c"
 
 #undef SYSCALL_IMPL
 #undef SYSCALL_ARGS
diff --git a/linux-user/strace.list b/linux-user/strace.list
index f99bd57c09..cc0bb10a7a 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -554,21 +554,6 @@
 #ifdef TARGET_NR_mknodat
 { TARGET_NR_mknodat, "mknodat" , NULL, print_mknodat, NULL },
 #endif
-#ifdef TARGET_NR_mlock
-{ TARGET_NR_mlock, "mlock" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_mlock2
-{ TARGET_NR_mlock2, "mlock2" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_mlockall
-{ TARGET_NR_mlockall, "mlockall" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_mmap
-{ TARGET_NR_mmap, "mmap" , NULL, print_mmap, print_syscall_ret_addr },
-#endif
-#ifdef TARGET_NR_mmap2
-{ TARGET_NR_mmap2, "mmap2" , NULL, print_mmap2, print_syscall_ret_addr },
-#endif
 #ifdef TARGET_NR_modify_ldt
 { TARGET_NR_modify_ldt, "modify_ldt" , NULL, NULL, NULL },
 #endif
@@ -578,9 +563,6 @@
 #ifdef TARGET_NR_move_pages
 { TARGET_NR_move_pages, "move_pages" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_mprotect
-{ TARGET_NR_mprotect, "mprotect" , NULL, print_mprotect, NULL },
-#endif
 #ifdef TARGET_NR_mpx
 { TARGET_NR_mpx, "mpx" , NULL, NULL, NULL },
 #endif
@@ -602,24 +584,9 @@
 #ifdef TARGET_NR_mq_unlink
 { TARGET_NR_mq_unlink, "mq_unlink" , NULL, print_mq_unlink, NULL },
 #endif
-#ifdef TARGET_NR_mremap
-{ TARGET_NR_mremap, "mremap" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_msync
-{ TARGET_NR_msync, "msync" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_multiplexer
 { TARGET_NR_multiplexer, "multiplexer" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_munlock
-{ TARGET_NR_munlock, "munlock" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_munlockall
-{ TARGET_NR_munlockall, "munlockall" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_munmap
-{ TARGET_NR_munmap, "munmap" , NULL, print_munmap, NULL },
-#endif
 #ifdef TARGET_NR_nanosleep
 { TARGET_NR_nanosleep, "nanosleep" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 15/74] linux-user: Split out exit
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (13 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 14/74] linux-user: Split out memory syscalls Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 16/74] linux-user: Split out brk Richard Henderson
                   ` (61 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  1 +
 linux-user/syscall-proc.inc.c | 61 +++++++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 38 +---------------------
 3 files changed, 63 insertions(+), 37 deletions(-)
 create mode 100644 linux-user/syscall-proc.inc.c

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 88f433e998..88aa1a6bfd 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -17,6 +17,7 @@
  */
 
 SYSCALL_DEF(close, ARG_DEC);
+SYSCALL_DEF(exit, ARG_DEC);
 #ifdef TARGET_NR_ipc
 SYSCALL_DEF_ARGS(ipc, ARG_HEX, ARG_DEC, ARG_DEC, ARG_HEX, ARG_PTR, ARG_HEX);
 #endif
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
new file mode 100644
index 0000000000..96ad363c1a
--- /dev/null
+++ b/linux-user/syscall-proc.inc.c
@@ -0,0 +1,61 @@
+/*
+ *  Linux process related syscalls
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+SYSCALL_IMPL(exit)
+{
+    CPUState *cpu = ENV_GET_CPU(cpu_env);
+    int status = arg1;
+
+    /*
+     * In old applications this may be used to implement _exit(2).
+     * However in threaded applictions it is used for thread termination,
+     * and _exit_group is used for application termination.
+     * Do thread termination if we have more then one thread.
+     */
+    if (block_signals()) {
+        return -TARGET_ERESTARTSYS;
+    }
+
+    cpu_list_lock();
+
+    if (CPU_NEXT(first_cpu)) {
+        TaskState *ts;
+
+        /* Remove the CPU from the list.  */
+        QTAILQ_REMOVE_RCU(&cpus, cpu, node);
+
+        cpu_list_unlock();
+
+        ts = cpu->opaque;
+        if (ts->child_tidptr) {
+            put_user_u32(0, ts->child_tidptr);
+            sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
+                      NULL, NULL, 0);
+        }
+        thread_cpu = NULL;
+        object_unref(OBJECT(cpu));
+        g_free(ts);
+        rcu_unregister_thread();
+        pthread_exit(NULL);
+    }
+
+    cpu_list_unlock();
+    preexit_cleanup(cpu_env, status);
+    _exit(status);
+}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 876426dd9c..c72d24aa76 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5681,43 +5681,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_exit:
-        /* In old applications this may be used to implement _exit(2).
-           However in threaded applictions it is used for thread termination,
-           and _exit_group is used for application termination.
-           Do thread termination if we have more then one thread.  */
-
-        if (block_signals()) {
-            return -TARGET_ERESTARTSYS;
-        }
-
-        cpu_list_lock();
-
-        if (CPU_NEXT(first_cpu)) {
-            TaskState *ts;
-
-            /* Remove the CPU from the list.  */
-            QTAILQ_REMOVE_RCU(&cpus, cpu, node);
-
-            cpu_list_unlock();
-
-            ts = cpu->opaque;
-            if (ts->child_tidptr) {
-                put_user_u32(0, ts->child_tidptr);
-                sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
-                          NULL, NULL, 0);
-            }
-            thread_cpu = NULL;
-            object_unref(OBJECT(cpu));
-            g_free(ts);
-            rcu_unregister_thread();
-            pthread_exit(NULL);
-        }
-
-        cpu_list_unlock();
-        preexit_cleanup(cpu_env, arg1);
-        _exit(arg1);
-        return 0; /* avoid warning */
     case TARGET_NR_brk:
         return do_brk(arg1);
 #ifdef TARGET_NR_fork
@@ -9975,6 +9938,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
 #include "syscall-file.inc.c"
 #include "syscall-ipc.inc.c"
 #include "syscall-mem.inc.c"
+#include "syscall-proc.inc.c"
 
 #undef SYSCALL_IMPL
 #undef SYSCALL_ARGS
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 16/74] linux-user: Split out brk
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (14 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 15/74] linux-user: Split out exit Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 17/74] linux-user: Split out clone, fork, vfork Richard Henderson
                   ` (60 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h    |  3 ++
 linux-user/strace.c          | 35 --------------
 linux-user/syscall-mem.inc.c | 90 ++++++++++++++++++++++++++++++++++
 linux-user/syscall.c         | 93 ------------------------------------
 linux-user/strace.list       |  3 --
 5 files changed, 93 insertions(+), 131 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 88aa1a6bfd..c3ed22ff16 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -16,6 +16,9 @@
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+SYSCALL_DEF_FULL(brk, .impl = impl_brk,
+                 .print_ret = print_syscall_ptr_ret,
+                 .arg_type = { ARG_PTR });
 SYSCALL_DEF(close, ARG_DEC);
 SYSCALL_DEF(exit, ARG_DEC);
 #ifdef TARGET_NR_ipc
diff --git a/linux-user/strace.c b/linux-user/strace.c
index a767227ac1..0a2c6764db 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -604,29 +604,6 @@ print_execve(const struct syscallname *name,
  * Variants for the return value output function
  */
 
-static void
-print_syscall_ret_addr(const struct syscallname *name, abi_long ret)
-{
-    const char *errstr = NULL;
-
-    if (ret < 0) {
-        errstr = target_strerror(-ret);
-    }
-    if (errstr) {
-        gemu_log(" = -1 errno=%d (%s)\n", (int)-ret, errstr);
-    } else {
-        gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
-    }
-}
-
-#if 0 /* currently unused */
-static void
-print_syscall_ret_raw(struct syscallname *name, abi_long ret)
-{
-        gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
-}
-#endif
-
 #ifdef TARGET_NR__newselect
 static void
 print_syscall_ret_newselect(const struct syscallname *name, abi_long ret)
@@ -1168,18 +1145,6 @@ print_access(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_brk
-static void
-print_brk(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_pointer(arg0, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_chdir
 static void
 print_chdir(const struct syscallname *name,
diff --git a/linux-user/syscall-mem.inc.c b/linux-user/syscall-mem.inc.c
index d2ce0cb8cc..17ba8e3d97 100644
--- a/linux-user/syscall-mem.inc.c
+++ b/linux-user/syscall-mem.inc.c
@@ -42,6 +42,96 @@ static bitmask_transtbl const mmap_flags_tbl[] = {
     { 0, 0, 0, 0 }
 };
 
+static abi_ulong target_brk;
+static abi_ulong target_original_brk;
+static abi_ulong brk_page;
+
+void target_set_brk(abi_ulong new_brk)
+{
+    target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
+    brk_page = HOST_PAGE_ALIGN(target_brk);
+}
+
+/* do_brk() must return target values and target errnos. */
+abi_long do_brk(abi_ulong new_brk)
+{
+    abi_long mapped_addr;
+    abi_ulong new_alloc_size;
+
+    if (!new_brk) {
+        return target_brk;
+    }
+    if (new_brk < target_original_brk) {
+        return target_brk;
+    }
+
+    /*
+     * If the new brk is less than the highest page reserved to the
+     * target heap allocation, set it and we're almost done...
+     */
+    if (new_brk <= brk_page) {
+        /*
+         * Heap contents are initialized to zero,
+         * as for anonymous mapped pages.
+         */
+        if (new_brk > target_brk) {
+            memset(g2h(target_brk), 0, new_brk - target_brk);
+        }
+        target_brk = new_brk;
+        return target_brk;
+    }
+
+    /*
+     * We need to allocate more memory after the brk... Note that
+     * we don't use MAP_FIXED because that will map over the top of
+     * any existing mapping (like the one with the host libc or qemu
+     * itself); instead we treat "mapped but at wrong address" as
+     * a failure and unmap again.
+     */
+    new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
+    mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
+                                        PROT_READ | PROT_WRITE,
+                                        MAP_ANON | MAP_PRIVATE, 0, 0));
+
+    if (mapped_addr == brk_page) {
+        /*
+         * Heap contents are initialized to zero, as for anonymous
+         * mapped pages.  Technically the new pages are already
+         * initialized to zero since they *are* anonymous mapped
+         * pages, however we have to take care with the contents that
+         * come from the remaining part of the previous page: it may
+         * contains garbage data due to a previous heap usage (grown
+         * then shrunken).
+         */
+        memset(g2h(target_brk), 0, brk_page - target_brk);
+
+        target_brk = new_brk;
+        brk_page = HOST_PAGE_ALIGN(target_brk);
+        return target_brk;
+    } else if (mapped_addr != -1) {
+        /*
+         * Mapped but at wrong address, meaning there wasn't actually
+         * enough space for this brk.
+         */
+        target_munmap(mapped_addr, new_alloc_size);
+        mapped_addr = -1;
+    }
+
+#if defined(TARGET_ALPHA)
+    /*
+     * We (partially) emulate OSF/1 on Alpha, which requires we
+     * return a proper errno, not an unchanged brk value.
+     */
+    return -TARGET_ENOMEM;
+#endif
+    /* For everything else, return the previous break. */
+    return target_brk;
+}
+
+SYSCALL_IMPL(brk)
+{
+    return do_brk(arg1);
+}
 
 SYSCALL_IMPL(mlock)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index c72d24aa76..4c9953a7ab 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -820,97 +820,6 @@ static inline int host_to_target_sock_type(int host_type)
     return target_type;
 }
 
-static abi_ulong target_brk;
-static abi_ulong target_original_brk;
-static abi_ulong brk_page;
-
-void target_set_brk(abi_ulong new_brk)
-{
-    target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
-    brk_page = HOST_PAGE_ALIGN(target_brk);
-}
-
-//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
-#define DEBUGF_BRK(message, args...)
-
-/* do_brk() must return target values and target errnos. */
-abi_long do_brk(abi_ulong new_brk)
-{
-    abi_long mapped_addr;
-    abi_ulong new_alloc_size;
-
-    DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk);
-
-    if (!new_brk) {
-        DEBUGF_BRK(TARGET_ABI_FMT_lx " (!new_brk)\n", target_brk);
-        return target_brk;
-    }
-    if (new_brk < target_original_brk) {
-        DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk < target_original_brk)\n",
-                   target_brk);
-        return target_brk;
-    }
-
-    /* If the new brk is less than the highest page reserved to the
-     * target heap allocation, set it and we're almost done...  */
-    if (new_brk <= brk_page) {
-        /* Heap contents are initialized to zero, as for anonymous
-         * mapped pages.  */
-        if (new_brk > target_brk) {
-            memset(g2h(target_brk), 0, new_brk - target_brk);
-        }
-	target_brk = new_brk;
-        DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", target_brk);
-	return target_brk;
-    }
-
-    /* We need to allocate more memory after the brk... Note that
-     * we don't use MAP_FIXED because that will map over the top of
-     * any existing mapping (like the one with the host libc or qemu
-     * itself); instead we treat "mapped but at wrong address" as
-     * a failure and unmap again.
-     */
-    new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
-    mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
-                                        PROT_READ|PROT_WRITE,
-                                        MAP_ANON|MAP_PRIVATE, 0, 0));
-
-    if (mapped_addr == brk_page) {
-        /* Heap contents are initialized to zero, as for anonymous
-         * mapped pages.  Technically the new pages are already
-         * initialized to zero since they *are* anonymous mapped
-         * pages, however we have to take care with the contents that
-         * come from the remaining part of the previous page: it may
-         * contains garbage data due to a previous heap usage (grown
-         * then shrunken).  */
-        memset(g2h(target_brk), 0, brk_page - target_brk);
-
-        target_brk = new_brk;
-        brk_page = HOST_PAGE_ALIGN(target_brk);
-        DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n",
-            target_brk);
-        return target_brk;
-    } else if (mapped_addr != -1) {
-        /* Mapped but at wrong address, meaning there wasn't actually
-         * enough space for this brk.
-         */
-        target_munmap(mapped_addr, new_alloc_size);
-        mapped_addr = -1;
-        DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr != -1)\n", target_brk);
-    }
-    else {
-        DEBUGF_BRK(TARGET_ABI_FMT_lx " (otherwise)\n", target_brk);
-    }
-
-#if defined(TARGET_ALPHA)
-    /* We (partially) emulate OSF/1 on Alpha, which requires we
-       return a proper errno, not an unchanged brk value.  */
-    return -TARGET_ENOMEM;
-#endif
-    /* For everything else, return the previous break. */
-    return target_brk;
-}
-
 static inline abi_long copy_from_user_fdset(fd_set *fds,
                                             abi_ulong target_fds_addr,
                                             int n)
@@ -5681,8 +5590,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_brk:
-        return do_brk(arg1);
 #ifdef TARGET_NR_fork
     case TARGET_NR_fork:
         return get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0));
diff --git a/linux-user/strace.list b/linux-user/strace.list
index cc0bb10a7a..aff6d1d73d 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -49,9 +49,6 @@
 #ifdef TARGET_NR_break
 { TARGET_NR_break, "break" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_brk
-{ TARGET_NR_brk, "brk" , NULL, print_brk, print_syscall_ret_addr },
-#endif
 #ifdef TARGET_NR_cachectl
 { TARGET_NR_cachectl, "cachectl" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 17/74] linux-user: Split out clone, fork, vfork
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (15 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 16/74] linux-user: Split out brk Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 18/74] linux-user: Split out wait4, waitid, waitpid Richard Henderson
                   ` (59 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Rename do_fork to do_clone, since that is what it does.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |   8 ++
 linux-user/syscall.h          |   1 +
 linux-user/strace.c           |  36 +----
 linux-user/syscall-proc.inc.c | 259 ++++++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 220 -----------------------------
 linux-user/strace.list        |   9 --
 6 files changed, 272 insertions(+), 261 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index c3ed22ff16..6f6f77927b 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -19,8 +19,12 @@
 SYSCALL_DEF_FULL(brk, .impl = impl_brk,
                  .print_ret = print_syscall_ptr_ret,
                  .arg_type = { ARG_PTR });
+SYSCALL_DEF_ARGS(clone, ARG_CLONEFLAG, ARG_PTR, ARG_PTR, ARG_PTR, ARG_PTR);
 SYSCALL_DEF(close, ARG_DEC);
 SYSCALL_DEF(exit, ARG_DEC);
+#ifdef TARGET_NR_fork
+SYSCALL_DEF(fork);
+#endif
 #ifdef TARGET_NR_ipc
 SYSCALL_DEF_ARGS(ipc, ARG_HEX, ARG_DEC, ARG_DEC, ARG_HEX, ARG_PTR, ARG_HEX);
 #endif
@@ -110,5 +114,9 @@ SYSCALL_DEF(shmdt, ARG_PTR);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_shmget)
 SYSCALL_DEF(shmget, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
+#ifdef TARGET_NR_vfork
+/* Emulate vfork() with fork().  */
+SYSCALL_DEF_FULL(vfork, .impl = impl_fork);
+#endif
 SYSCALL_DEF(write, ARG_DEC, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(writev, ARG_DEC, ARG_PTR, ARG_DEC);
diff --git a/linux-user/syscall.h b/linux-user/syscall.h
index 8175de4c31..f75cd3ddd0 100644
--- a/linux-user/syscall.h
+++ b/linux-user/syscall.h
@@ -58,6 +58,7 @@ typedef enum {
     /* These print as sets of flags.  */
     ARG_ATDIRFD,
     ARG_ATFLAG,
+    ARG_CLONEFLAG,
     ARG_MMAPFLAG,
     ARG_MMAPPROT,
     ARG_MODEFLAG,
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 0a2c6764db..842136e425 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -813,7 +813,7 @@ static struct flags const mmap_flags[] = {
     FLAG_END,
 };
 
-UNUSED static struct flags clone_flags[] = {
+static struct flags const clone_flags[] = {
     FLAG_GENERIC(CLONE_VM),
     FLAG_GENERIC(CLONE_FS),
     FLAG_GENERIC(CLONE_FILES),
@@ -1195,37 +1195,6 @@ print_clock_adjtime(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_clone
-static void do_print_clone(unsigned int flags, abi_ulong newsp,
-                           abi_ulong parent_tidptr, target_ulong newtls,
-                           abi_ulong child_tidptr)
-{
-    print_flags(clone_flags, flags, 0);
-    print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, newsp, 0);
-    print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, parent_tidptr, 0);
-    print_raw_param("tls=0x" TARGET_ABI_FMT_lx, newtls, 0);
-    print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, child_tidptr, 1);
-}
-
-static void
-print_clone(const struct syscallname *name,
-    abi_long arg1, abi_long arg2, abi_long arg3,
-    abi_long arg4, abi_long arg5, abi_long arg6)
-{
-    print_syscall_prologue(name);
-#if defined(TARGET_MICROBLAZE)
-    do_print_clone(arg1, arg2, arg4, arg6, arg5);
-#elif defined(TARGET_CLONE_BACKWARDS)
-    do_print_clone(arg1, arg2, arg3, arg4, arg5);
-#elif defined(TARGET_CLONE_BACKWARDS2)
-    do_print_clone(arg2, arg1, arg3, arg5, arg4);
-#else
-    do_print_clone(arg1, arg2, arg3, arg5, arg4);
-#endif
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_creat
 static void
 print_creat(const struct syscallname *name,
@@ -2533,6 +2502,9 @@ static void print_syscall_def1(const SyscallDef *def, int64_t args[6])
         case ARG_ATFLAG:
             len = add_flags(b, rest, at_file_flags, arg, false);
             break;
+        case ARG_CLONEFLAG:
+            len = add_flags(b, rest, clone_flags, arg, false);
+            break;
         case ARG_MMAPFLAG:
             len = add_flags(b, rest, mmap_flags, arg, false);
             break;
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
index 96ad363c1a..9eda2b2ca2 100644
--- a/linux-user/syscall-proc.inc.c
+++ b/linux-user/syscall-proc.inc.c
@@ -16,6 +16,258 @@
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#ifndef CLONE_IO
+#define CLONE_IO                0x80000000      /* Clone io context */
+#endif
+
+/*
+ * We can't directly call the host clone syscall, because this will
+ * badly confuse libc (breaking mutexes, for example). So we must
+ * divide clone flags into:
+ *  * flag combinations that look like pthread_create()
+ *  * flag combinations that look like fork()
+ *  * flags we can implement within QEMU itself
+ *  * flags we can't support and will return an error for
+ *
+ * For thread creation, all these flags must be present; for
+ * fork, none must be present.
+ */
+#define CLONE_THREAD_FLAGS                              \
+    (CLONE_VM | CLONE_FS | CLONE_FILES |                \
+     CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM)
+
+/*
+ * These flags are ignored:
+ * CLONE_DETACHED is now ignored by the kernel;
+ * CLONE_IO is just an optimisation hint to the I/O scheduler
+ */
+#define CLONE_IGNORED_FLAGS                     \
+    (CLONE_DETACHED | CLONE_IO)
+
+/* Flags for fork which we can implement within QEMU itself */
+#define CLONE_OPTIONAL_FORK_FLAGS               \
+    (CLONE_SETTLS | CLONE_PARENT_SETTID |       \
+     CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID)
+
+/* Flags for thread creation which we can implement within QEMU itself */
+#define CLONE_OPTIONAL_THREAD_FLAGS                             \
+    (CLONE_SETTLS | CLONE_PARENT_SETTID |                       \
+     CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_PARENT)
+
+#define CLONE_INVALID_FORK_FLAGS                                        \
+    (~(CSIGNAL | CLONE_OPTIONAL_FORK_FLAGS | CLONE_IGNORED_FLAGS))
+
+#define CLONE_INVALID_THREAD_FLAGS                                      \
+    (~(CSIGNAL | CLONE_THREAD_FLAGS | CLONE_OPTIONAL_THREAD_FLAGS |     \
+       CLONE_IGNORED_FLAGS))
+
+/*
+ * CLONE_VFORK is special cased early in do_fork(). The other flag bits
+ * have almost all been allocated. We cannot support any of
+ * CLONE_NEWNS, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC,
+ * CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, CLONE_PTRACE, CLONE_UNTRACED.
+ * The checks against the invalid thread masks above will catch these.
+ * (The one remaining unallocated bit is 0x1000 which used to be CLONE_PID.)
+ */
+
+/**
+ * do_clone:
+ * Arguments as for clone(2), returns target errnos.
+ */
+static abi_long do_clone(CPUArchState *env, unsigned int flags,
+                         abi_ulong newsp, abi_ulong parent_tidptr,
+                         abi_ulong child_tidptr, target_ulong newtls)
+{
+    CPUState *cpu = ENV_GET_CPU(env);
+    abi_long ret;
+    TaskState *ts;
+    CPUState *new_cpu;
+    CPUArchState *new_env;
+    sigset_t sigmask;
+
+    flags &= ~CLONE_IGNORED_FLAGS;
+
+    /* Emulate vfork() with fork() */
+    if (flags & CLONE_VFORK) {
+        flags &= ~(CLONE_VFORK | CLONE_VM);
+    }
+
+    if (flags & CLONE_VM) {
+        /* If CLONE_VM, we consider it a new thread.  */
+        TaskState *parent_ts = (TaskState *)cpu->opaque;
+        new_thread_info info;
+        pthread_attr_t attr;
+
+        if (((flags & CLONE_THREAD_FLAGS) != CLONE_THREAD_FLAGS) ||
+            (flags & CLONE_INVALID_THREAD_FLAGS)) {
+            return -TARGET_EINVAL;
+        }
+
+        ts = g_new0(TaskState, 1);
+        init_task_state(ts);
+
+        /* Grab a mutex so that thread setup appears atomic.  */
+        pthread_mutex_lock(&clone_lock);
+
+        /* Create a new CPU instance.  */
+        new_env = cpu_copy(env);
+
+        /* Init regs that differ from the parent.  */
+        cpu_clone_regs_child(new_env, newsp);
+        cpu_clone_regs_parent(env);
+        new_cpu = ENV_GET_CPU(new_env);
+        new_cpu->opaque = ts;
+        ts->bprm = parent_ts->bprm;
+        ts->info = parent_ts->info;
+        ts->signal_mask = parent_ts->signal_mask;
+
+        if (flags & CLONE_CHILD_CLEARTID) {
+            ts->child_tidptr = child_tidptr;
+        }
+
+        if (flags & CLONE_SETTLS) {
+            cpu_set_tls(new_env, newtls);
+        }
+
+        memset(&info, 0, sizeof(info));
+        pthread_mutex_init(&info.mutex, NULL);
+        pthread_mutex_lock(&info.mutex);
+        pthread_cond_init(&info.cond, NULL);
+        info.env = new_env;
+        if (flags & CLONE_CHILD_SETTID) {
+            info.child_tidptr = child_tidptr;
+        }
+        if (flags & CLONE_PARENT_SETTID) {
+            info.parent_tidptr = parent_tidptr;
+        }
+
+        ret = pthread_attr_init(&attr);
+        ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
+        ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+        /*
+         * It is not safe to deliver signals until the child has finished
+         * initializing, so temporarily block all signals.
+         */
+        sigfillset(&sigmask);
+        sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
+
+        /*
+         * If this is our first additional thread, we need to ensure we
+         * generate code for parallel execution and flush old translations.
+         */
+        if (!parallel_cpus) {
+            parallel_cpus = true;
+            tb_flush(cpu);
+        }
+
+        ret = pthread_create(&info.thread, &attr, clone_func, &info);
+        /* TODO: Free new CPU state if thread creation failed.  */
+
+        sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
+        pthread_attr_destroy(&attr);
+        if (ret == 0) {
+            /* Wait for the child to initialize.  */
+            pthread_cond_wait(&info.cond, &info.mutex);
+            ret = info.tid;
+        } else {
+            ret = host_to_target_errno(ret);
+        }
+        pthread_mutex_unlock(&info.mutex);
+        pthread_cond_destroy(&info.cond);
+        pthread_mutex_destroy(&info.mutex);
+        pthread_mutex_unlock(&clone_lock);
+    } else {
+        /* If no CLONE_VM, we consider it a fork.  */
+        if (flags & CLONE_INVALID_FORK_FLAGS) {
+            return -TARGET_EINVAL;
+        }
+
+        /* We can't support custom termination signals.  */
+        if ((flags & CSIGNAL) != TARGET_SIGCHLD) {
+            return -TARGET_EINVAL;
+        }
+
+        if (block_signals()) {
+            return -TARGET_ERESTARTSYS;
+        }
+
+        fork_start();
+        ret = fork();
+        if (ret == 0) {
+            /* Child Process.  */
+            cpu_clone_regs_child(env, newsp);
+            fork_end(1);
+            /*
+             * There is a race condition here.  The parent process could
+             * theoretically read the TID in the child process before the
+             * child tid is set.  This would require using either ptrace
+             * (not implemented) or having *_tidptr to point at a shared
+             * memory mapping.  We can't repeat the spinlock hack used
+             * above because the child process gets its own copy of the lock.
+             */
+            if (flags & CLONE_CHILD_SETTID) {
+                put_user_u32(sys_gettid(), child_tidptr);
+            }
+            if (flags & CLONE_PARENT_SETTID) {
+                put_user_u32(sys_gettid(), parent_tidptr);
+            }
+            ts = (TaskState *)cpu->opaque;
+            if (flags & CLONE_SETTLS) {
+                cpu_set_tls(env, newtls);
+            }
+            if (flags & CLONE_CHILD_CLEARTID) {
+                ts->child_tidptr = child_tidptr;
+            }
+        } else {
+            cpu_clone_regs_parent(env);
+            fork_end(0);
+            ret = get_errno(ret);
+        }
+    }
+    return ret;
+}
+
+#if defined(TARGET_MICROBLAZE) || \
+    defined(TARGET_CLONE_BACKWARDS) || \
+    defined(TARGET_CLONE_BACKWARDS2)
+SYSCALL_ARGS(clone)
+{
+    /*
+     * Linux manages to have three "standard" orderings for its
+     * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
+     * match the kernel's CONFIG_CLONE_* settings.
+     * Microblaze is further special in that it uses a sixth
+     * implicit argument to clone for the TLS pointer.
+     *
+     * Standardize on the non-BACKWARDS ordering.
+     */
+# if defined(TARGET_MICROBLAZE)
+    /* We have already assigned out[0-1].  */
+    out[2] = in[3];
+    out[3] = in[4];
+    out[4] = in[5];
+# elif defined(TARGET_CLONE_BACKWARDS)
+    /* We have already assigned out[0-2].  */
+    out[3] = in[4];
+    out[4] = in[3];
+# elif defined(TARGET_CLONE_BACKWARDS2)
+    /* We have already assigned out[2-4].  */
+    out[0] = in[1];
+    out[1] = in[0];
+# else
+#  error Missing case
+# endif
+    return def;
+}
+#else
+#define args_clone NULL
+#endif
+
+SYSCALL_IMPL(clone)
+{
+    return do_clone(cpu_env, arg1, arg2, arg3, arg4, arg5);
+}
 
 SYSCALL_IMPL(exit)
 {
@@ -59,3 +311,10 @@ SYSCALL_IMPL(exit)
     preexit_cleanup(cpu_env, status);
     _exit(status);
 }
+
+#if defined(TARGET_NR_fork) || defined(TARGET_NR_vfork)
+SYSCALL_IMPL(fork)
+{
+    return do_clone(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0);
+}
+#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 4c9953a7ab..26140ebb2f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -110,57 +110,6 @@
 #include "fd-trans.h"
 #include "syscall.h"
 
-#ifndef CLONE_IO
-#define CLONE_IO                0x80000000      /* Clone io context */
-#endif
-
-/* We can't directly call the host clone syscall, because this will
- * badly confuse libc (breaking mutexes, for example). So we must
- * divide clone flags into:
- *  * flag combinations that look like pthread_create()
- *  * flag combinations that look like fork()
- *  * flags we can implement within QEMU itself
- *  * flags we can't support and will return an error for
- */
-/* For thread creation, all these flags must be present; for
- * fork, none must be present.
- */
-#define CLONE_THREAD_FLAGS                              \
-    (CLONE_VM | CLONE_FS | CLONE_FILES |                \
-     CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM)
-
-/* These flags are ignored:
- * CLONE_DETACHED is now ignored by the kernel;
- * CLONE_IO is just an optimisation hint to the I/O scheduler
- */
-#define CLONE_IGNORED_FLAGS                     \
-    (CLONE_DETACHED | CLONE_IO)
-
-/* Flags for fork which we can implement within QEMU itself */
-#define CLONE_OPTIONAL_FORK_FLAGS               \
-    (CLONE_SETTLS | CLONE_PARENT_SETTID |       \
-     CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID)
-
-/* Flags for thread creation which we can implement within QEMU itself */
-#define CLONE_OPTIONAL_THREAD_FLAGS                             \
-    (CLONE_SETTLS | CLONE_PARENT_SETTID |                       \
-     CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_PARENT)
-
-#define CLONE_INVALID_FORK_FLAGS                                        \
-    (~(CSIGNAL | CLONE_OPTIONAL_FORK_FLAGS | CLONE_IGNORED_FLAGS))
-
-#define CLONE_INVALID_THREAD_FLAGS                                      \
-    (~(CSIGNAL | CLONE_THREAD_FLAGS | CLONE_OPTIONAL_THREAD_FLAGS |     \
-       CLONE_IGNORED_FLAGS))
-
-/* CLONE_VFORK is special cased early in do_fork(). The other flag bits
- * have almost all been allocated. We cannot support any of
- * CLONE_NEWNS, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC,
- * CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, CLONE_PTRACE, CLONE_UNTRACED.
- * The checks against the invalid thread masks above will catch these.
- * (The one remaining unallocated bit is 0x1000 which used to be CLONE_PID.)
- */
-
 /* Define DEBUG_ERESTARTSYS to force every syscall to be restarted
  * once. This exercises the codepaths for restart.
  */
@@ -4450,148 +4399,6 @@ static void *clone_func(void *arg)
     return NULL;
 }
 
-/* do_fork() Must return host values and target errnos (unlike most
-   do_*() functions). */
-static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
-                   abi_ulong parent_tidptr, target_ulong newtls,
-                   abi_ulong child_tidptr)
-{
-    CPUState *cpu = ENV_GET_CPU(env);
-    int ret;
-    TaskState *ts;
-    CPUState *new_cpu;
-    CPUArchState *new_env;
-    sigset_t sigmask;
-
-    flags &= ~CLONE_IGNORED_FLAGS;
-
-    /* Emulate vfork() with fork() */
-    if (flags & CLONE_VFORK)
-        flags &= ~(CLONE_VFORK | CLONE_VM);
-
-    if (flags & CLONE_VM) {
-        TaskState *parent_ts = (TaskState *)cpu->opaque;
-        new_thread_info info;
-        pthread_attr_t attr;
-
-        if (((flags & CLONE_THREAD_FLAGS) != CLONE_THREAD_FLAGS) ||
-            (flags & CLONE_INVALID_THREAD_FLAGS)) {
-            return -TARGET_EINVAL;
-        }
-
-        ts = g_new0(TaskState, 1);
-        init_task_state(ts);
-
-        /* Grab a mutex so that thread setup appears atomic.  */
-        pthread_mutex_lock(&clone_lock);
-
-        /* we create a new CPU instance. */
-        new_env = cpu_copy(env);
-        /* Init regs that differ from the parent.  */
-        cpu_clone_regs_child(new_env, newsp);
-        cpu_clone_regs_parent(env);
-        new_cpu = ENV_GET_CPU(new_env);
-        new_cpu->opaque = ts;
-        ts->bprm = parent_ts->bprm;
-        ts->info = parent_ts->info;
-        ts->signal_mask = parent_ts->signal_mask;
-
-        if (flags & CLONE_CHILD_CLEARTID) {
-            ts->child_tidptr = child_tidptr;
-        }
-
-        if (flags & CLONE_SETTLS) {
-            cpu_set_tls (new_env, newtls);
-        }
-
-        memset(&info, 0, sizeof(info));
-        pthread_mutex_init(&info.mutex, NULL);
-        pthread_mutex_lock(&info.mutex);
-        pthread_cond_init(&info.cond, NULL);
-        info.env = new_env;
-        if (flags & CLONE_CHILD_SETTID) {
-            info.child_tidptr = child_tidptr;
-        }
-        if (flags & CLONE_PARENT_SETTID) {
-            info.parent_tidptr = parent_tidptr;
-        }
-
-        ret = pthread_attr_init(&attr);
-        ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
-        ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-        /* It is not safe to deliver signals until the child has finished
-           initializing, so temporarily block all signals.  */
-        sigfillset(&sigmask);
-        sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
-
-        /* If this is our first additional thread, we need to ensure we
-         * generate code for parallel execution and flush old translations.
-         */
-        if (!parallel_cpus) {
-            parallel_cpus = true;
-            tb_flush(cpu);
-        }
-
-        ret = pthread_create(&info.thread, &attr, clone_func, &info);
-        /* TODO: Free new CPU state if thread creation failed.  */
-
-        sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
-        pthread_attr_destroy(&attr);
-        if (ret == 0) {
-            /* Wait for the child to initialize.  */
-            pthread_cond_wait(&info.cond, &info.mutex);
-            ret = info.tid;
-        } else {
-            ret = -1;
-        }
-        pthread_mutex_unlock(&info.mutex);
-        pthread_cond_destroy(&info.cond);
-        pthread_mutex_destroy(&info.mutex);
-        pthread_mutex_unlock(&clone_lock);
-    } else {
-        /* if no CLONE_VM, we consider it is a fork */
-        if (flags & CLONE_INVALID_FORK_FLAGS) {
-            return -TARGET_EINVAL;
-        }
-
-        /* We can't support custom termination signals */
-        if ((flags & CSIGNAL) != TARGET_SIGCHLD) {
-            return -TARGET_EINVAL;
-        }
-
-        if (block_signals()) {
-            return -TARGET_ERESTARTSYS;
-        }
-
-        fork_start();
-        ret = fork();
-        if (ret == 0) {
-            /* Child Process.  */
-            cpu_clone_regs_child(env, newsp);
-            fork_end(1);
-            /* There is a race condition here.  The parent process could
-               theoretically read the TID in the child process before the child
-               tid is set.  This would require using either ptrace
-               (not implemented) or having *_tidptr to point at a shared memory
-               mapping.  We can't repeat the spinlock hack used above because
-               the child process gets its own copy of the lock.  */
-            if (flags & CLONE_CHILD_SETTID)
-                put_user_u32(sys_gettid(), child_tidptr);
-            if (flags & CLONE_PARENT_SETTID)
-                put_user_u32(sys_gettid(), parent_tidptr);
-            ts = (TaskState *)cpu->opaque;
-            if (flags & CLONE_SETTLS)
-                cpu_set_tls (env, newtls);
-            if (flags & CLONE_CHILD_CLEARTID)
-                ts->child_tidptr = child_tidptr;
-        } else {
-            cpu_clone_regs_parent(env);
-            fork_end(0);
-        }
-    }
-    return ret;
-}
-
 /* warning : doesn't handle linux specific flags... */
 static int target_to_host_fcntl_cmd(int cmd)
 {
@@ -5590,10 +5397,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_fork
-    case TARGET_NR_fork:
-        return get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0));
-#endif
 #ifdef TARGET_NR_waitpid
     case TARGET_NR_waitpid:
         {
@@ -7283,23 +7086,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         return ret;
     case TARGET_NR_fsync:
         return get_errno(fsync(arg1));
-    case TARGET_NR_clone:
-        /* Linux manages to have three different orderings for its
-         * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
-         * match the kernel's CONFIG_CLONE_* settings.
-         * Microblaze is further special in that it uses a sixth
-         * implicit argument to clone for the TLS pointer.
-         */
-#if defined(TARGET_MICROBLAZE)
-        ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
-#elif defined(TARGET_CLONE_BACKWARDS)
-        ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
-#elif defined(TARGET_CLONE_BACKWARDS2)
-        ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
-#else
-        ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
-#endif
-        return ret;
 #ifdef __NR_exit_group
         /* new thread calls */
     case TARGET_NR_exit_group:
@@ -8170,12 +7956,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     }
 #endif
 #endif
-#ifdef TARGET_NR_vfork
-    case TARGET_NR_vfork:
-        return get_errno(do_fork(cpu_env,
-                         CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD,
-                         0, 0, 0, 0));
-#endif
 #ifdef TARGET_NR_ugetrlimit
     case TARGET_NR_ugetrlimit:
     {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index aff6d1d73d..76d983a882 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -91,9 +91,6 @@
 #ifdef TARGET_NR_clock_settime
 { TARGET_NR_clock_settime, "clock_settime" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_clone
-{ TARGET_NR_clone, "clone" , NULL, print_clone, NULL },
-#endif
 #ifdef TARGET_NR_connect
 { TARGET_NR_connect, "connect" , "%s(%d,%#x,%d)", NULL, NULL },
 #endif
@@ -220,9 +217,6 @@
 #ifdef TARGET_NR_flock
 { TARGET_NR_flock, "flock" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_fork
-{ TARGET_NR_fork, "fork" , "%s()", NULL, NULL },
-#endif
 #ifdef TARGET_NR_fremovexattr
 { TARGET_NR_fremovexattr, "fremovexattr" , NULL, NULL, NULL },
 #endif
@@ -1485,9 +1479,6 @@
 #ifdef TARGET_NR_utrap_install
 { TARGET_NR_utrap_install, "utrap_install" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_vfork
-{ TARGET_NR_vfork, "vfork" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_vhangup
 { TARGET_NR_vhangup, "vhangup" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 18/74] linux-user: Split out wait4, waitid, waitpid
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (16 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 17/74] linux-user: Split out clone, fork, vfork Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 19/74] linux-user: Implement rusage argument to waitid Richard Henderson
                   ` (58 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Note that waitid is universally provided and need not be conditional.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  5 ++
 linux-user/syscall-proc.inc.c | 88 +++++++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 67 --------------------------
 linux-user/strace.list        |  9 ----
 4 files changed, 93 insertions(+), 76 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 6f6f77927b..a84050a318 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -118,5 +118,10 @@ SYSCALL_DEF(shmget, ARG_DEC, ARG_DEC, ARG_HEX);
 /* Emulate vfork() with fork().  */
 SYSCALL_DEF_FULL(vfork, .impl = impl_fork);
 #endif
+SYSCALL_DEF(wait4, ARG_DEC, ARG_PTR, ARG_HEX, ARG_PTR);
+SYSCALL_DEF(waitid, ARG_HEX, ARG_DEC, ARG_PTR, ARG_HEX);
+#ifdef TARGET_NR_waitpid
+SYSCALL_DEF(waitpid, ARG_DEC, ARG_PTR, ARG_HEX);
+#endif
 SYSCALL_DEF(write, ARG_DEC, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(writev, ARG_DEC, ARG_PTR, ARG_DEC);
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
index 9eda2b2ca2..7c647f36d7 100644
--- a/linux-user/syscall-proc.inc.c
+++ b/linux-user/syscall-proc.inc.c
@@ -318,3 +318,91 @@ SYSCALL_IMPL(fork)
     return do_clone(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0);
 }
 #endif
+
+/*
+ * Map host to target signal numbers for the wait family of syscalls.
+ * Assume all other status bits are the same.
+ */
+int host_to_target_waitstatus(int status)
+{
+    if (WIFSIGNALED(status)) {
+        return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
+    }
+    if (WIFSTOPPED(status)) {
+        return (host_to_target_signal(WSTOPSIG(status)) << 8)
+               | (status & 0xff);
+    }
+    return status;
+}
+
+SYSCALL_IMPL(wait4)
+{
+    int status;
+    pid_t pid = arg1;
+    abi_ulong status_ptr = arg2;
+    int options = arg3;
+    abi_ulong target_rusage = arg4;
+    struct rusage rusage;
+    struct rusage *rusage_ptr = target_rusage ? &rusage : NULL;
+    abi_long ret;
+
+    ret = get_errno(safe_wait4(pid, &status, options, rusage_ptr));
+    if (!is_error(ret)) {
+        if (status_ptr && ret) {
+            status = host_to_target_waitstatus(status);
+            if (put_user_s32(status, status_ptr)) {
+                return -TARGET_EFAULT;
+            }
+        }
+        if (target_rusage) {
+            abi_long err = host_to_target_rusage(target_rusage, &rusage);
+            if (err) {
+                ret = err;
+            }
+        }
+    }
+    return ret;
+}
+
+SYSCALL_IMPL(waitid)
+{
+    idtype_t idtype = arg1;
+    id_t id = arg2;
+    abi_ulong target_info = arg3;
+    int options = arg4;
+    siginfo_t info, *info_ptr = target_info ? &info : NULL;
+    abi_long ret;
+
+    info.si_pid = 0;
+    ret = get_errno(safe_waitid(idtype, id, info_ptr, options, NULL));
+    if (!is_error(ret) && target_info && info.si_pid != 0) {
+        target_siginfo_t *p = lock_user(VERIFY_WRITE, target_info,
+                                        sizeof(target_siginfo_t), 0);
+        if (!p) {
+            return -TARGET_EFAULT;
+        }
+        host_to_target_siginfo(p, &info);
+        unlock_user(p, target_info, sizeof(target_siginfo_t));
+    }
+    return ret;
+}
+
+#ifdef TARGET_NR_waitpid
+SYSCALL_IMPL(waitpid)
+{
+    pid_t pid = arg1;
+    abi_ulong target_status = arg2;
+    int options = arg3;
+    int status;
+    abi_long ret;
+
+    ret = get_errno(safe_wait4(pid, &status, options, NULL));
+    if (!is_error(ret)
+        && target_status
+        && ret
+        && put_user_s32(host_to_target_waitstatus(status), target_status)) {
+        return -TARGET_EFAULT;
+    }
+    return ret;
+}
+#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 26140ebb2f..bdb0d45d9a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5271,20 +5271,6 @@ static abi_long do_signalfd4(int fd, abi_long mask, int flags)
 }
 #endif
 
-/* Map host to target signal numbers for the wait family of syscalls.
-   Assume all other status bits are the same.  */
-int host_to_target_waitstatus(int status)
-{
-    if (WIFSIGNALED(status)) {
-        return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
-    }
-    if (WIFSTOPPED(status)) {
-        return (host_to_target_signal(WSTOPSIG(status)) << 8)
-               | (status & 0xff);
-    }
-    return status;
-}
-
 #define TIMER_MAGIC 0x0caf0000
 #define TIMER_MAGIC_MASK 0xffff0000
 
@@ -5397,32 +5383,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_waitpid
-    case TARGET_NR_waitpid:
-        {
-            int status;
-            ret = get_errno(safe_wait4(arg1, &status, arg3, 0));
-            if (!is_error(ret) && arg2 && ret
-                && put_user_s32(host_to_target_waitstatus(status), arg2))
-                return -TARGET_EFAULT;
-        }
-        return ret;
-#endif
-#ifdef TARGET_NR_waitid
-    case TARGET_NR_waitid:
-        {
-            siginfo_t info;
-            info.si_pid = 0;
-            ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL));
-            if (!is_error(ret) && arg3 && info.si_pid != 0) {
-                if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
-                    return -TARGET_EFAULT;
-                host_to_target_siginfo(p, &info);
-                unlock_user(p, arg3, sizeof(target_siginfo_t));
-            }
-        }
-        return ret;
-#endif
 #ifdef TARGET_NR_creat /* not on alpha */
     case TARGET_NR_creat:
         if (!(p = lock_user_string(arg1)))
@@ -7022,33 +6982,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         return do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
                           arg6, arg7, arg8, 0);
 #endif
-    case TARGET_NR_wait4:
-        {
-            int status;
-            abi_long status_ptr = arg2;
-            struct rusage rusage, *rusage_ptr;
-            abi_ulong target_rusage = arg4;
-            abi_long rusage_err;
-            if (target_rusage)
-                rusage_ptr = &rusage;
-            else
-                rusage_ptr = NULL;
-            ret = get_errno(safe_wait4(arg1, &status, arg3, rusage_ptr));
-            if (!is_error(ret)) {
-                if (status_ptr && ret) {
-                    status = host_to_target_waitstatus(status);
-                    if (put_user_s32(status, status_ptr))
-                        return -TARGET_EFAULT;
-                }
-                if (target_rusage) {
-                    rusage_err = host_to_target_rusage(target_rusage, &rusage);
-                    if (rusage_err) {
-                        ret = rusage_err;
-                    }
-                }
-            }
-        }
-        return ret;
 #ifdef TARGET_NR_swapoff
     case TARGET_NR_swapoff:
         if (!(p = lock_user_string(arg1)))
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 76d983a882..759b35458e 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1494,15 +1494,6 @@
 #ifdef TARGET_NR_vserver
 { TARGET_NR_vserver, "vserver" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_wait4
-{ TARGET_NR_wait4, "wait4" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_waitid
-{ TARGET_NR_waitid, "waitid" , "%s(%#x,%d,%p,%#x)", NULL, NULL },
-#endif
-#ifdef TARGET_NR_waitpid
-{ TARGET_NR_waitpid, "waitpid" , "%s(%d,%p,%#x)", NULL, NULL },
-#endif
 #ifdef TARGET_NR_utimensat
 { TARGET_NR_utimensat, "utimensat", NULL, print_utimensat, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 19/74] linux-user: Implement rusage argument to waitid
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (17 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 18/74] linux-user: Split out wait4, waitid, waitpid Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 20/74] linux-user: Split out creat Richard Henderson
                   ` (57 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

The kernel interface, which we are supposed to be implementing,
takes a fifth argument: an rusage pointer akin to wait4.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  2 +-
 linux-user/syscall-proc.inc.c | 27 +++++++++++++++++++--------
 2 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index a84050a318..f099d98fa3 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -119,7 +119,7 @@ SYSCALL_DEF(shmget, ARG_DEC, ARG_DEC, ARG_HEX);
 SYSCALL_DEF_FULL(vfork, .impl = impl_fork);
 #endif
 SYSCALL_DEF(wait4, ARG_DEC, ARG_PTR, ARG_HEX, ARG_PTR);
-SYSCALL_DEF(waitid, ARG_HEX, ARG_DEC, ARG_PTR, ARG_HEX);
+SYSCALL_DEF(waitid, ARG_HEX, ARG_DEC, ARG_PTR, ARG_HEX, ARG_PTR);
 #ifdef TARGET_NR_waitpid
 SYSCALL_DEF(waitpid, ARG_DEC, ARG_PTR, ARG_HEX);
 #endif
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
index 7c647f36d7..b7304b7a42 100644
--- a/linux-user/syscall-proc.inc.c
+++ b/linux-user/syscall-proc.inc.c
@@ -370,19 +370,30 @@ SYSCALL_IMPL(waitid)
     id_t id = arg2;
     abi_ulong target_info = arg3;
     int options = arg4;
+    abi_ulong target_rusage = arg5;
     siginfo_t info, *info_ptr = target_info ? &info : NULL;
+    struct rusage rusage;
+    struct rusage *rusage_ptr = target_rusage ? &rusage : NULL;
     abi_long ret;
 
     info.si_pid = 0;
-    ret = get_errno(safe_waitid(idtype, id, info_ptr, options, NULL));
-    if (!is_error(ret) && target_info && info.si_pid != 0) {
-        target_siginfo_t *p = lock_user(VERIFY_WRITE, target_info,
-                                        sizeof(target_siginfo_t), 0);
-        if (!p) {
-            return -TARGET_EFAULT;
+    ret = get_errno(safe_waitid(idtype, id, info_ptr, options, rusage_ptr));
+    if (!is_error(ret)) {
+        if (target_info && info.si_pid != 0) {
+            target_siginfo_t *p = lock_user(VERIFY_WRITE, target_info,
+                                            sizeof(target_siginfo_t), 0);
+            if (!p) {
+                return -TARGET_EFAULT;
+            }
+            host_to_target_siginfo(p, &info);
+            unlock_user(p, target_info, sizeof(target_siginfo_t));
+        }
+        if (target_rusage) {
+            abi_long err = host_to_target_rusage(target_rusage, &rusage);
+            if (err) {
+                ret = err;
+            }
         }
-        host_to_target_siginfo(p, &info);
-        unlock_user(p, target_info, sizeof(target_siginfo_t));
     }
     return ret;
 }
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 20/74] linux-user: Split out creat
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (18 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 19/74] linux-user: Implement rusage argument to waitid Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 21/74] linux-user: Split out link, linkat Richard Henderson
                   ` (56 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  3 +++
 linux-user/strace.c           | 13 -------------
 linux-user/syscall-file.inc.c | 16 ++++++++++++++++
 linux-user/syscall.c          |  9 ---------
 linux-user/strace.list        |  3 ---
 5 files changed, 19 insertions(+), 25 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index f099d98fa3..de7a99f0c6 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -21,6 +21,9 @@ SYSCALL_DEF_FULL(brk, .impl = impl_brk,
                  .arg_type = { ARG_PTR });
 SYSCALL_DEF_ARGS(clone, ARG_CLONEFLAG, ARG_PTR, ARG_PTR, ARG_PTR, ARG_PTR);
 SYSCALL_DEF(close, ARG_DEC);
+#ifdef TARGET_NR_creat
+SYSCALL_DEF(creat, ARG_STR, ARG_MODEFLAG);
+#endif
 SYSCALL_DEF(exit, ARG_DEC);
 #ifdef TARGET_NR_fork
 SYSCALL_DEF(fork);
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 842136e425..640a80f32b 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1195,19 +1195,6 @@ print_clock_adjtime(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_creat
-static void
-print_creat(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 0);
-    print_file_mode(arg1, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_execv
 static void
 print_execv(const struct syscallname *name,
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index dd44d5b804..9b966ad627 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -24,6 +24,22 @@ SYSCALL_IMPL(close)
     return get_errno(close(fd));
 }
 
+#ifdef TARGET_NR_creat
+SYSCALL_IMPL(creat)
+{
+    char *p = lock_user_string(arg1);
+    abi_long ret;
+
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(creat(p, arg2));
+    fd_trans_unregister(ret);
+    unlock_user(p, arg1, 0);
+    return ret;
+}
+#endif
+
 /*
  * Helpers for do_openat, manipulating /proc/self/foo.
  */
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index bdb0d45d9a..491e1d7cfb 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5383,15 +5383,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_creat /* not on alpha */
-    case TARGET_NR_creat:
-        if (!(p = lock_user_string(arg1)))
-            return -TARGET_EFAULT;
-        ret = get_errno(creat(p, arg2));
-        fd_trans_unregister(ret);
-        unlock_user(p, arg1, 0);
-        return ret;
-#endif
 #ifdef TARGET_NR_link
     case TARGET_NR_link:
         {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 759b35458e..41f8f8d0d0 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -94,9 +94,6 @@
 #ifdef TARGET_NR_connect
 { TARGET_NR_connect, "connect" , "%s(%d,%#x,%d)", NULL, NULL },
 #endif
-#ifdef TARGET_NR_creat
-{ TARGET_NR_creat, "creat" , NULL, print_creat, NULL },
-#endif
 #ifdef TARGET_NR_create_module
 { TARGET_NR_create_module, "create_module" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 21/74] linux-user: Split out link, linkat
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (19 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 20/74] linux-user: Split out creat Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 22/74] linux-user: Split out unlink, unlinkat, rmdir Richard Henderson
                   ` (55 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Note that linkat is universally provided.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  4 ++++
 linux-user/strace.c           | 29 -----------------------------
 linux-user/syscall-file.inc.c | 28 ++++++++++++++++++++++++++++
 linux-user/syscall.c          | 32 --------------------------------
 linux-user/strace.list        |  6 ------
 5 files changed, 32 insertions(+), 67 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index de7a99f0c6..41dd887dbc 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -31,6 +31,10 @@ SYSCALL_DEF(fork);
 #ifdef TARGET_NR_ipc
 SYSCALL_DEF_ARGS(ipc, ARG_HEX, ARG_DEC, ARG_DEC, ARG_HEX, ARG_PTR, ARG_HEX);
 #endif
+#ifdef TARGET_NR_link
+SYSCALL_DEF(link, ARG_STR, ARG_STR);
+#endif
+SYSCALL_DEF(linkat, ARG_ATDIRFD, ARG_STR, ARG_ATDIRFD, ARG_STR, ARG_ATFLAG);
 SYSCALL_DEF(mlock, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(mlockall, ARG_HEX);
 #ifdef TARGET_NR_mmap
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 640a80f32b..feb8ec7c09 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1369,35 +1369,6 @@ print_futimesat(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_link
-static void
-print_link(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 0);
-    print_string(arg1, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
-#ifdef TARGET_NR_linkat
-static void
-print_linkat(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_at_dirfd(arg0, 0);
-    print_string(arg1, 0);
-    print_at_dirfd(arg2, 0);
-    print_string(arg3, 0);
-    print_flags(at_file_flags, arg4, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR__llseek
 static void
 print__llseek(const struct syscallname *name,
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 9b966ad627..440ff5ed14 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -40,6 +40,34 @@ SYSCALL_IMPL(creat)
 }
 #endif
 
+static abi_long do_linkat(int olddirfd, abi_ulong target_oldpath,
+                          int newdirfd, abi_ulong target_newpath,
+                          int flags)
+{
+    char *oldpath = lock_user_string(target_oldpath);
+    char *newpath = lock_user_string(target_newpath);
+    abi_long ret = -TARGET_EFAULT;
+
+    if (oldpath && newpath) {
+        ret = get_errno(linkat(olddirfd, oldpath, newdirfd, newpath, flags));
+    }
+    unlock_user(oldpath, target_oldpath, 0);
+    unlock_user(newpath, target_newpath, 0);
+    return ret;
+}
+
+#ifdef TARGET_NR_link
+SYSCALL_IMPL(link)
+{
+    return do_linkat(AT_FDCWD, arg1, AT_FDCWD, arg2, 0);
+}
+#endif
+
+SYSCALL_IMPL(linkat)
+{
+    return do_linkat(arg1, arg2, arg3, arg4, arg5);
+}
+
 /*
  * Helpers for do_openat, manipulating /proc/self/foo.
  */
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 491e1d7cfb..865129df9e 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5383,38 +5383,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_link
-    case TARGET_NR_link:
-        {
-            void * p2;
-            p = lock_user_string(arg1);
-            p2 = lock_user_string(arg2);
-            if (!p || !p2)
-                ret = -TARGET_EFAULT;
-            else
-                ret = get_errno(link(p, p2));
-            unlock_user(p2, arg2, 0);
-            unlock_user(p, arg1, 0);
-        }
-        return ret;
-#endif
-#if defined(TARGET_NR_linkat)
-    case TARGET_NR_linkat:
-        {
-            void * p2 = NULL;
-            if (!arg2 || !arg4)
-                return -TARGET_EFAULT;
-            p  = lock_user_string(arg2);
-            p2 = lock_user_string(arg4);
-            if (!p || !p2)
-                ret = -TARGET_EFAULT;
-            else
-                ret = get_errno(linkat(arg1, p, arg3, p2, arg5));
-            unlock_user(p, arg2, 0);
-            unlock_user(p2, arg4, 0);
-        }
-        return ret;
-#endif
 #ifdef TARGET_NR_unlink
     case TARGET_NR_unlink:
         if (!(p = lock_user_string(arg1)))
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 41f8f8d0d0..f3c54cec69 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -461,12 +461,6 @@
 #ifdef TARGET_NR_lgetxattr
 { TARGET_NR_lgetxattr, "lgetxattr" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_link
-{ TARGET_NR_link, "link" , NULL, print_link, NULL },
-#endif
-#ifdef TARGET_NR_linkat
-{ TARGET_NR_linkat, "linkat" , NULL, print_linkat, NULL },
-#endif
 #ifdef TARGET_NR_Linux
 { TARGET_NR_Linux, "Linux" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 22/74] linux-user: Split out unlink, unlinkat, rmdir
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (20 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 21/74] linux-user: Split out link, linkat Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 23/74] linux-user: Split out execve Richard Henderson
                   ` (54 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Note that unlinkat is universally provided.
Implement rmdir in terms of unlinkat.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  7 ++++++
 linux-user/syscall.h          |  1 +
 linux-user/strace.c           | 43 ++++-------------------------------
 linux-user/syscall-file.inc.c | 32 ++++++++++++++++++++++++++
 linux-user/syscall.c          | 24 -------------------
 linux-user/strace.list        |  9 --------
 6 files changed, 44 insertions(+), 72 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 41dd887dbc..78d3f600eb 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -98,6 +98,9 @@ SYSCALL_DEF(readlink, ARG_STR, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(readlinkat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_DEC);
 #endif
 SYSCALL_DEF(readv, ARG_DEC, ARG_PTR, ARG_DEC);
+#ifdef TARGET_NR_rmdir
+SYSCALL_DEF(rmdir, ARG_STR);
+#endif
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semctl)
 SYSCALL_DEF(semctl, ARG_DEC, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
@@ -121,6 +124,10 @@ SYSCALL_DEF(shmdt, ARG_PTR);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_shmget)
 SYSCALL_DEF(shmget, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
+#ifdef TARGET_NR_unlink
+SYSCALL_DEF(unlink, ARG_STR);
+#endif
+SYSCALL_DEF(unlinkat, ARG_ATDIRFD, ARG_STR, ARG_UNLINKATFLAG);
 #ifdef TARGET_NR_vfork
 /* Emulate vfork() with fork().  */
 SYSCALL_DEF_FULL(vfork, .impl = impl_fork);
diff --git a/linux-user/syscall.h b/linux-user/syscall.h
index f75cd3ddd0..bdc4d653c4 100644
--- a/linux-user/syscall.h
+++ b/linux-user/syscall.h
@@ -63,6 +63,7 @@ typedef enum {
     ARG_MMAPPROT,
     ARG_MODEFLAG,
     ARG_OPENFLAG,
+    ARG_UNLINKATFLAG,
 
     /* These are interpreted as pointers.  */
     ARG_PTR,
diff --git a/linux-user/strace.c b/linux-user/strace.c
index feb8ec7c09..9ac0b859da 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -684,7 +684,7 @@ static struct flags const at_file_flags[] = {
     FLAG_END,
 };
 
-UNUSED static struct flags unlinkat_flags[] = {
+static struct flags const unlinkat_flags[] = {
 #ifdef AT_REMOVEDIR
     FLAG_GENERIC(AT_REMOVEDIR),
 #endif
@@ -1810,18 +1810,6 @@ print_mkdirat(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_rmdir
-static void
-print_rmdir(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 0);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_rt_sigaction
 static void
 print_rt_sigaction(const struct syscallname *name,
@@ -2187,32 +2175,6 @@ print_umount2(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_unlink
-static void
-print_unlink(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
-#ifdef TARGET_NR_unlinkat
-static void
-print_unlinkat(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_at_dirfd(arg0, 0);
-    print_string(arg1, 0);
-    print_flags(unlinkat_flags, arg2, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_utime
 static void
 print_utime(const struct syscallname *name,
@@ -2475,6 +2437,9 @@ static void print_syscall_def1(const SyscallDef *def, int64_t args[6])
         case ARG_OPENFLAG:
             len = add_open_flags(b, rest, arg);
             break;
+        case ARG_UNLINKATFLAG:
+            len = add_flags(b, rest, unlinkat_flags, arg, true);
+            break;
         case ARG_PTR:
             len = add_pointer(b, rest, arg);
             break;
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 440ff5ed14..5acd8ecc10 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -662,6 +662,38 @@ SYSCALL_IMPL(readlinkat)
 }
 #endif
 
+static abi_long do_unlinkat(int dirfd, abi_ulong target_path, int flags)
+{
+    char *p = lock_user_string(target_path);
+    abi_long ret;
+
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(unlinkat(dirfd, p, flags));
+    unlock_user(p, target_path, 0);
+    return ret;
+}
+
+#ifdef TARGET_NR_unlink
+SYSCALL_IMPL(unlink)
+{
+    return do_unlinkat(AT_FDCWD, arg1, 0);
+}
+#endif
+
+#ifdef TARGET_NR_rmdir
+SYSCALL_IMPL(rmdir)
+{
+    return do_unlinkat(AT_FDCWD, arg1, AT_REMOVEDIR);
+}
+#endif
+
+SYSCALL_IMPL(unlinkat)
+{
+    return do_unlinkat(arg1, arg2, arg3);
+}
+
 SYSCALL_IMPL(write)
 {
     int fd = arg1;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 865129df9e..53e108b614 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5383,22 +5383,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_unlink
-    case TARGET_NR_unlink:
-        if (!(p = lock_user_string(arg1)))
-            return -TARGET_EFAULT;
-        ret = get_errno(unlink(p));
-        unlock_user(p, arg1, 0);
-        return ret;
-#endif
-#if defined(TARGET_NR_unlinkat)
-    case TARGET_NR_unlinkat:
-        if (!(p = lock_user_string(arg2)))
-            return -TARGET_EFAULT;
-        ret = get_errno(unlinkat(arg1, p, arg3));
-        unlock_user(p, arg2, 0);
-        return ret;
-#endif
     case TARGET_NR_execve:
         {
             char **argp, **envp;
@@ -5790,14 +5774,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         ret = get_errno(mkdirat(arg1, p, arg3));
         unlock_user(p, arg2, 0);
         return ret;
-#endif
-#ifdef TARGET_NR_rmdir
-    case TARGET_NR_rmdir:
-        if (!(p = lock_user_string(arg1)))
-            return -TARGET_EFAULT;
-        ret = get_errno(rmdir(p));
-        unlock_user(p, arg1, 0);
-        return ret;
 #endif
     case TARGET_NR_dup:
         ret = get_errno(dup(arg1));
diff --git a/linux-user/strace.list b/linux-user/strace.list
index f3c54cec69..f08ddaddac 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -527,9 +527,6 @@
 #ifdef TARGET_NR_mkdirat
 { TARGET_NR_mkdirat, "mkdirat" , NULL, print_mkdirat, NULL },
 #endif
-#ifdef TARGET_NR_rmdir
-{ TARGET_NR_rmdir, "rmdir" , NULL, print_rmdir, NULL },
-#endif
 #ifdef TARGET_NR_mknod
 { TARGET_NR_mknod, "mknod" , NULL, print_mknod, NULL },
 #endif
@@ -1425,12 +1422,6 @@
 #ifdef TARGET_NR_uname
 { TARGET_NR_uname, "uname" , "%s(%p)", NULL, NULL },
 #endif
-#ifdef TARGET_NR_unlink
-{ TARGET_NR_unlink, "unlink" , NULL, print_unlink, NULL },
-#endif
-#ifdef TARGET_NR_unlinkat
-{ TARGET_NR_unlinkat, "unlinkat" , NULL, print_unlinkat, NULL },
-#endif
 #ifdef TARGET_NR_unshare
 { TARGET_NR_unshare, "unshare" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 23/74] linux-user: Split out execve
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (21 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 22/74] linux-user: Split out unlink, unlinkat, rmdir Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 24/74] linux-user: Implement execveat Richard Henderson
                   ` (53 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |   1 +
 linux-user/strace.c           |  32 ----------
 linux-user/syscall-proc.inc.c | 110 ++++++++++++++++++++++++++++++++++
 linux-user/syscall.c          |  97 ------------------------------
 linux-user/strace.list        |   3 -
 5 files changed, 111 insertions(+), 132 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 78d3f600eb..58fef48666 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -25,6 +25,7 @@ SYSCALL_DEF(close, ARG_DEC);
 SYSCALL_DEF(creat, ARG_STR, ARG_MODEFLAG);
 #endif
 SYSCALL_DEF(exit, ARG_DEC);
+SYSCALL_DEF(execve, ARG_STR, ARG_PTR, ARG_PTR);
 #ifdef TARGET_NR_fork
 SYSCALL_DEF(fork);
 #endif
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 9ac0b859da..9d6c765715 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -568,38 +568,6 @@ print_newselect(const struct syscallname *name,
 }
 #endif
 
-static void
-print_execve(const struct syscallname *name,
-             abi_long arg1, abi_long arg2, abi_long arg3,
-             abi_long arg4, abi_long arg5, abi_long arg6)
-{
-    abi_ulong arg_ptr_addr;
-    char *s;
-
-    if (!(s = lock_user_string(arg1)))
-        return;
-    gemu_log("%s(\"%s\",{", name->name, s);
-    unlock_user(s, arg1, 0);
-
-    for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) {
-        abi_ulong *arg_ptr, arg_addr;
-
-        arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1);
-        if (!arg_ptr)
-            return;
-    arg_addr = tswapal(*arg_ptr);
-        unlock_user(arg_ptr, arg_ptr_addr, 0);
-        if (!arg_addr)
-            break;
-        if ((s = lock_user_string(arg_addr))) {
-            gemu_log("\"%s\",", s);
-            unlock_user(s, arg_addr, 0);
-        }
-    }
-
-    gemu_log("NULL})");
-}
-
 /*
  * Variants for the return value output function
  */
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
index b7304b7a42..66ad768551 100644
--- a/linux-user/syscall-proc.inc.c
+++ b/linux-user/syscall-proc.inc.c
@@ -269,6 +269,116 @@ SYSCALL_IMPL(clone)
     return do_clone(cpu_env, arg1, arg2, arg3, arg4, arg5);
 }
 
+SYSCALL_IMPL(execve)
+{
+    char **argp, **envp;
+    int argc, envc;
+    abi_ulong gp;
+    abi_ulong guest_path = arg1;
+    abi_ulong guest_argp = arg2;
+    abi_ulong guest_envp = arg3;
+    abi_ulong addr;
+    char **q, *p;
+    int total_size = 0;
+    abi_long ret = -TARGET_EFAULT;
+
+    argc = 0;
+    for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
+        if (get_user_ual(addr, gp)) {
+            goto execve_nofree;
+        }
+        if (!addr) {
+            break;
+        }
+        argc++;
+    }
+    envc = 0;
+    for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
+        if (get_user_ual(addr, gp)) {
+            goto execve_nofree;
+        }
+        if (!addr) {
+            break;
+        }
+        envc++;
+    }
+
+    argp = g_new0(char *, argc + 1);
+    envp = g_new0(char *, envc + 1);
+
+    for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) {
+        char *this_q;
+
+        if (get_user_ual(addr, gp)) {
+            goto execve_free;
+        }
+        if (!addr) {
+            break;
+        }
+        this_q = lock_user_string(addr);
+        if (!this_q) {
+            goto execve_free;
+        }
+        *q = this_q;
+        total_size += strlen(this_q) + 1;
+    }
+
+    for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) {
+        char *this_q;
+
+        if (get_user_ual(addr, gp)) {
+            goto execve_free;
+        }
+        if (!addr) {
+            break;
+        }
+        this_q = lock_user_string(addr);
+        if (!this_q) {
+            goto execve_free;
+        }
+        *q = this_q;
+        total_size += strlen(this_q) + 1;
+    }
+
+    p = lock_user_string(guest_path);
+    if (!p) {
+        goto execve_free;
+    }
+
+    /*
+     * Although execve() is not an interruptible syscall it is
+     * a special case where we must use the safe_syscall wrapper:
+     * if we allow a signal to happen before we make the host
+     * syscall then we will 'lose' it, because at the point of
+     * execve the process leaves QEMU's control. So we use the
+     * safe syscall wrapper to ensure that we either take the
+     * signal as a guest signal, or else it does not happen
+     * before the execve completes and makes it the other
+     * program's problem.
+     */
+    ret = get_errno(safe_execve(p, argp, envp));
+    unlock_user(p, guest_path, 0);
+
+ execve_free:
+    for (gp = guest_argp, q = argp; *q; gp += sizeof(abi_ulong), q++) {
+        if (get_user_ual(addr, gp) || !addr) {
+            break;
+        }
+        unlock_user(*q, addr, 0);
+    }
+    for (gp = guest_envp, q = envp; *q; gp += sizeof(abi_ulong), q++) {
+        if (get_user_ual(addr, gp) || !addr) {
+            break;
+        }
+        unlock_user(*q, addr, 0);
+    }
+    g_free(argp);
+    g_free(envp);
+
+ execve_nofree:
+    return ret;
+}
+
 SYSCALL_IMPL(exit)
 {
     CPUState *cpu = ENV_GET_CPU(cpu_env);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 53e108b614..a00df1162f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5383,103 +5383,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_execve:
-        {
-            char **argp, **envp;
-            int argc, envc;
-            abi_ulong gp;
-            abi_ulong guest_argp;
-            abi_ulong guest_envp;
-            abi_ulong addr;
-            char **q;
-            int total_size = 0;
-
-            argc = 0;
-            guest_argp = arg2;
-            for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
-                if (get_user_ual(addr, gp))
-                    return -TARGET_EFAULT;
-                if (!addr)
-                    break;
-                argc++;
-            }
-            envc = 0;
-            guest_envp = arg3;
-            for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
-                if (get_user_ual(addr, gp))
-                    return -TARGET_EFAULT;
-                if (!addr)
-                    break;
-                envc++;
-            }
-
-            argp = g_new0(char *, argc + 1);
-            envp = g_new0(char *, envc + 1);
-
-            for (gp = guest_argp, q = argp; gp;
-                  gp += sizeof(abi_ulong), q++) {
-                if (get_user_ual(addr, gp))
-                    goto execve_efault;
-                if (!addr)
-                    break;
-                if (!(*q = lock_user_string(addr)))
-                    goto execve_efault;
-                total_size += strlen(*q) + 1;
-            }
-            *q = NULL;
-
-            for (gp = guest_envp, q = envp; gp;
-                  gp += sizeof(abi_ulong), q++) {
-                if (get_user_ual(addr, gp))
-                    goto execve_efault;
-                if (!addr)
-                    break;
-                if (!(*q = lock_user_string(addr)))
-                    goto execve_efault;
-                total_size += strlen(*q) + 1;
-            }
-            *q = NULL;
-
-            if (!(p = lock_user_string(arg1)))
-                goto execve_efault;
-            /* Although execve() is not an interruptible syscall it is
-             * a special case where we must use the safe_syscall wrapper:
-             * if we allow a signal to happen before we make the host
-             * syscall then we will 'lose' it, because at the point of
-             * execve the process leaves QEMU's control. So we use the
-             * safe syscall wrapper to ensure that we either take the
-             * signal as a guest signal, or else it does not happen
-             * before the execve completes and makes it the other
-             * program's problem.
-             */
-            ret = get_errno(safe_execve(p, argp, envp));
-            unlock_user(p, arg1, 0);
-
-            goto execve_end;
-
-        execve_efault:
-            ret = -TARGET_EFAULT;
-
-        execve_end:
-            for (gp = guest_argp, q = argp; *q;
-                  gp += sizeof(abi_ulong), q++) {
-                if (get_user_ual(addr, gp)
-                    || !addr)
-                    break;
-                unlock_user(*q, addr, 0);
-            }
-            for (gp = guest_envp, q = envp; *q;
-                  gp += sizeof(abi_ulong), q++) {
-                if (get_user_ual(addr, gp)
-                    || !addr)
-                    break;
-                unlock_user(*q, addr, 0);
-            }
-
-            g_free(argp);
-            g_free(envp);
-        }
-        return ret;
     case TARGET_NR_chdir:
         if (!(p = lock_user_string(arg1)))
             return -TARGET_EFAULT;
diff --git a/linux-user/strace.list b/linux-user/strace.list
index f08ddaddac..39e5c5b1aa 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -139,9 +139,6 @@
 #ifdef TARGET_NR_execv
 { TARGET_NR_execv, "execv" , NULL, print_execv, NULL },
 #endif
-#ifdef TARGET_NR_execve
-{ TARGET_NR_execve, "execve" , NULL, print_execve, NULL },
-#endif
 #ifdef TARGET_NR_execveat
 { TARGET_NR_execveat, "execveat" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 24/74] linux-user: Implement execveat
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (22 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 23/74] linux-user: Split out execve Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 25/74] linux-user: Split out chdir Richard Henderson
                   ` (52 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

A trivial extension to our current execve implementation
to support the new(ish) syscall.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  1 +
 linux-user/syscall-proc.inc.c | 19 ++++++++++++++-----
 linux-user/syscall.c          |  3 ++-
 linux-user/strace.list        |  3 ---
 4 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 58fef48666..392bd1579c 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -26,6 +26,7 @@ SYSCALL_DEF(creat, ARG_STR, ARG_MODEFLAG);
 #endif
 SYSCALL_DEF(exit, ARG_DEC);
 SYSCALL_DEF(execve, ARG_STR, ARG_PTR, ARG_PTR);
+SYSCALL_DEF(execveat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_PTR, ARG_ATFLAG);
 #ifdef TARGET_NR_fork
 SYSCALL_DEF(fork);
 #endif
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
index 66ad768551..fd114d1f03 100644
--- a/linux-user/syscall-proc.inc.c
+++ b/linux-user/syscall-proc.inc.c
@@ -269,14 +269,13 @@ SYSCALL_IMPL(clone)
     return do_clone(cpu_env, arg1, arg2, arg3, arg4, arg5);
 }
 
-SYSCALL_IMPL(execve)
+static abi_long do_execveat(int dirfd, abi_ulong guest_path,
+                            abi_ulong guest_argp, abi_ulong guest_envp,
+                            int flags)
 {
     char **argp, **envp;
     int argc, envc;
     abi_ulong gp;
-    abi_ulong guest_path = arg1;
-    abi_ulong guest_argp = arg2;
-    abi_ulong guest_envp = arg3;
     abi_ulong addr;
     char **q, *p;
     int total_size = 0;
@@ -356,7 +355,7 @@ SYSCALL_IMPL(execve)
      * before the execve completes and makes it the other
      * program's problem.
      */
-    ret = get_errno(safe_execve(p, argp, envp));
+    ret = get_errno(safe_execveat(dirfd, p, argp, envp, flags));
     unlock_user(p, guest_path, 0);
 
  execve_free:
@@ -379,6 +378,16 @@ SYSCALL_IMPL(execve)
     return ret;
 }
 
+SYSCALL_IMPL(execve)
+{
+    return do_execveat(AT_FDCWD, arg1, arg2, arg3, 0);
+}
+
+SYSCALL_IMPL(execveat)
+{
+    return do_execveat(arg1, arg2, arg3, arg4, arg5);
+}
+
 SYSCALL_IMPL(exit)
 {
     CPUState *cpu = ENV_GET_CPU(cpu_env);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index a00df1162f..affcd81273 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -672,7 +672,8 @@ safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
               struct rusage *, rusage)
 safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
               int, options, struct rusage *, rusage)
-safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp)
+safe_syscall5(int, execveat, int, dirfd, const char *, filename,
+              char **, argv, char **, envp, int, flags)
 safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
               fd_set *, exceptfds, struct timespec *, timeout, void *, sig)
 safe_syscall5(int, ppoll, struct pollfd *, ufds, unsigned int, nfds,
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 39e5c5b1aa..c6bb475728 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -139,9 +139,6 @@
 #ifdef TARGET_NR_execv
 { TARGET_NR_execv, "execv" , NULL, print_execv, NULL },
 #endif
-#ifdef TARGET_NR_execveat
-{ TARGET_NR_execveat, "execveat" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_exec_with_loader
 { TARGET_NR_exec_with_loader, "exec_with_loader" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 25/74] linux-user: Split out chdir
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (23 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 24/74] linux-user: Implement execveat Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 26/74] linux-user: Split out time Richard Henderson
                   ` (51 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Note that chdir is universally provided.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  1 +
 linux-user/strace.c           | 12 ------------
 linux-user/syscall-file.inc.c | 14 ++++++++++++++
 linux-user/syscall.c          |  6 ------
 linux-user/strace.list        |  3 ---
 5 files changed, 15 insertions(+), 21 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 392bd1579c..3fad9d51f0 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -19,6 +19,7 @@
 SYSCALL_DEF_FULL(brk, .impl = impl_brk,
                  .print_ret = print_syscall_ptr_ret,
                  .arg_type = { ARG_PTR });
+SYSCALL_DEF(chdir, ARG_STR);
 SYSCALL_DEF_ARGS(clone, ARG_CLONEFLAG, ARG_PTR, ARG_PTR, ARG_PTR, ARG_PTR);
 SYSCALL_DEF(close, ARG_DEC);
 #ifdef TARGET_NR_creat
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 9d6c765715..b234274034 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1113,18 +1113,6 @@ print_access(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_chdir
-static void
-print_chdir(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_chroot
 static void
 print_chroot(const struct syscallname *name,
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 5acd8ecc10..76637fe71b 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -16,6 +16,20 @@
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+SYSCALL_IMPL(chdir)
+{
+    abi_ulong target_path = arg1;
+    char *p = lock_user_string(target_path);
+    abi_long ret;
+
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(chdir(p));
+    unlock_user(p, target_path, 0);
+    return ret;
+}
+
 SYSCALL_IMPL(close)
 {
     int fd = arg1;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index affcd81273..0bf5901014 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5384,12 +5384,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_chdir:
-        if (!(p = lock_user_string(arg1)))
-            return -TARGET_EFAULT;
-        ret = get_errno(chdir(p));
-        unlock_user(p, arg1, 0);
-        return ret;
 #ifdef TARGET_NR_time
     case TARGET_NR_time:
         {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index c6bb475728..3f79159b63 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -61,9 +61,6 @@
 #ifdef TARGET_NR_capset
 { TARGET_NR_capset, "capset" , "%s(%p,%p)", NULL, NULL },
 #endif
-#ifdef TARGET_NR_chdir
-{ TARGET_NR_chdir, "chdir" , NULL, print_chdir, NULL },
-#endif
 #ifdef TARGET_NR_chmod
 { TARGET_NR_chmod, "chmod" , NULL, print_chmod, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 26/74] linux-user: Split out time
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (24 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 25/74] linux-user: Split out chdir Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 27/74] linux-user: Split out mknod, mknodat Richard Henderson
                   ` (50 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  3 +++
 linux-user/syscall-time.inc.c | 32 ++++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 13 +------------
 linux-user/strace.list        |  3 ---
 4 files changed, 36 insertions(+), 15 deletions(-)
 create mode 100644 linux-user/syscall-time.inc.c

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 3fad9d51f0..9950b73e76 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -127,6 +127,9 @@ SYSCALL_DEF(shmdt, ARG_PTR);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_shmget)
 SYSCALL_DEF(shmget, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
+#ifdef TARGET_NR_time
+SYSCALL_DEF(time, ARG_PTR);
+#endif
 #ifdef TARGET_NR_unlink
 SYSCALL_DEF(unlink, ARG_STR);
 #endif
diff --git a/linux-user/syscall-time.inc.c b/linux-user/syscall-time.inc.c
new file mode 100644
index 0000000000..14fec88e47
--- /dev/null
+++ b/linux-user/syscall-time.inc.c
@@ -0,0 +1,32 @@
+/*
+ *  Linux time related syscalls
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef TARGET_NR_time
+SYSCALL_IMPL(time)
+{
+    time_t host_time;
+    abi_long ret = get_errno(time(&host_time));
+
+    if (!is_error(ret)
+        && arg1
+        && put_user_sal(host_time, arg1)) {
+        return -TARGET_EFAULT;
+    }
+    return ret;
+}
+#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 0bf5901014..ea89734706 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5384,18 +5384,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_time
-    case TARGET_NR_time:
-        {
-            time_t host_time;
-            ret = get_errno(time(&host_time));
-            if (!is_error(ret)
-                && arg1
-                && put_user_sal(host_time, arg1))
-                return -TARGET_EFAULT;
-        }
-        return ret;
-#endif
 #ifdef TARGET_NR_mknod
     case TARGET_NR_mknod:
         if (!(p = lock_user_string(arg1)))
@@ -9392,6 +9380,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
 #include "syscall-ipc.inc.c"
 #include "syscall-mem.inc.c"
 #include "syscall-proc.inc.c"
+#include "syscall-time.inc.c"
 
 #undef SYSCALL_IMPL
 #undef SYSCALL_ARGS
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 3f79159b63..95706a696b 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1350,9 +1350,6 @@
 #ifdef TARGET_NR_tgkill
 { TARGET_NR_tgkill, "tgkill" , NULL, print_tgkill, NULL },
 #endif
-#ifdef TARGET_NR_time
-{ TARGET_NR_time, "time" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_timer_create
 { TARGET_NR_timer_create, "timer_create" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 27/74] linux-user: Split out mknod, mknodat
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (25 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 26/74] linux-user: Split out time Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 28/74] linux-user: Split out chmod, fchmod, fchmodat Richard Henderson
                   ` (49 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Note that mknodat is universally provided.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  4 ++++
 linux-user/strace.c           | 39 -----------------------------------
 linux-user/syscall-file.inc.c | 26 +++++++++++++++++++++++
 linux-user/syscall.c          | 16 --------------
 linux-user/strace.list        |  6 ------
 5 files changed, 30 insertions(+), 61 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 9950b73e76..b5951e6911 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -38,6 +38,10 @@ SYSCALL_DEF_ARGS(ipc, ARG_HEX, ARG_DEC, ARG_DEC, ARG_HEX, ARG_PTR, ARG_HEX);
 SYSCALL_DEF(link, ARG_STR, ARG_STR);
 #endif
 SYSCALL_DEF(linkat, ARG_ATDIRFD, ARG_STR, ARG_ATDIRFD, ARG_STR, ARG_ATFLAG);
+#ifdef TARGET_NR_mknod
+SYSCALL_DEF(mknod, ARG_STR, ARG_MODEFLAG, ARG_HEX);
+#endif
+SYSCALL_DEF(mknodat, ARG_ATDIRFD, ARG_STR, ARG_MODEFLAG, ARG_HEX);
 SYSCALL_DEF(mlock, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(mlockall, ARG_HEX);
 #ifdef TARGET_NR_mmap
diff --git a/linux-user/strace.c b/linux-user/strace.c
index b234274034..c70c06d965 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1923,45 +1923,6 @@ print_syslog(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_mknod
-static void
-print_mknod(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    int hasdev = (arg1 & (S_IFCHR|S_IFBLK));
-
-    print_syscall_prologue(name);
-    print_string(arg0, 0);
-    print_file_mode(arg1, (hasdev == 0));
-    if (hasdev) {
-        print_raw_param("makedev(%d", major(arg2), 0);
-        print_raw_param("%d)", minor(arg2), 1);
-    }
-    print_syscall_epilogue(name);
-}
-#endif
-
-#ifdef TARGET_NR_mknodat
-static void
-print_mknodat(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    int hasdev = (arg2 & (S_IFCHR|S_IFBLK));
-
-    print_syscall_prologue(name);
-    print_at_dirfd(arg0, 0);
-    print_string(arg1, 0);
-    print_file_mode(arg2, (hasdev == 0));
-    if (hasdev) {
-        print_raw_param("makedev(%d", major(arg3), 0);
-        print_raw_param("%d)", minor(arg3), 1);
-    }
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_mq_open
 static void
 print_mq_open(const struct syscallname *name,
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 76637fe71b..3adb629124 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -82,6 +82,32 @@ SYSCALL_IMPL(linkat)
     return do_linkat(arg1, arg2, arg3, arg4, arg5);
 }
 
+static abi_long do_mknodat(int dirfd, abi_ulong target_path,
+                           mode_t mode, dev_t dev)
+{
+    char *p = lock_user_string(target_path);
+    abi_long ret;
+
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(mknodat(dirfd, p, mode, dev));
+    unlock_user(p, target_path, 0);
+    return ret;
+}
+
+#ifdef TARGET_NR_mknod
+SYSCALL_IMPL(mknod)
+{
+    return do_mknodat(AT_FDCWD, arg1, arg2, arg3);
+}
+#endif
+
+SYSCALL_IMPL(mknodat)
+{
+    return do_mknodat(arg1, arg2, arg3, arg4);
+}
+
 /*
  * Helpers for do_openat, manipulating /proc/self/foo.
  */
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ea89734706..18163f558c 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5384,22 +5384,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_mknod
-    case TARGET_NR_mknod:
-        if (!(p = lock_user_string(arg1)))
-            return -TARGET_EFAULT;
-        ret = get_errno(mknod(p, arg2, arg3));
-        unlock_user(p, arg1, 0);
-        return ret;
-#endif
-#if defined(TARGET_NR_mknodat)
-    case TARGET_NR_mknodat:
-        if (!(p = lock_user_string(arg2)))
-            return -TARGET_EFAULT;
-        ret = get_errno(mknodat(arg1, p, arg3, arg4));
-        unlock_user(p, arg2, 0);
-        return ret;
-#endif
 #ifdef TARGET_NR_chmod
     case TARGET_NR_chmod:
         if (!(p = lock_user_string(arg1)))
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 95706a696b..f56d9acf76 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -518,12 +518,6 @@
 #ifdef TARGET_NR_mkdirat
 { TARGET_NR_mkdirat, "mkdirat" , NULL, print_mkdirat, NULL },
 #endif
-#ifdef TARGET_NR_mknod
-{ TARGET_NR_mknod, "mknod" , NULL, print_mknod, NULL },
-#endif
-#ifdef TARGET_NR_mknodat
-{ TARGET_NR_mknodat, "mknodat" , NULL, print_mknodat, NULL },
-#endif
 #ifdef TARGET_NR_modify_ldt
 { TARGET_NR_modify_ldt, "modify_ldt" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 28/74] linux-user: Split out chmod, fchmod, fchmodat
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (26 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 27/74] linux-user: Split out mknod, mknodat Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 29/74] linux-user: Split out lseek, llseek Richard Henderson
                   ` (48 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Note that fchmodat is universally provided.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  5 +++++
 linux-user/strace.c           | 28 ----------------------------
 linux-user/syscall-file.inc.c | 30 ++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 18 ------------------
 linux-user/strace.list        |  9 ---------
 5 files changed, 35 insertions(+), 55 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index b5951e6911..3ddf8aa0e3 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -20,6 +20,9 @@ SYSCALL_DEF_FULL(brk, .impl = impl_brk,
                  .print_ret = print_syscall_ptr_ret,
                  .arg_type = { ARG_PTR });
 SYSCALL_DEF(chdir, ARG_STR);
+#ifdef TARGET_NR_chmod
+SYSCALL_DEF(chmod, ARG_STR, ARG_MODEFLAG);
+#endif
 SYSCALL_DEF_ARGS(clone, ARG_CLONEFLAG, ARG_PTR, ARG_PTR, ARG_PTR, ARG_PTR);
 SYSCALL_DEF(close, ARG_DEC);
 #ifdef TARGET_NR_creat
@@ -28,6 +31,8 @@ SYSCALL_DEF(creat, ARG_STR, ARG_MODEFLAG);
 SYSCALL_DEF(exit, ARG_DEC);
 SYSCALL_DEF(execve, ARG_STR, ARG_PTR, ARG_PTR);
 SYSCALL_DEF(execveat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_PTR, ARG_ATFLAG);
+SYSCALL_DEF(fchmod, ARG_DEC, ARG_MODEFLAG);
+SYSCALL_DEF(fchmodat, ARG_ATDIRFD, ARG_STR, ARG_MODEFLAG);
 #ifdef TARGET_NR_fork
 SYSCALL_DEF(fork);
 #endif
diff --git a/linux-user/strace.c b/linux-user/strace.c
index c70c06d965..4771badeb5 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1125,19 +1125,6 @@ print_chroot(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_chmod
-static void
-print_chmod(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 0);
-    print_file_mode(arg1, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_clock_adjtime
 static void
 print_clock_adjtime(const struct syscallname *name,
@@ -1179,21 +1166,6 @@ print_faccessat(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_fchmodat
-static void
-print_fchmodat(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_at_dirfd(arg0, 0);
-    print_string(arg1, 0);
-    print_file_mode(arg2, 0);
-    print_flags(at_file_flags, arg3, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_fchownat
 static void
 print_fchownat(const struct syscallname *name,
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 3adb629124..fb64d5bd1d 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -30,6 +30,26 @@ SYSCALL_IMPL(chdir)
     return ret;
 }
 
+static abi_long do_fchmodat(int dirfd, abi_ulong target_path, mode_t mode)
+{
+    char *p = lock_user_string(target_path);
+    abi_long ret;
+
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(fchmodat(dirfd, p, mode, 0));
+    unlock_user(p, target_path, 0);
+    return ret;
+}
+
+#ifdef TARGET_NR_chmod
+SYSCALL_IMPL(chmod)
+{
+    return do_fchmodat(AT_FDCWD, arg1, arg2);
+}
+#endif
+
 SYSCALL_IMPL(close)
 {
     int fd = arg1;
@@ -54,6 +74,16 @@ SYSCALL_IMPL(creat)
 }
 #endif
 
+SYSCALL_IMPL(fchmod)
+{
+    return get_errno(fchmod(arg1, arg2));
+}
+
+SYSCALL_IMPL(fchmodat)
+{
+    return do_fchmodat(arg1, arg2, arg3);
+}
+
 static abi_long do_linkat(int olddirfd, abi_ulong target_oldpath,
                           int newdirfd, abi_ulong target_newpath,
                           int flags)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 18163f558c..3c0de73aa4 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5384,14 +5384,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_chmod
-    case TARGET_NR_chmod:
-        if (!(p = lock_user_string(arg1)))
-            return -TARGET_EFAULT;
-        ret = get_errno(chmod(p, arg2));
-        unlock_user(p, arg1, 0);
-        return ret;
-#endif
 #ifdef TARGET_NR_lseek
     case TARGET_NR_lseek:
         return get_errno(lseek(arg1, arg2, arg3));
@@ -6463,16 +6455,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
 #ifdef TARGET_NR_ftruncate
     case TARGET_NR_ftruncate:
         return get_errno(ftruncate(arg1, arg2));
-#endif
-    case TARGET_NR_fchmod:
-        return get_errno(fchmod(arg1, arg2));
-#if defined(TARGET_NR_fchmodat)
-    case TARGET_NR_fchmodat:
-        if (!(p = lock_user_string(arg2)))
-            return -TARGET_EFAULT;
-        ret = get_errno(fchmodat(arg1, p, arg3, 0));
-        unlock_user(p, arg2, 0);
-        return ret;
 #endif
     case TARGET_NR_getpriority:
         /* Note that negative values are valid for getpriority, so we must
diff --git a/linux-user/strace.list b/linux-user/strace.list
index f56d9acf76..0906aba812 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -61,9 +61,6 @@
 #ifdef TARGET_NR_capset
 { TARGET_NR_capset, "capset" , "%s(%p,%p)", NULL, NULL },
 #endif
-#ifdef TARGET_NR_chmod
-{ TARGET_NR_chmod, "chmod" , NULL, print_chmod, NULL },
-#endif
 #ifdef TARGET_NR_chown
 { TARGET_NR_chown, "chown" , NULL, NULL, NULL },
 #endif
@@ -169,12 +166,6 @@
 #ifdef TARGET_NR_fchdir
 { TARGET_NR_fchdir, "fchdir" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_fchmod
-{ TARGET_NR_fchmod, "fchmod" , "%s(%d,%#o)", NULL, NULL },
-#endif
-#ifdef TARGET_NR_fchmodat
-{ TARGET_NR_fchmodat, "fchmodat" , NULL, print_fchmodat, NULL },
-#endif
 #ifdef TARGET_NR_fchown
 { TARGET_NR_fchown, "fchown" , "%s(%d,%d,%d)", NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 29/74] linux-user: Split out lseek, llseek
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (27 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 28/74] linux-user: Split out chmod, fchmod, fchmodat Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 30/74] linux-user: Split out getpid, getppid, getxpid Richard Henderson
                   ` (47 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Canonicalise the target syscall name on llseek (new kernels)
instead of _llseek (old kernels).  Always use host lseek(3)
rather than attempting to use the host llseek(2).

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  6 ++++++
 linux-user/syscall.h          |  1 +
 linux-user/strace.c           | 39 +++++++++++++++--------------------
 linux-user/syscall-file.inc.c | 36 ++++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 32 ++--------------------------
 linux-user/strace.list        |  6 ------
 6 files changed, 62 insertions(+), 58 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 3ddf8aa0e3..3453e7afdf 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -43,6 +43,12 @@ SYSCALL_DEF_ARGS(ipc, ARG_HEX, ARG_DEC, ARG_DEC, ARG_HEX, ARG_PTR, ARG_HEX);
 SYSCALL_DEF(link, ARG_STR, ARG_STR);
 #endif
 SYSCALL_DEF(linkat, ARG_ATDIRFD, ARG_STR, ARG_ATDIRFD, ARG_STR, ARG_ATFLAG);
+#ifdef TARGET_NR_lseek
+SYSCALL_DEF(lseek, ARG_DEC, ARG_DEC, ARG_LSEEKWHENCE);
+#endif
+#ifdef TARGET_NR_llseek
+SYSCALL_DEF_ARGS(llseek, ARG_DEC, ARG_DEC, ARG_PTR, ARG_LSEEKWHENCE);
+#endif
 #ifdef TARGET_NR_mknod
 SYSCALL_DEF(mknod, ARG_STR, ARG_MODEFLAG, ARG_HEX);
 #endif
diff --git a/linux-user/syscall.h b/linux-user/syscall.h
index bdc4d653c4..c16c0a3f1e 100644
--- a/linux-user/syscall.h
+++ b/linux-user/syscall.h
@@ -64,6 +64,7 @@ typedef enum {
     ARG_MODEFLAG,
     ARG_OPENFLAG,
     ARG_UNLINKATFLAG,
+    ARG_LSEEKWHENCE,
 
     /* These are interpreted as pointers.  */
     ARG_PTR,
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 4771badeb5..a4d7b397b4 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -934,6 +934,20 @@ print_open_flags(abi_long flags, int last)
     gemu_log("%s%s", buf, get_comma(last));
 }
 
+static int add_lseek_whence(char *buf, int size, int whence)
+{
+    switch (whence) {
+    case SEEK_SET:
+        return snprintf(buf, size, "SEEK_SET");
+    case SEEK_CUR:
+        return snprintf(buf, size, "SEEK_CUR");
+    case SEEK_END:
+        return snprintf(buf, size, "SEEK_END");
+    default:
+        return snprintf(buf, size, "%#x", whence);
+    }
+}
+
 static void
 print_syscall_prologue(const struct syscallname *sc)
 {
@@ -1297,28 +1311,6 @@ print_futimesat(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR__llseek
-static void
-print__llseek(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    const char *whence = "UNKNOWN";
-    print_syscall_prologue(name);
-    print_raw_param("%d", arg0, 0);
-    print_raw_param("%ld", arg1, 0);
-    print_raw_param("%ld", arg2, 0);
-    print_pointer(arg3, 0);
-    switch(arg4) {
-    case SEEK_SET: whence = "SEEK_SET"; break;
-    case SEEK_CUR: whence = "SEEK_CUR"; break;
-    case SEEK_END: whence = "SEEK_END"; break;
-    }
-    gemu_log("%s",whence);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #if defined(TARGET_NR_socket)
 static void
 print_socket(const struct syscallname *name,
@@ -2329,6 +2321,9 @@ static void print_syscall_def1(const SyscallDef *def, int64_t args[6])
         case ARG_UNLINKATFLAG:
             len = add_flags(b, rest, unlinkat_flags, arg, true);
             break;
+        case ARG_LSEEKWHENCE:
+            len = add_lseek_whence(b, rest, arg);
+            break;
         case ARG_PTR:
             len = add_pointer(b, rest, arg);
             break;
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index fb64d5bd1d..e267adec1e 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -112,6 +112,42 @@ SYSCALL_IMPL(linkat)
     return do_linkat(arg1, arg2, arg3, arg4, arg5);
 }
 
+#ifdef TARGET_NR_lseek
+SYSCALL_IMPL(lseek)
+{
+    return get_errno(lseek(arg1, arg2, arg3));
+}
+#endif
+
+#ifdef TARGET_NR_llseek
+SYSCALL_ARGS(llseek)
+{
+    /* The parts for offset are *always* in big-endian order.  */
+    abi_ulong lo = in[2], hi = in[1];
+    out[1] = (((uint64_t)hi << (TARGET_ABI_BITS - 1)) << 1) | lo;
+    out[2] = in[3];
+    out[3] = in[4];
+    return def;
+}
+
+SYSCALL_IMPL(llseek)
+{
+    int fd = arg1;
+    int64_t offset = arg2;
+    abi_ulong target_res = arg3;
+    int whence = arg4;
+
+    off_t res = lseek(fd, offset, whence);
+
+    if (res == -1) {
+        return get_errno(-1);
+    } else if (put_user_s64(res, target_res)) {
+        return -TARGET_EFAULT;
+    }
+    return 0;
+}
+#endif
+
 static abi_long do_mknodat(int dirfd, abi_ulong target_path,
                            mode_t mode, dev_t dev)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 3c0de73aa4..9eff91d67e 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -192,8 +192,8 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,	\
 #endif
 
 /* Newer kernel ports have llseek() instead of _llseek() */
-#if defined(TARGET_NR_llseek) && !defined(TARGET_NR__llseek)
-#define TARGET_NR__llseek TARGET_NR_llseek
+#if !defined(TARGET_NR_llseek) && defined(TARGET_NR__llseek)
+#define TARGET_NR_llseek TARGET_NR__llseek
 #endif
 
 #define __NR_sys_gettid __NR_gettid
@@ -217,10 +217,6 @@ _syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count)
     (defined(TARGET_NR_getdents64) && defined(__NR_getdents64))
 _syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
 #endif
-#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
-_syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
-          loff_t *, res, uint, wh);
-#endif
 _syscall3(int, sys_rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t *, uinfo)
 _syscall4(int, sys_rt_tgsigqueueinfo, pid_t, pid, pid_t, tid, int, sig,
           siginfo_t *, uinfo)
@@ -5384,10 +5380,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_lseek
-    case TARGET_NR_lseek:
-        return get_errno(lseek(arg1, arg2, arg3));
-#endif
 #if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
     /* Alpha specific */
     case TARGET_NR_getxpid:
@@ -6886,26 +6878,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         return get_errno(fchdir(arg1));
     case TARGET_NR_personality:
         return get_errno(personality(arg1));
-#ifdef TARGET_NR__llseek /* Not on alpha */
-    case TARGET_NR__llseek:
-        {
-            int64_t res;
-#if !defined(__NR_llseek)
-            res = lseek(arg1, ((uint64_t)arg2 << 32) | (abi_ulong)arg3, arg5);
-            if (res == -1) {
-                ret = get_errno(res);
-            } else {
-                ret = 0;
-            }
-#else
-            ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
-#endif
-            if ((ret == 0) && put_user_s64(res, arg4)) {
-                return -TARGET_EFAULT;
-            }
-        }
-        return ret;
-#endif
 #ifdef TARGET_NR_getdents
     case TARGET_NR_getdents:
 #ifdef EMULATE_GETDENTS_WITH_GETDENTS
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 0906aba812..fb37c72a1f 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -455,9 +455,6 @@
 #ifdef TARGET_NR_llistxattr
 { TARGET_NR_llistxattr, "llistxattr" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR__llseek
-{ TARGET_NR__llseek, "_llseek" , NULL, print__llseek, NULL },
-#endif
 #ifdef TARGET_NR_lock
 { TARGET_NR_lock, "lock" , NULL, NULL, NULL },
 #endif
@@ -467,9 +464,6 @@
 #ifdef TARGET_NR_lremovexattr
 { TARGET_NR_lremovexattr, "lremovexattr" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_lseek
-{ TARGET_NR_lseek, "lseek" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_lsetxattr
 { TARGET_NR_lsetxattr, "lsetxattr" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 30/74] linux-user: Split out getpid, getppid, getxpid
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (28 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 29/74] linux-user: Split out lseek, llseek Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 31/74] linux-user: Split out mount Richard Henderson
                   ` (46 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  9 +++++++++
 linux-user/syscall-proc.inc.c | 23 +++++++++++++++++++++++
 linux-user/syscall.c          | 14 --------------
 linux-user/strace.list        |  9 ---------
 4 files changed, 32 insertions(+), 23 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 3453e7afdf..d163bbf409 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -36,6 +36,15 @@ SYSCALL_DEF(fchmodat, ARG_ATDIRFD, ARG_STR, ARG_MODEFLAG);
 #ifdef TARGET_NR_fork
 SYSCALL_DEF(fork);
 #endif
+#ifdef TARGET_NR_getpid
+SYSCALL_DEF(getpid);
+#endif
+#ifdef TARGET_NR_getppid
+SYSCALL_DEF(getppid);
+#endif
+#ifdef TARGET_NR_getxpid
+SYSCALL_DEF(getxpid);
+#endif
 #ifdef TARGET_NR_ipc
 SYSCALL_DEF_ARGS(ipc, ARG_HEX, ARG_DEC, ARG_DEC, ARG_HEX, ARG_PTR, ARG_HEX);
 #endif
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
index fd114d1f03..4d8d385b38 100644
--- a/linux-user/syscall-proc.inc.c
+++ b/linux-user/syscall-proc.inc.c
@@ -438,6 +438,29 @@ SYSCALL_IMPL(fork)
 }
 #endif
 
+#ifdef TARGET_NR_getpid
+SYSCALL_IMPL(getpid)
+{
+    return getpid();
+}
+#endif
+
+#ifdef TARGET_NR_getppid
+SYSCALL_IMPL(getppid)
+{
+    return getppid();
+}
+#endif
+
+#ifdef TARGET_NR_getxpid
+SYSCALL_IMPL(getxpid)
+{
+    /* Alpha specific */
+    cpu_env->ir[IR_A4] = getppid();
+    return getpid();
+}
+#endif
+
 /*
  * Map host to target signal numbers for the wait family of syscalls.
  * Assume all other status bits are the same.
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 9eff91d67e..29ea56deee 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5380,16 +5380,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
-    /* Alpha specific */
-    case TARGET_NR_getxpid:
-        ((CPUAlphaState *)cpu_env)->ir[IR_A4] = getppid();
-        return get_errno(getpid());
-#endif
-#ifdef TARGET_NR_getpid
-    case TARGET_NR_getpid:
-        return get_errno(getpid());
-#endif
     case TARGET_NR_mount:
         {
             /* need to look at the data field */
@@ -5721,10 +5711,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         return ret;
     }
 #endif
-#ifdef TARGET_NR_getppid /* not on alpha */
-    case TARGET_NR_getppid:
-        return get_errno(getppid());
-#endif
 #ifdef TARGET_NR_getpgrp
     case TARGET_NR_getpgrp:
         return get_errno(getpgrp());
diff --git a/linux-user/strace.list b/linux-user/strace.list
index fb37c72a1f..3e898ea307 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -298,15 +298,9 @@
 #ifdef TARGET_NR_getpgrp
 { TARGET_NR_getpgrp, "getpgrp" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_getpid
-{ TARGET_NR_getpid, "getpid" , "%s()", NULL, NULL },
-#endif
 #ifdef TARGET_NR_getpmsg
 { TARGET_NR_getpmsg, "getpmsg" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_getppid
-{ TARGET_NR_getppid, "getppid" , "%s()", NULL, NULL },
-#endif
 #ifdef TARGET_NR_getpriority
 { TARGET_NR_getpriority, "getpriority", "%s(%#x,%#x)", NULL, NULL },
 #endif
@@ -365,9 +359,6 @@
 #ifdef TARGET_NR_getxgid
 { TARGET_NR_getxgid, "getxgid" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_getxpid
-{ TARGET_NR_getxpid, "getxpid" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_getxuid
 { TARGET_NR_getxuid, "getxuid" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 31/74] linux-user: Split out mount
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (29 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 30/74] linux-user: Split out getpid, getppid, getxpid Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 32/74] linux-user: Split out umount, umount2 Richard Henderson
                   ` (45 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  1 +
 linux-user/syscall.h          |  1 +
 linux-user/strace.c           | 21 +++----------
 linux-user/syscall-file.inc.c | 48 ++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 55 -----------------------------------
 linux-user/strace.list        |  3 --
 6 files changed, 54 insertions(+), 75 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index d163bbf409..2b331c6a6d 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -78,6 +78,7 @@ SYSCALL_DEF_FULL(mmap2, .impl = impl_mmap,
                  .arg_type = { ARG_PTR, ARG_DEC, ARG_MMAPPROT,
                                ARG_MMAPFLAG, ARG_DEC, ARG_DEC64 });
 #endif
+SYSCALL_DEF(mount, ARG_STR, ARG_STR, ARG_STR, ARG_MOUNTFLAG, ARG_PTR);
 SYSCALL_DEF(mprotect, ARG_PTR, ARG_DEC, ARG_MMAPPROT);
 SYSCALL_DEF_FULL(mremap, .impl = impl_mremap,
                  .print_ret = print_syscall_ptr_ret,
diff --git a/linux-user/syscall.h b/linux-user/syscall.h
index c16c0a3f1e..35dd3e5fa3 100644
--- a/linux-user/syscall.h
+++ b/linux-user/syscall.h
@@ -62,6 +62,7 @@ typedef enum {
     ARG_MMAPFLAG,
     ARG_MMAPPROT,
     ARG_MODEFLAG,
+    ARG_MOUNTFLAG,
     ARG_OPENFLAG,
     ARG_UNLINKATFLAG,
     ARG_LSEEKWHENCE,
diff --git a/linux-user/strace.c b/linux-user/strace.c
index a4d7b397b4..a99ab46b97 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -708,7 +708,7 @@ static struct flags const open_flags[] = {
     FLAG_END,
 };
 
-UNUSED static struct flags mount_flags[] = {
+static struct flags const mount_flags[] = {
 #ifdef MS_BIND
     FLAG_GENERIC(MS_BIND),
 #endif
@@ -2015,22 +2015,6 @@ print_symlinkat(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_mount
-static void
-print_mount(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 0);
-    print_string(arg1, 0);
-    print_string(arg2, 0);
-    print_flags(mount_flags, arg3, 0);
-    print_pointer(arg4, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_umount
 static void
 print_umount(const struct syscallname *name,
@@ -2315,6 +2299,9 @@ static void print_syscall_def1(const SyscallDef *def, int64_t args[6])
         case ARG_MODEFLAG:
             len = add_flags(b, rest, mode_flags, arg, true);
             break;
+        case ARG_MOUNTFLAG:
+            len = add_flags(b, rest, mount_flags, arg, true);
+            break;
         case ARG_OPENFLAG:
             len = add_open_flags(b, rest, arg);
             break;
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index e267adec1e..4fc12512c2 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -174,6 +174,54 @@ SYSCALL_IMPL(mknodat)
     return do_mknodat(arg1, arg2, arg3, arg4);
 }
 
+SYSCALL_IMPL(mount)
+{
+    abi_ulong target_src = arg1;
+    abi_ulong target_tgt = arg2;
+    abi_ulong target_fst = arg3;
+    abi_ulong mountflags = arg4;
+    abi_ulong target_data = arg5;
+    char *p_src = NULL, *p_tgt = NULL, *p_fst = NULL, *p_data = NULL;
+    abi_long ret = -TARGET_EFAULT;
+
+    if (target_src) {
+        p_src = lock_user_string(target_src);
+        if (!p_src) {
+            goto exit0;
+        }
+    }
+
+    p_tgt = lock_user_string(target_tgt);
+    if (!p_tgt) {
+        goto exit1;
+    }
+
+    if (target_fst) {
+        p_fst = lock_user_string(target_fst);
+        if (!p_fst) {
+            goto exit2;
+        }
+    }
+
+    /*
+     * FIXME - arg5 should be locked, but it isn't clear how to
+     * do that since it's not guaranteed to be a NULL-terminated
+     * string.
+     */
+    if (target_data) {
+        p_data = g2h(target_data);
+    }
+    ret = get_errno(mount(p_src, p_tgt, p_fst, mountflags, p_data));
+
+    unlock_user(p_fst, target_fst, 0);
+ exit2:
+    unlock_user(p_tgt, target_tgt, 0);
+ exit1:
+    unlock_user(p_src, target_src, 0);
+ exit0:
+    return ret;
+}
+
 /*
  * Helpers for do_openat, manipulating /proc/self/foo.
  */
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 29ea56deee..c826c65317 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5380,61 +5380,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_mount:
-        {
-            /* need to look at the data field */
-            void *p2, *p3;
-
-            if (arg1) {
-                p = lock_user_string(arg1);
-                if (!p) {
-                    return -TARGET_EFAULT;
-                }
-            } else {
-                p = NULL;
-            }
-
-            p2 = lock_user_string(arg2);
-            if (!p2) {
-                if (arg1) {
-                    unlock_user(p, arg1, 0);
-                }
-                return -TARGET_EFAULT;
-            }
-
-            if (arg3) {
-                p3 = lock_user_string(arg3);
-                if (!p3) {
-                    if (arg1) {
-                        unlock_user(p, arg1, 0);
-                    }
-                    unlock_user(p2, arg2, 0);
-                    return -TARGET_EFAULT;
-                }
-            } else {
-                p3 = NULL;
-            }
-
-            /* FIXME - arg5 should be locked, but it isn't clear how to
-             * do that since it's not guaranteed to be a NULL-terminated
-             * string.
-             */
-            if (!arg5) {
-                ret = mount(p, p2, p3, (unsigned long)arg4, NULL);
-            } else {
-                ret = mount(p, p2, p3, (unsigned long)arg4, g2h(arg5));
-            }
-            ret = get_errno(ret);
-
-            if (arg1) {
-                unlock_user(p, arg1, 0);
-            }
-            unlock_user(p2, arg2, 0);
-            if (arg3) {
-                unlock_user(p3, arg3, 0);
-            }
-        }
-        return ret;
 #ifdef TARGET_NR_umount
     case TARGET_NR_umount:
         if (!(p = lock_user_string(arg1)))
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 3e898ea307..9b4024d94f 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -497,9 +497,6 @@
 #ifdef TARGET_NR_modify_ldt
 { TARGET_NR_modify_ldt, "modify_ldt" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_mount
-{ TARGET_NR_mount, "mount" , NULL, print_mount, NULL },
-#endif
 #ifdef TARGET_NR_move_pages
 { TARGET_NR_move_pages, "move_pages" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 32/74] linux-user: Split out umount, umount2
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (30 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 31/74] linux-user: Split out mount Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 33/74] linux-user: Split out stime Richard Henderson
                   ` (44 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Note that umount2 is unconditionally available.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  4 ++++
 linux-user/syscall.h          |  1 +
 linux-user/strace.c           | 30 ++++--------------------------
 linux-user/syscall-file.inc.c | 25 +++++++++++++++++++++++++
 linux-user/syscall.c          | 16 ----------------
 linux-user/strace.list        |  6 ------
 6 files changed, 34 insertions(+), 48 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 2b331c6a6d..0d8da0c6d6 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -155,6 +155,10 @@ SYSCALL_DEF(shmget, ARG_DEC, ARG_DEC, ARG_HEX);
 #ifdef TARGET_NR_time
 SYSCALL_DEF(time, ARG_PTR);
 #endif
+#ifdef TARGET_NR_umount
+SYSCALL_DEF(umount, ARG_STR);
+#endif
+SYSCALL_DEF(umount2, ARG_STR, ARG_UMOUNTFLAG);
 #ifdef TARGET_NR_unlink
 SYSCALL_DEF(unlink, ARG_STR);
 #endif
diff --git a/linux-user/syscall.h b/linux-user/syscall.h
index 35dd3e5fa3..3c936b648a 100644
--- a/linux-user/syscall.h
+++ b/linux-user/syscall.h
@@ -64,6 +64,7 @@ typedef enum {
     ARG_MODEFLAG,
     ARG_MOUNTFLAG,
     ARG_OPENFLAG,
+    ARG_UMOUNTFLAG,
     ARG_UNLINKATFLAG,
     ARG_LSEEKWHENCE,
 
diff --git a/linux-user/strace.c b/linux-user/strace.c
index a99ab46b97..278d235ae6 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -733,7 +733,7 @@ static struct flags const mount_flags[] = {
     FLAG_END,
 };
 
-UNUSED static struct flags umount2_flags[] = {
+static struct flags const umount2_flags[] = {
 #ifdef MNT_FORCE
     FLAG_GENERIC(MNT_FORCE),
 #endif
@@ -2015,31 +2015,6 @@ print_symlinkat(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_umount
-static void
-print_umount(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
-#ifdef TARGET_NR_umount2
-static void
-print_umount2(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 0);
-    print_flags(umount2_flags, arg1, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_utime
 static void
 print_utime(const struct syscallname *name,
@@ -2305,6 +2280,9 @@ static void print_syscall_def1(const SyscallDef *def, int64_t args[6])
         case ARG_OPENFLAG:
             len = add_open_flags(b, rest, arg);
             break;
+        case ARG_UMOUNTFLAG:
+            len = add_flags(b, rest, umount2_flags, arg, false);
+            break;
         case ARG_UNLINKATFLAG:
             len = add_flags(b, rest, unlinkat_flags, arg, true);
             break;
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 4fc12512c2..345b4cb421 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -816,6 +816,31 @@ SYSCALL_IMPL(readlinkat)
 }
 #endif
 
+static abi_long do_umount2(abi_ulong target_path, int flags)
+{
+    char *p = lock_user_string(target_path);
+    abi_long ret;
+
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(umount2(p, flags));
+    unlock_user(p, target_path, 0);
+    return ret;
+}
+
+#ifdef TARGET_NR_umount
+SYSCALL_IMPL(umount)
+{
+    return do_umount2(arg1, 0);
+}
+#endif
+
+SYSCALL_IMPL(umount2)
+{
+    return do_umount2(arg1, arg2);
+}
+
 static abi_long do_unlinkat(int dirfd, abi_ulong target_path, int flags)
 {
     char *p = lock_user_string(target_path);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index c826c65317..f3e03f535d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5380,14 +5380,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_umount
-    case TARGET_NR_umount:
-        if (!(p = lock_user_string(arg1)))
-            return -TARGET_EFAULT;
-        ret = get_errno(umount(p));
-        unlock_user(p, arg1, 0);
-        return ret;
-#endif
 #ifdef TARGET_NR_stime /* not on alpha */
     case TARGET_NR_stime:
         {
@@ -5608,14 +5600,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
             unlock_user(p, arg1, 0);
         }
         return ret;
-#ifdef TARGET_NR_umount2
-    case TARGET_NR_umount2:
-        if (!(p = lock_user_string(arg1)))
-            return -TARGET_EFAULT;
-        ret = get_errno(umount2(p, arg2));
-        unlock_user(p, arg1, 0);
-        return ret;
-#endif
     case TARGET_NR_ioctl:
         return do_ioctl(arg1, arg2, arg3);
 #ifdef TARGET_NR_fcntl
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 9b4024d94f..973a4c9209 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1368,12 +1368,6 @@
 #ifdef TARGET_NR_umask
 { TARGET_NR_umask, "umask" , "%s(%#o)", NULL, NULL },
 #endif
-#ifdef TARGET_NR_umount
-{ TARGET_NR_umount, "umount" , NULL, print_umount, NULL },
-#endif
-#ifdef TARGET_NR_umount2
-{ TARGET_NR_umount2, "umount2" , NULL, print_umount2, NULL },
-#endif
 #ifdef TARGET_NR_uname
 { TARGET_NR_uname, "uname" , "%s(%p)", NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 33/74] linux-user: Split out stime
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (31 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 32/74] linux-user: Split out umount, umount2 Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 34/74] linux-user: Split out alarm, pause Richard Henderson
                   ` (43 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  3 +++
 linux-user/syscall-time.inc.c | 12 ++++++++++++
 linux-user/syscall.c          |  9 ---------
 linux-user/strace.list        |  3 ---
 4 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 0d8da0c6d6..6ca82af397 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -152,6 +152,9 @@ SYSCALL_DEF(shmdt, ARG_PTR);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_shmget)
 SYSCALL_DEF(shmget, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
+#ifdef TARGET_NR_stime
+SYSCALL_DEF(stime, ARG_PTR);
+#endif
 #ifdef TARGET_NR_time
 SYSCALL_DEF(time, ARG_PTR);
 #endif
diff --git a/linux-user/syscall-time.inc.c b/linux-user/syscall-time.inc.c
index 14fec88e47..d1fb72bde0 100644
--- a/linux-user/syscall-time.inc.c
+++ b/linux-user/syscall-time.inc.c
@@ -16,6 +16,18 @@
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#ifdef TARGET_NR_stime
+SYSCALL_IMPL(stime)
+{
+    time_t host_time;
+
+    if (get_user_sal(host_time, arg1)) {
+        return -TARGET_EFAULT;
+    }
+    return get_errno(stime(&host_time));
+}
+#endif
+
 #ifdef TARGET_NR_time
 SYSCALL_IMPL(time)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f3e03f535d..ae56ecbbc7 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5380,15 +5380,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_stime /* not on alpha */
-    case TARGET_NR_stime:
-        {
-            time_t host_time;
-            if (get_user_sal(host_time, arg1))
-                return -TARGET_EFAULT;
-            return get_errno(stime(&host_time));
-        }
-#endif
 #ifdef TARGET_NR_alarm /* not on alpha */
     case TARGET_NR_alarm:
         return alarm(arg1);
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 973a4c9209..d0646b9424 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1254,9 +1254,6 @@
 #ifdef TARGET_NR_statfs64
 { TARGET_NR_statfs64, "statfs64" , NULL, print_statfs64, NULL },
 #endif
-#ifdef TARGET_NR_stime
-{ TARGET_NR_stime, "stime" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_streams1
 { TARGET_NR_streams1, "streams1" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 34/74] linux-user: Split out alarm, pause
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (32 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 33/74] linux-user: Split out stime Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 35/74] linux-user: Split out utime, utimes, futimesat Richard Henderson
                   ` (42 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h    |  6 ++++++
 linux-user/syscall-sig.inc.c | 36 ++++++++++++++++++++++++++++++++++++
 linux-user/syscall.c         | 12 +-----------
 linux-user/strace.list       |  6 ------
 4 files changed, 43 insertions(+), 17 deletions(-)
 create mode 100644 linux-user/syscall-sig.inc.c

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 6ca82af397..9d0dd7457b 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -16,6 +16,9 @@
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#ifdef TARGET_NR_alarm
+SYSCALL_DEF(alarm, ARG_DEC);
+#endif
 SYSCALL_DEF_FULL(brk, .impl = impl_brk,
                  .print_ret = print_syscall_ptr_ret,
                  .arg_type = { ARG_PTR });
@@ -106,6 +109,9 @@ SYSCALL_DEF(open, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG);
 #endif
 SYSCALL_DEF(openat, ARG_ATDIRFD, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG);
 SYSCALL_DEF(open_by_handle_at, ARG_DEC, ARG_PTR, ARG_OPENFLAG);
+#ifdef TARGET_NR_pause
+SYSCALL_DEF(pause);
+#endif
 SYSCALL_DEF_FULL(pread64, .impl = impl_pread64,
                  .args = args_pread64_pwrite64,
                  .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 });
diff --git a/linux-user/syscall-sig.inc.c b/linux-user/syscall-sig.inc.c
new file mode 100644
index 0000000000..f4e43eb00e
--- /dev/null
+++ b/linux-user/syscall-sig.inc.c
@@ -0,0 +1,36 @@
+/*
+ *  Linux signal related syscalls
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef TARGET_NR_alarm
+SYSCALL_IMPL(alarm)
+{
+    return alarm(arg1);
+}
+#endif
+
+#ifdef TARGET_NR_pause
+SYSCALL_IMPL(pause)
+{
+    if (!block_signals()) {
+        CPUState *cpu = ENV_GET_CPU(cpu_env);
+        TaskState *ts = cpu->opaque;
+        sigsuspend(&ts->signal_mask);
+    }
+    return -TARGET_EINTR;
+}
+#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ae56ecbbc7..96e77ea38f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5380,17 +5380,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_alarm /* not on alpha */
-    case TARGET_NR_alarm:
-        return alarm(arg1);
-#endif
-#ifdef TARGET_NR_pause /* not on alpha */
-    case TARGET_NR_pause:
-        if (!block_signals()) {
-            sigsuspend(&((TaskState *)cpu->opaque)->signal_mask);
-        }
-        return -TARGET_EINTR;
-#endif
 #ifdef TARGET_NR_utime
     case TARGET_NR_utime:
         {
@@ -9224,6 +9213,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
 #include "syscall-ipc.inc.c"
 #include "syscall-mem.inc.c"
 #include "syscall-proc.inc.c"
+#include "syscall-sig.inc.c"
 #include "syscall-time.inc.c"
 
 #undef SYSCALL_IMPL
diff --git a/linux-user/strace.list b/linux-user/strace.list
index d0646b9424..2a65457c76 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -25,9 +25,6 @@
 #ifdef TARGET_NR_afs_syscall
 { TARGET_NR_afs_syscall, "afs_syscall" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_alarm
-{ TARGET_NR_alarm, "alarm" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_aplib
 { TARGET_NR_aplib, "aplib" , NULL, NULL, NULL },
 #endif
@@ -872,9 +869,6 @@
 #ifdef TARGET_NR_osf_waitid
 { TARGET_NR_osf_waitid, "osf_waitid" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_pause
-{ TARGET_NR_pause, "pause" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_pciconfig_iobase
 { TARGET_NR_pciconfig_iobase, "pciconfig_iobase" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 35/74] linux-user: Split out utime, utimes, futimesat
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (33 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 34/74] linux-user: Split out alarm, pause Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 36/74] linux-user: Split out access, faccessat Richard Henderson
                   ` (41 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  9 ++++
 linux-user/strace.c           | 41 ---------------
 linux-user/syscall-file.inc.c | 95 +++++++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 63 -----------------------
 linux-user/strace.list        |  9 ----
 5 files changed, 104 insertions(+), 113 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 9d0dd7457b..2767e335d8 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -36,6 +36,9 @@ SYSCALL_DEF(execve, ARG_STR, ARG_PTR, ARG_PTR);
 SYSCALL_DEF(execveat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_PTR, ARG_ATFLAG);
 SYSCALL_DEF(fchmod, ARG_DEC, ARG_MODEFLAG);
 SYSCALL_DEF(fchmodat, ARG_ATDIRFD, ARG_STR, ARG_MODEFLAG);
+#ifdef TARGET_NR_futimesat
+SYSCALL_DEF(futimesat, ARG_ATDIRFD, ARG_STR, ARG_PTR);
+#endif
 #ifdef TARGET_NR_fork
 SYSCALL_DEF(fork);
 #endif
@@ -172,6 +175,12 @@ SYSCALL_DEF(umount2, ARG_STR, ARG_UMOUNTFLAG);
 SYSCALL_DEF(unlink, ARG_STR);
 #endif
 SYSCALL_DEF(unlinkat, ARG_ATDIRFD, ARG_STR, ARG_UNLINKATFLAG);
+#ifdef TARGET_NR_utime
+SYSCALL_DEF(utime, ARG_STR, ARG_PTR);
+#endif
+#ifdef TARGET_NR_utimes
+SYSCALL_DEF(utimes, ARG_STR, ARG_PTR);
+#endif
 #ifdef TARGET_NR_vfork
 /* Emulate vfork() with fork().  */
 SYSCALL_DEF_FULL(vfork, .impl = impl_fork);
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 278d235ae6..3a7a5c30ec 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1296,21 +1296,6 @@ print_fcntl(const struct syscallname *name,
 #endif
 
 
-#ifdef TARGET_NR_futimesat
-static void
-print_futimesat(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_at_dirfd(arg0, 0);
-    print_string(arg1, 0);
-    print_timeval(arg2, 0);
-    print_timeval(arg2 + sizeof (struct target_timeval), 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #if defined(TARGET_NR_socket)
 static void
 print_socket(const struct syscallname *name,
@@ -2015,32 +2000,6 @@ print_symlinkat(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_utime
-static void
-print_utime(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 0);
-    print_pointer(arg1, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
-#ifdef TARGET_NR_utimes
-static void
-print_utimes(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 0);
-    print_pointer(arg1, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_utimensat
 static void
 print_utimensat(const struct syscallname *name,
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 345b4cb421..42e5cd2dc1 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -84,6 +84,38 @@ SYSCALL_IMPL(fchmodat)
     return do_fchmodat(arg1, arg2, arg3);
 }
 
+#ifdef TARGET_NR_futimesat
+SYSCALL_IMPL(futimesat)
+{
+    int dirfd = arg1;
+    abi_ulong target_path = arg2;
+    abi_ulong target_tv = arg3;
+    struct timeval *tvp, tv[2];
+    char *p;
+    abi_long ret;
+
+    if (target_tv) {
+        if (copy_from_user_timeval(&tv[0], target_tv)
+            || copy_from_user_timeval(&tv[1],
+                                      target_tv +
+                                      sizeof(struct target_timeval))) {
+            return -TARGET_EFAULT;
+        }
+        tvp = tv;
+    } else {
+        tvp = NULL;
+    }
+
+    p = lock_user_string(target_path);
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(futimesat(dirfd, path(p), tvp));
+    unlock_user(p, target_path, 0);
+    return ret;
+}
+#endif
+
 static abi_long do_linkat(int olddirfd, abi_ulong target_oldpath,
                           int newdirfd, abi_ulong target_newpath,
                           int flags)
@@ -873,6 +905,69 @@ SYSCALL_IMPL(unlinkat)
     return do_unlinkat(arg1, arg2, arg3);
 }
 
+#ifdef TARGET_NR_utime
+SYSCALL_IMPL(utime)
+{
+    abi_ulong target_path = arg1;
+    abi_ulong target_times = arg2;
+    struct utimbuf tbuf, *host_tbuf;
+    struct target_utimbuf *target_tbuf;
+    char *p;
+    abi_long ret;
+
+    if (target_times) {
+        if (!lock_user_struct(VERIFY_READ, target_tbuf, target_times, 1)) {
+            return -TARGET_EFAULT;
+        }
+        tbuf.actime = tswapal(target_tbuf->actime);
+        tbuf.modtime = tswapal(target_tbuf->modtime);
+        unlock_user_struct(target_tbuf, arg2, 0);
+        host_tbuf = &tbuf;
+    } else {
+        host_tbuf = NULL;
+    }
+
+    p = lock_user_string(target_path);
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(utime(p, host_tbuf));
+    unlock_user(p, target_path, 0);
+    return ret;
+}
+#endif
+
+#ifdef TARGET_NR_utimes
+SYSCALL_IMPL(utimes)
+{
+    abi_ulong target_path = arg1;
+    abi_ulong target_tv = arg2;
+    struct timeval *tvp, tv[2];
+    char *p;
+    abi_long ret;
+
+    if (target_tv) {
+        if (copy_from_user_timeval(&tv[0], target_tv)
+            || copy_from_user_timeval(&tv[1],
+                                      target_tv +
+                                      sizeof(struct target_timeval))) {
+            return -TARGET_EFAULT;
+        }
+        tvp = tv;
+    } else {
+        tvp = NULL;
+    }
+
+    p = lock_user_string(target_path);
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(utimes(p, tvp));
+    unlock_user(p, target_path, 0);
+    return ret;
+}
+#endif
+
 SYSCALL_IMPL(write)
 {
     int fd = arg1;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 96e77ea38f..f66acbf27c 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5380,69 +5380,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_utime
-    case TARGET_NR_utime:
-        {
-            struct utimbuf tbuf, *host_tbuf;
-            struct target_utimbuf *target_tbuf;
-            if (arg2) {
-                if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
-                    return -TARGET_EFAULT;
-                tbuf.actime = tswapal(target_tbuf->actime);
-                tbuf.modtime = tswapal(target_tbuf->modtime);
-                unlock_user_struct(target_tbuf, arg2, 0);
-                host_tbuf = &tbuf;
-            } else {
-                host_tbuf = NULL;
-            }
-            if (!(p = lock_user_string(arg1)))
-                return -TARGET_EFAULT;
-            ret = get_errno(utime(p, host_tbuf));
-            unlock_user(p, arg1, 0);
-        }
-        return ret;
-#endif
-#ifdef TARGET_NR_utimes
-    case TARGET_NR_utimes:
-        {
-            struct timeval *tvp, tv[2];
-            if (arg2) {
-                if (copy_from_user_timeval(&tv[0], arg2)
-                    || copy_from_user_timeval(&tv[1],
-                                              arg2 + sizeof(struct target_timeval)))
-                    return -TARGET_EFAULT;
-                tvp = tv;
-            } else {
-                tvp = NULL;
-            }
-            if (!(p = lock_user_string(arg1)))
-                return -TARGET_EFAULT;
-            ret = get_errno(utimes(p, tvp));
-            unlock_user(p, arg1, 0);
-        }
-        return ret;
-#endif
-#if defined(TARGET_NR_futimesat)
-    case TARGET_NR_futimesat:
-        {
-            struct timeval *tvp, tv[2];
-            if (arg3) {
-                if (copy_from_user_timeval(&tv[0], arg3)
-                    || copy_from_user_timeval(&tv[1],
-                                              arg3 + sizeof(struct target_timeval)))
-                    return -TARGET_EFAULT;
-                tvp = tv;
-            } else {
-                tvp = NULL;
-            }
-            if (!(p = lock_user_string(arg2))) {
-                return -TARGET_EFAULT;
-            }
-            ret = get_errno(futimesat(arg1, path(p), tvp));
-            unlock_user(p, arg2, 0);
-        }
-        return ret;
-#endif
 #ifdef TARGET_NR_access
     case TARGET_NR_access:
         if (!(p = lock_user_string(arg1))) {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 2a65457c76..3f92224b55 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -226,9 +226,6 @@
 #ifdef TARGET_NR_futex
 { TARGET_NR_futex, "futex" , NULL, print_futex, NULL },
 #endif
-#ifdef TARGET_NR_futimesat
-{ TARGET_NR_futimesat, "futimesat" , NULL, print_futimesat, NULL },
-#endif
 #ifdef TARGET_NR_getcpu
 { TARGET_NR_getcpu, "getcpu" , "%s(%p,%d)", NULL, NULL },
 #endif
@@ -1392,12 +1389,6 @@
 #ifdef TARGET_NR_ustat
 { TARGET_NR_ustat, "ustat" , "%s(%#x,%p)", NULL, NULL },
 #endif
-#ifdef TARGET_NR_utime
-{ TARGET_NR_utime, "utime" , NULL, print_utime, NULL },
-#endif
-#ifdef TARGET_NR_utimes
-{ TARGET_NR_utimes, "utimes" , NULL, print_utimes, NULL },
-#endif
 #ifdef TARGET_NR_utrap_install
 { TARGET_NR_utrap_install, "utrap_install" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 36/74] linux-user: Split out access, faccessat
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (34 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 35/74] linux-user: Split out utime, utimes, futimesat Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 37/74] linux-user: Split out nice Richard Henderson
                   ` (40 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Note that faccessat is unconditionally available.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  4 ++++
 linux-user/syscall.h          |  1 +
 linux-user/strace.c           | 33 ++++-----------------------------
 linux-user/syscall-file.inc.c | 25 +++++++++++++++++++++++++
 linux-user/syscall.c          | 18 ------------------
 linux-user/strace.list        |  6 ------
 6 files changed, 34 insertions(+), 53 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 2767e335d8..39e3ae3c21 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -16,6 +16,9 @@
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#ifdef TARGET_NR_access
+SYSCALL_DEF(access, ARG_STR, ARG_ACCESSFLAG);
+#endif
 #ifdef TARGET_NR_alarm
 SYSCALL_DEF(alarm, ARG_DEC);
 #endif
@@ -34,6 +37,7 @@ SYSCALL_DEF(creat, ARG_STR, ARG_MODEFLAG);
 SYSCALL_DEF(exit, ARG_DEC);
 SYSCALL_DEF(execve, ARG_STR, ARG_PTR, ARG_PTR);
 SYSCALL_DEF(execveat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_PTR, ARG_ATFLAG);
+SYSCALL_DEF(faccessat, ARG_ATDIRFD, ARG_STR, ARG_ACCESSFLAG);
 SYSCALL_DEF(fchmod, ARG_DEC, ARG_MODEFLAG);
 SYSCALL_DEF(fchmodat, ARG_ATDIRFD, ARG_STR, ARG_MODEFLAG);
 #ifdef TARGET_NR_futimesat
diff --git a/linux-user/syscall.h b/linux-user/syscall.h
index 3c936b648a..84a52b2d9a 100644
--- a/linux-user/syscall.h
+++ b/linux-user/syscall.h
@@ -57,6 +57,7 @@ typedef enum {
 
     /* These print as sets of flags.  */
     ARG_ATDIRFD,
+    ARG_ACCESSFLAG,
     ARG_ATFLAG,
     ARG_CLONEFLAG,
     ARG_MMAPFLAG,
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 3a7a5c30ec..c42abc2f08 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -634,7 +634,7 @@ print_syscall_ret_adjtimex(const struct syscallname *name, abi_long ret)
     gemu_log("\n");
 }
 
-UNUSED static struct flags access_flags[] = {
+static struct flags const access_flags[] = {
     FLAG_GENERIC(F_OK),
     FLAG_GENERIC(R_OK),
     FLAG_GENERIC(W_OK),
@@ -1114,19 +1114,6 @@ print_accept(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_access
-static void
-print_access(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 0);
-    print_flags(access_flags, arg1, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_chroot
 static void
 print_chroot(const struct syscallname *name,
@@ -1165,21 +1152,6 @@ print_execv(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_faccessat
-static void
-print_faccessat(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_at_dirfd(arg0, 0);
-    print_string(arg1, 0);
-    print_flags(access_flags, arg2, 0);
-    print_flags(at_file_flags, arg3, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_fchownat
 static void
 print_fchownat(const struct syscallname *name,
@@ -2218,6 +2190,9 @@ static void print_syscall_def1(const SyscallDef *def, int64_t args[6])
         case ARG_ATDIRFD:
             len = add_atdirfd(b, rest, arg);
             break;
+        case ARG_ACCESSFLAG:
+            len = add_flags(b, rest, access_flags, arg, false);
+            break;
         case ARG_ATFLAG:
             len = add_flags(b, rest, at_file_flags, arg, false);
             break;
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 42e5cd2dc1..5e276d13bc 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -16,6 +16,26 @@
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+static abi_long do_faccessat(int dirfd, abi_ulong target_path, int mode)
+{
+    char *p = lock_user_string(target_path);
+    abi_long ret;
+
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(faccessat(dirfd, p, mode, 0));
+    unlock_user(p, target_path, 0);
+    return ret;
+}
+
+#ifdef TARGET_NR_access
+SYSCALL_IMPL(access)
+{
+    return do_faccessat(AT_FDCWD, arg1, arg2);
+}
+#endif
+
 SYSCALL_IMPL(chdir)
 {
     abi_ulong target_path = arg1;
@@ -74,6 +94,11 @@ SYSCALL_IMPL(creat)
 }
 #endif
 
+SYSCALL_IMPL(faccessat)
+{
+    return do_faccessat(arg1, arg2, arg3);
+}
+
 SYSCALL_IMPL(fchmod)
 {
     return get_errno(fchmod(arg1, arg2));
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f66acbf27c..b5ade974a7 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5380,24 +5380,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_access
-    case TARGET_NR_access:
-        if (!(p = lock_user_string(arg1))) {
-            return -TARGET_EFAULT;
-        }
-        ret = get_errno(access(path(p), arg2));
-        unlock_user(p, arg1, 0);
-        return ret;
-#endif
-#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
-    case TARGET_NR_faccessat:
-        if (!(p = lock_user_string(arg2))) {
-            return -TARGET_EFAULT;
-        }
-        ret = get_errno(faccessat(arg1, p, arg3, 0));
-        unlock_user(p, arg2, 0);
-        return ret;
-#endif
 #ifdef TARGET_NR_nice /* not on alpha */
     case TARGET_NR_nice:
         return get_errno(nice(arg1));
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 3f92224b55..80b9220e89 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -9,9 +9,6 @@
 #ifdef TARGET_NR_accept4
 { TARGET_NR_accept4, "accept4" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_access
-{ TARGET_NR_access, "access" , NULL, print_access, NULL },
-#endif
 #ifdef TARGET_NR_acct
 { TARGET_NR_acct, "acct" , NULL, NULL, NULL },
 #endif
@@ -142,9 +139,6 @@
 #ifdef TARGET_NR_exit_group
 { TARGET_NR_exit_group, "exit_group" , "%s(%d)\n", NULL, NULL },
 #endif
-#ifdef TARGET_NR_faccessat
-{ TARGET_NR_faccessat, "faccessat" , NULL, print_faccessat, NULL },
-#endif
 #ifdef TARGET_NR_fadvise64
 { TARGET_NR_fadvise64, "fadvise64" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 37/74] linux-user: Split out nice
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (35 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 36/74] linux-user: Split out access, faccessat Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 38/74] linux-user: Split out sync, syncfs Richard Henderson
                   ` (39 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     | 3 +++
 linux-user/syscall-proc.inc.c | 7 +++++++
 linux-user/syscall.c          | 4 ----
 linux-user/strace.list        | 3 ---
 4 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 39e3ae3c21..860754aaca 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -111,6 +111,9 @@ SYSCALL_DEF(munlockall);
 SYSCALL_DEF(munmap, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(name_to_handle_at,
             ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_PTR, ARG_ATFLAG);
+#ifdef TARGET_NR_nice
+SYSCALL_DEF(nice, ARG_DEC);
+#endif
 #ifdef TARGET_NR_open
 SYSCALL_DEF(open, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG);
 #endif
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
index 4d8d385b38..e29c2ede25 100644
--- a/linux-user/syscall-proc.inc.c
+++ b/linux-user/syscall-proc.inc.c
@@ -461,6 +461,13 @@ SYSCALL_IMPL(getxpid)
 }
 #endif
 
+#ifdef TARGET_NR_nice
+SYSCALL_IMPL(nice)
+{
+    return get_errno(nice(arg1));
+}
+#endif
+
 /*
  * Map host to target signal numbers for the wait family of syscalls.
  * Assume all other status bits are the same.
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index b5ade974a7..6d30e8ff2f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5380,10 +5380,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_nice /* not on alpha */
-    case TARGET_NR_nice:
-        return get_errno(nice(arg1));
-#endif
     case TARGET_NR_sync:
         sync();
         return 0;
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 80b9220e89..3161546afc 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -527,9 +527,6 @@
 #ifdef TARGET_NR_nfsservctl
 { TARGET_NR_nfsservctl, "nfsservctl" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_nice
-{ TARGET_NR_nice, "nice" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_old_adjtimex
 { TARGET_NR_old_adjtimex, "old_adjtimex" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 38/74] linux-user: Split out sync, syncfs
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (36 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 37/74] linux-user: Split out nice Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 39/74] linux-user: Split out kill Richard Henderson
                   ` (38 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Note that syncfs is universally available.
If !CONFIG_SYNCFS, provide our own syscall replacement.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  2 ++
 linux-user/syscall-file.inc.c | 11 +++++++++++
 linux-user/syscall.c          | 20 ++++++++++++--------
 linux-user/strace.list        |  6 ------
 4 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 860754aaca..497fbdba66 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -171,6 +171,8 @@ SYSCALL_DEF(shmget, ARG_DEC, ARG_DEC, ARG_HEX);
 #ifdef TARGET_NR_stime
 SYSCALL_DEF(stime, ARG_PTR);
 #endif
+SYSCALL_DEF(sync);
+SYSCALL_DEF(syncfs, ARG_DEC);
 #ifdef TARGET_NR_time
 SYSCALL_DEF(time, ARG_PTR);
 #endif
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 5e276d13bc..9f3cf7221a 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -873,6 +873,17 @@ SYSCALL_IMPL(readlinkat)
 }
 #endif
 
+SYSCALL_IMPL(sync)
+{
+    sync();
+    return 0;
+}
+
+SYSCALL_IMPL(syncfs)
+{
+    return get_errno(syncfs(arg1));
+}
+
 static abi_long do_umount2(abi_ulong target_path, int flags)
 {
     char *p = lock_user_string(target_path);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 6d30e8ff2f..d612dade23 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -199,6 +199,15 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,	\
 #define __NR_sys_gettid __NR_gettid
 _syscall0(int, sys_gettid)
 
+/*
+ * These definitions produce an ENOSYS from the host kernel.
+ * Performing a bogus syscall is easier than boilerplating
+ * the replacement functions here in C.
+ */
+#ifndef __NR_syncfs
+#define __NR_syncfs  -1
+#endif
+
 /* For the 64-bit guest on 32-bit host case we must emulate
  * getdents using getdents64, because otherwise the host
  * might hand us back more dirent records than we can fit
@@ -254,11 +263,13 @@ _syscall3(int, ioprio_set, int, which, int, who, int, ioprio)
 #if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
 _syscall3(int, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
 #endif
-
 #if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
 _syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type,
           unsigned long, idx1, unsigned long, idx2)
 #endif
+#ifndef CONFIG_SYNCFS
+_syscall1(int, syncfs, int, fd)
+#endif
 
 static bitmask_transtbl fcntl_flags_tbl[] = {
   { TARGET_O_ACCMODE,   TARGET_O_WRONLY,    O_ACCMODE,   O_WRONLY,    },
@@ -5380,13 +5391,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_sync:
-        sync();
-        return 0;
-#if defined(TARGET_NR_syncfs) && defined(CONFIG_SYNCFS)
-    case TARGET_NR_syncfs:
-        return get_errno(syncfs(arg1));
-#endif
     case TARGET_NR_kill:
         return get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
 #ifdef TARGET_NR_rename
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 3161546afc..749bdce638 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1260,12 +1260,6 @@
 #ifdef TARGET_NR_symlinkat
 { TARGET_NR_symlinkat, "symlinkat", NULL, print_symlinkat, NULL },
 #endif
-#ifdef TARGET_NR_sync
-{ TARGET_NR_sync, "sync" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_syncfs
-{ TARGET_NR_syncfs, "syncfs" , "%s(%d)", NULL, NULL },
-#endif
 #ifdef TARGET_NR_syscall
 { TARGET_NR_syscall, "syscall" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 39/74] linux-user: Split out kill
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (37 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 38/74] linux-user: Split out sync, syncfs Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 40/74] linux-user: Split out rename, renameat, renameat2 Richard Henderson
                   ` (37 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h    |  1 +
 linux-user/syscall.h         |  7 +++-
 linux-user/strace.c          | 76 ++++++++++++++++++------------------
 linux-user/syscall-sig.inc.c |  5 +++
 linux-user/syscall.c         |  2 -
 linux-user/strace.list       |  3 --
 6 files changed, 48 insertions(+), 46 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 497fbdba66..c672b5ad99 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -58,6 +58,7 @@ SYSCALL_DEF(getxpid);
 #ifdef TARGET_NR_ipc
 SYSCALL_DEF_ARGS(ipc, ARG_HEX, ARG_DEC, ARG_DEC, ARG_HEX, ARG_PTR, ARG_HEX);
 #endif
+SYSCALL_DEF(kill, ARG_DEC, ARG_SIGNAL);
 #ifdef TARGET_NR_link
 SYSCALL_DEF(link, ARG_STR, ARG_STR);
 #endif
diff --git a/linux-user/syscall.h b/linux-user/syscall.h
index 84a52b2d9a..642fb6dccb 100644
--- a/linux-user/syscall.h
+++ b/linux-user/syscall.h
@@ -55,8 +55,12 @@ typedef enum {
     ARG_HEX,
     ARG_OCT,
 
-    /* These print as sets of flags.  */
+    /* These numbers are interpreted.  */
     ARG_ATDIRFD,
+    ARG_SIGNAL,
+    ARG_LSEEKWHENCE,
+
+    /* These print as sets of flags.  */
     ARG_ACCESSFLAG,
     ARG_ATFLAG,
     ARG_CLONEFLAG,
@@ -67,7 +71,6 @@ typedef enum {
     ARG_OPENFLAG,
     ARG_UMOUNTFLAG,
     ARG_UNLINKATFLAG,
-    ARG_LSEEKWHENCE,
 
     /* These are interpreted as pointers.  */
     ARG_PTR,
diff --git a/linux-user/strace.c b/linux-user/strace.c
index c42abc2f08..01a5c210fa 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -70,35 +70,43 @@ UNUSED static void print_socket_protocol(int domain, int type, int protocol);
 /*
  * Utility functions
  */
+static int
+add_signal(char *buf, int size, int sig)
+{
+    static const char * const signals[] = {
+        [TARGET_SIGHUP]  = "SIGHUP",
+        [TARGET_SIGINT]  = "SIGINT",
+        [TARGET_SIGQUIT] = "SIGQUIT",
+        [TARGET_SIGILL]  = "SIGILL",
+        [TARGET_SIGABRT] = "SIGABRT",
+        [TARGET_SIGFPE]  = "SIGFPE",
+        [TARGET_SIGKILL] = "SIGKILL",
+        [TARGET_SIGSEGV] = "SIGSEGV",
+        [TARGET_SIGPIPE] = "SIGPIPE",
+        [TARGET_SIGALRM] = "SIGALRM",
+        [TARGET_SIGTERM] = "SIGTERM",
+        [TARGET_SIGUSR1] = "SIGUSR1",
+        [TARGET_SIGUSR2] = "SIGUSR2",
+        [TARGET_SIGCHLD] = "SIGCHLD",
+        [TARGET_SIGCONT] = "SIGCONT",
+        [TARGET_SIGSTOP] = "SIGSTOP",
+        [TARGET_SIGTTIN] = "SIGTTIN",
+        [TARGET_SIGTTOU] = "SIGTTOU",
+    };
+
+    if (sig >= 0 && sig < ARRAY_SIZE(signals) && signals[sig]) {
+        return snprintf(buf, size, "%s", signals[sig]);
+    } else {
+        return snprintf(buf, size, "%d", sig);
+    }
+}
+
 static void
 print_signal(abi_ulong arg, int last)
 {
-    const char *signal_name = NULL;
-    switch(arg) {
-    case TARGET_SIGHUP: signal_name = "SIGHUP"; break;
-    case TARGET_SIGINT: signal_name = "SIGINT"; break;
-    case TARGET_SIGQUIT: signal_name = "SIGQUIT"; break;
-    case TARGET_SIGILL: signal_name = "SIGILL"; break;
-    case TARGET_SIGABRT: signal_name = "SIGABRT"; break;
-    case TARGET_SIGFPE: signal_name = "SIGFPE"; break;
-    case TARGET_SIGKILL: signal_name = "SIGKILL"; break;
-    case TARGET_SIGSEGV: signal_name = "SIGSEGV"; break;
-    case TARGET_SIGPIPE: signal_name = "SIGPIPE"; break;
-    case TARGET_SIGALRM: signal_name = "SIGALRM"; break;
-    case TARGET_SIGTERM: signal_name = "SIGTERM"; break;
-    case TARGET_SIGUSR1: signal_name = "SIGUSR1"; break;
-    case TARGET_SIGUSR2: signal_name = "SIGUSR2"; break;
-    case TARGET_SIGCHLD: signal_name = "SIGCHLD"; break;
-    case TARGET_SIGCONT: signal_name = "SIGCONT"; break;
-    case TARGET_SIGSTOP: signal_name = "SIGSTOP"; break;
-    case TARGET_SIGTTIN: signal_name = "SIGTTIN"; break;
-    case TARGET_SIGTTOU: signal_name = "SIGTTOU"; break;
-    }
-    if (signal_name == NULL) {
-        print_raw_param("%ld", arg, last);
-        return;
-    }
-    gemu_log("%s%s", signal_name, get_comma(last));
+    char buf[16];
+    add_signal(buf, sizeof(buf), arg);
+    gemu_log("%s%s", buf, get_comma(last));
 }
 
 static void print_si_code(int arg)
@@ -2044,19 +2052,6 @@ print_futex(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_kill
-static void
-print_kill(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_raw_param("%d", arg0, 0);
-    print_signal(arg1, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_tkill
 static void
 print_tkill(const struct syscallname *name,
@@ -2190,6 +2185,9 @@ static void print_syscall_def1(const SyscallDef *def, int64_t args[6])
         case ARG_ATDIRFD:
             len = add_atdirfd(b, rest, arg);
             break;
+        case ARG_SIGNAL:
+            len = add_signal(b, rest, arg);
+            break;
         case ARG_ACCESSFLAG:
             len = add_flags(b, rest, access_flags, arg, false);
             break;
diff --git a/linux-user/syscall-sig.inc.c b/linux-user/syscall-sig.inc.c
index f4e43eb00e..a4fbcc567d 100644
--- a/linux-user/syscall-sig.inc.c
+++ b/linux-user/syscall-sig.inc.c
@@ -23,6 +23,11 @@ SYSCALL_IMPL(alarm)
 }
 #endif
 
+SYSCALL_IMPL(kill)
+{
+    return get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
+}
+
 #ifdef TARGET_NR_pause
 SYSCALL_IMPL(pause)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index d612dade23..3fe770890c 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5391,8 +5391,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_kill:
-        return get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
 #ifdef TARGET_NR_rename
     case TARGET_NR_rename:
         {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 749bdce638..07e5f7c518 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -410,9 +410,6 @@
 #ifdef TARGET_NR_keyctl
 { TARGET_NR_keyctl, "keyctl" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_kill
-{ TARGET_NR_kill, "kill", NULL, print_kill, NULL },
-#endif
 #ifdef TARGET_NR_lchown
 { TARGET_NR_lchown, "lchown" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 40/74] linux-user: Split out rename, renameat, renameat2
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (38 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 39/74] linux-user: Split out kill Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 41/74] linux-user: Split out mkdir, mkdirat Richard Henderson
                   ` (36 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Note that renameat2 is universally available for guests.
Merge sys_renameat2 into the new do_renameat2 helper.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  8 +++++
 linux-user/syscall.h          |  1 +
 linux-user/strace.c           | 39 ++++++---------------
 linux-user/syscall-file.inc.c | 45 ++++++++++++++++++++++++
 linux-user/syscall.c          | 64 -----------------------------------
 linux-user/strace.list        |  9 -----
 6 files changed, 65 insertions(+), 101 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index c672b5ad99..0ed01aa100 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -142,6 +142,14 @@ SYSCALL_DEF(readlink, ARG_STR, ARG_PTR, ARG_DEC);
 #ifdef TARGET_NR_readlinkat
 SYSCALL_DEF(readlinkat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_DEC);
 #endif
+#ifdef TARGET_NR_rename
+SYSCALL_DEF(rename, ARG_STR, ARG_STR);
+#endif
+#ifdef TARGET_NR_renameat
+SYSCALL_DEF(renameat, ARG_ATDIRFD, ARG_STR, ARG_ATDIRFD, ARG_STR);
+#endif
+SYSCALL_DEF(renameat2, ARG_ATDIRFD, ARG_STR,
+            ARG_ATDIRFD, ARG_STR, ARG_RENAMEFLAG);
 SYSCALL_DEF(readv, ARG_DEC, ARG_PTR, ARG_DEC);
 #ifdef TARGET_NR_rmdir
 SYSCALL_DEF(rmdir, ARG_STR);
diff --git a/linux-user/syscall.h b/linux-user/syscall.h
index 642fb6dccb..7b197840f5 100644
--- a/linux-user/syscall.h
+++ b/linux-user/syscall.h
@@ -69,6 +69,7 @@ typedef enum {
     ARG_MODEFLAG,
     ARG_MOUNTFLAG,
     ARG_OPENFLAG,
+    ARG_RENAMEFLAG,
     ARG_UMOUNTFLAG,
     ARG_UNLINKATFLAG,
 
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 01a5c210fa..8f871b30ae 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -4,6 +4,7 @@
 #include <arpa/inet.h>
 #include <netinet/tcp.h>
 #include <linux/if_packet.h>
+#include <linux/fs.h>
 #include <sched.h>
 #include "qemu.h"
 #include "syscall.h"
@@ -741,6 +742,13 @@ static struct flags const mount_flags[] = {
     FLAG_END,
 };
 
+static struct flags const renameat2_flags[] = {
+    FLAG_GENERIC(RENAME_EXCHANGE),
+    FLAG_GENERIC(RENAME_NOREPLACE),
+    FLAG_GENERIC(RENAME_WHITEOUT),
+    FLAG_END,
+};
+
 static struct flags const umount2_flags[] = {
 #ifdef MNT_FORCE
     FLAG_GENERIC(MNT_FORCE),
@@ -1899,34 +1907,6 @@ print_fstatat64(const struct syscallname *name,
 #define print_newfstatat    print_fstatat64
 #endif
 
-#ifdef TARGET_NR_rename
-static void
-print_rename(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 0);
-    print_string(arg1, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
-#ifdef TARGET_NR_renameat
-static void
-print_renameat(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_at_dirfd(arg0, 0);
-    print_string(arg1, 0);
-    print_at_dirfd(arg2, 0);
-    print_string(arg3, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_statfs
 static void
 print_statfs(const struct syscallname *name,
@@ -2212,6 +2192,9 @@ static void print_syscall_def1(const SyscallDef *def, int64_t args[6])
         case ARG_OPENFLAG:
             len = add_open_flags(b, rest, arg);
             break;
+        case ARG_RENAMEFLAG:
+            len = add_flags(b, rest, renameat2_flags, arg, false);
+            break;
         case ARG_UMOUNTFLAG:
             len = add_flags(b, rest, umount2_flags, arg, false);
             break;
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 9f3cf7221a..18553f055e 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -873,6 +873,51 @@ SYSCALL_IMPL(readlinkat)
 }
 #endif
 
+static abi_long do_renameat2(int oldfd, abi_ulong target_oldpath,
+                             int newfd, abi_ulong target_newpath,
+                             unsigned int flags)
+{
+    char *p_old = lock_user_string(target_oldpath);
+    char *p_new = lock_user_string(target_newpath);
+    abi_long ret = -TARGET_EFAULT;
+
+    if (p_old && p_new) {
+        if (flags == 0) {
+            ret = renameat(oldfd, p_old, newfd, p_new);
+        } else {
+#ifdef __NR_renameat2
+            ret = syscall(__NR_renameat2, oldfd, p_old, newfd, p_new, flags);
+#else
+            errno = ENOSYS;
+            ret = -1;
+#endif
+        }
+        ret = get_errno(ret);
+    }
+    unlock_user(p_old, target_oldpath, 0);
+    unlock_user(p_new, target_newpath, 0);
+    return ret;
+}
+
+#ifdef TARGET_NR_rename
+SYSCALL_IMPL(rename)
+{
+    return do_renameat2(AT_FDCWD, arg1, AT_FDCWD, arg2, 0);
+}
+#endif
+
+#ifdef TARGET_NR_renameat
+SYSCALL_IMPL(renameat)
+{
+    return do_renameat2(arg1, arg2, arg3, arg4, 0);
+}
+#endif
+
+SYSCALL_IMPL(renameat2)
+{
+    return do_renameat2(arg1, arg2, arg3, arg4, arg5);
+}
+
 SYSCALL_IMPL(sync)
 {
     sync();
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 3fe770890c..d8f6da63cc 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -331,24 +331,6 @@ static int sys_utimensat(int dirfd, const char *pathname,
 #endif
 #endif /* TARGET_NR_utimensat */
 
-#ifdef TARGET_NR_renameat2
-#if defined(__NR_renameat2)
-#define __NR_sys_renameat2 __NR_renameat2
-_syscall5(int, sys_renameat2, int, oldfd, const char *, old, int, newfd,
-          const char *, new, unsigned int, flags)
-#else
-static int sys_renameat2(int oldfd, const char *old,
-                         int newfd, const char *new, int flags)
-{
-    if (flags == 0) {
-        return renameat(oldfd, old, newfd, new);
-    }
-    errno = ENOSYS;
-    return -1;
-}
-#endif
-#endif /* TARGET_NR_renameat2 */
-
 #ifdef CONFIG_INOTIFY
 #include <sys/inotify.h>
 
@@ -5391,52 +5373,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_rename
-    case TARGET_NR_rename:
-        {
-            void *p2;
-            p = lock_user_string(arg1);
-            p2 = lock_user_string(arg2);
-            if (!p || !p2)
-                ret = -TARGET_EFAULT;
-            else
-                ret = get_errno(rename(p, p2));
-            unlock_user(p2, arg2, 0);
-            unlock_user(p, arg1, 0);
-        }
-        return ret;
-#endif
-#if defined(TARGET_NR_renameat)
-    case TARGET_NR_renameat:
-        {
-            void *p2;
-            p  = lock_user_string(arg2);
-            p2 = lock_user_string(arg4);
-            if (!p || !p2)
-                ret = -TARGET_EFAULT;
-            else
-                ret = get_errno(renameat(arg1, p, arg3, p2));
-            unlock_user(p2, arg4, 0);
-            unlock_user(p, arg2, 0);
-        }
-        return ret;
-#endif
-#if defined(TARGET_NR_renameat2)
-    case TARGET_NR_renameat2:
-        {
-            void *p2;
-            p  = lock_user_string(arg2);
-            p2 = lock_user_string(arg4);
-            if (!p || !p2) {
-                ret = -TARGET_EFAULT;
-            } else {
-                ret = get_errno(sys_renameat2(arg1, p, arg3, p2, arg5));
-            }
-            unlock_user(p2, arg4, 0);
-            unlock_user(p, arg2, 0);
-        }
-        return ret;
-#endif
 #ifdef TARGET_NR_mkdir
     case TARGET_NR_mkdir:
         if (!(p = lock_user_string(arg1)))
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 07e5f7c518..3b002a0500 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -944,15 +944,6 @@
 #ifdef TARGET_NR_removexattr
 { TARGET_NR_removexattr, "removexattr" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_rename
-{ TARGET_NR_rename, "rename" , NULL, print_rename, NULL },
-#endif
-#ifdef TARGET_NR_renameat
-{ TARGET_NR_renameat, "renameat" , NULL, print_renameat, NULL },
-#endif
-#ifdef TARGET_NR_renameat2
-{ TARGET_NR_renameat2, "renameat2" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_request_key
 { TARGET_NR_request_key, "request_key" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 41/74] linux-user: Split out mkdir, mkdirat
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (39 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 40/74] linux-user: Split out rename, renameat, renameat2 Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 42/74] linux-user: Split out dup, dup2, dup3 Richard Henderson
                   ` (35 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Note that mkdirat is universally available.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  4 ++++
 linux-user/strace.c           | 27 ---------------------------
 linux-user/syscall-file.inc.c | 25 +++++++++++++++++++++++++
 linux-user/syscall.c          | 16 ----------------
 linux-user/strace.list        |  6 ------
 5 files changed, 29 insertions(+), 49 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 0ed01aa100..8b6d8f75ff 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -69,6 +69,10 @@ SYSCALL_DEF(lseek, ARG_DEC, ARG_DEC, ARG_LSEEKWHENCE);
 #ifdef TARGET_NR_llseek
 SYSCALL_DEF_ARGS(llseek, ARG_DEC, ARG_DEC, ARG_PTR, ARG_LSEEKWHENCE);
 #endif
+#ifdef TARGET_NR_mkdir
+SYSCALL_DEF(mkdir, ARG_STR, ARG_MODEFLAG);
+#endif
+SYSCALL_DEF(mkdirat, ARG_ATDIRFD, ARG_STR, ARG_MODEFLAG);
 #ifdef TARGET_NR_mknod
 SYSCALL_DEF(mknod, ARG_STR, ARG_MODEFLAG, ARG_HEX);
 #endif
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 8f871b30ae..2b31998dbd 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1676,33 +1676,6 @@ print_fstat(const struct syscallname *name,
 #define print_fstat64     print_fstat
 #endif
 
-#ifdef TARGET_NR_mkdir
-static void
-print_mkdir(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 0);
-    print_file_mode(arg1, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
-#ifdef TARGET_NR_mkdirat
-static void
-print_mkdirat(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_at_dirfd(arg0, 0);
-    print_string(arg1, 0);
-    print_file_mode(arg2, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_rt_sigaction
 static void
 print_rt_sigaction(const struct syscallname *name,
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 18553f055e..5ed8b78c79 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -205,6 +205,31 @@ SYSCALL_IMPL(llseek)
 }
 #endif
 
+static abi_long do_mkdirat(int dirfd, abi_ulong target_path, mode_t mode)
+{
+    char *p = lock_user_string(target_path);
+    abi_long ret;
+
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(mkdirat(dirfd, p, mode));
+    unlock_user(p, target_path, 0);
+    return ret;
+}
+
+#ifdef TARGET_NR_mkdir
+SYSCALL_IMPL(mkdir)
+{
+    return do_mkdirat(AT_FDCWD, arg1, arg2);
+}
+#endif
+
+SYSCALL_IMPL(mkdirat)
+{
+    return do_mkdirat(arg1, arg2, arg3);
+}
+
 static abi_long do_mknodat(int dirfd, abi_ulong target_path,
                            mode_t mode, dev_t dev)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index d8f6da63cc..0d6a9b7a6c 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5373,22 +5373,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_mkdir
-    case TARGET_NR_mkdir:
-        if (!(p = lock_user_string(arg1)))
-            return -TARGET_EFAULT;
-        ret = get_errno(mkdir(p, arg2));
-        unlock_user(p, arg1, 0);
-        return ret;
-#endif
-#if defined(TARGET_NR_mkdirat)
-    case TARGET_NR_mkdirat:
-        if (!(p = lock_user_string(arg2)))
-            return -TARGET_EFAULT;
-        ret = get_errno(mkdirat(arg1, p, arg3));
-        unlock_user(p, arg2, 0);
-        return ret;
-#endif
     case TARGET_NR_dup:
         ret = get_errno(dup(arg1));
         if (ret >= 0) {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 3b002a0500..cdbc59bffd 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -473,12 +473,6 @@
 #ifdef TARGET_NR_mincore
 { TARGET_NR_mincore, "mincore" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_mkdir
-{ TARGET_NR_mkdir, "mkdir" , NULL, print_mkdir, NULL },
-#endif
-#ifdef TARGET_NR_mkdirat
-{ TARGET_NR_mkdirat, "mkdirat" , NULL, print_mkdirat, NULL },
-#endif
 #ifdef TARGET_NR_modify_ldt
 { TARGET_NR_modify_ldt, "modify_ldt" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 42/74] linux-user: Split out dup, dup2, dup3
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (40 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 41/74] linux-user: Split out mkdir, mkdirat Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 43/74] linux-user: Split out pipe, pipe2 Richard Henderson
                   ` (34 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Note that dup3 is universally available for guests.
Implement host support with syscall when !CONFIG_DUP3.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  5 +++++
 linux-user/syscall-file.inc.c | 42 +++++++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 33 +++------------------------
 linux-user/strace.list        |  6 -----
 4 files changed, 50 insertions(+), 36 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 8b6d8f75ff..062adddd75 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -34,6 +34,11 @@ SYSCALL_DEF(close, ARG_DEC);
 #ifdef TARGET_NR_creat
 SYSCALL_DEF(creat, ARG_STR, ARG_MODEFLAG);
 #endif
+SYSCALL_DEF(dup, ARG_DEC);
+#ifdef TARGET_NR_dup2
+SYSCALL_DEF(dup2, ARG_DEC, ARG_DEC);
+#endif
+SYSCALL_DEF(dup3, ARG_DEC, ARG_DEC, ARG_OPENFLAG);
 SYSCALL_DEF(exit, ARG_DEC);
 SYSCALL_DEF(execve, ARG_STR, ARG_PTR, ARG_PTR);
 SYSCALL_DEF(execveat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_PTR, ARG_ATFLAG);
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 5ed8b78c79..7d97dd1ec1 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -94,6 +94,48 @@ SYSCALL_IMPL(creat)
 }
 #endif
 
+SYSCALL_IMPL(dup)
+{
+    abi_long ret = get_errno(dup(arg1));
+    if (ret >= 0) {
+        fd_trans_dup(arg1, ret);
+    }
+    return ret;
+}
+
+#ifdef TARGET_NR_dup2
+SYSCALL_IMPL(dup2)
+{
+    abi_long ret = get_errno(dup2(arg1, arg2));
+    if (ret >= 0) {
+        fd_trans_dup(arg1, arg2);
+    }
+    return ret;
+}
+#endif
+
+SYSCALL_IMPL(dup3)
+{
+    int ofd = arg1;
+    int nfd = arg2;
+    int host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl);
+    abi_long ret;
+
+#ifdef CONFIG_DUP3
+    ret = dup3(ofd, nfd, host_flags);
+#else
+    if (host_flags == 0) {
+        if (ofd == nfd) {
+            return -TARGET_EINVAL;
+        }
+        ret = dup2(ofd, nfd);
+    } else {
+        ret = syscall(__NR_dup3, ofd, nfd, host_flags);
+    }
+#endif
+    return get_errno(ret);
+}
+
 SYSCALL_IMPL(faccessat)
 {
     return do_faccessat(arg1, arg2, arg3);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 0d6a9b7a6c..bab9a57ee0 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -204,6 +204,9 @@ _syscall0(int, sys_gettid)
  * Performing a bogus syscall is easier than boilerplating
  * the replacement functions here in C.
  */
+#ifndef __NR_dup3
+#define __NR_dup3  -1
+#endif
 #ifndef __NR_syncfs
 #define __NR_syncfs  -1
 #endif
@@ -5373,12 +5376,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_dup:
-        ret = get_errno(dup(arg1));
-        if (ret >= 0) {
-            fd_trans_dup(arg1, ret);
-        }
-        return ret;
 #ifdef TARGET_NR_pipe
     case TARGET_NR_pipe:
         return do_pipe(cpu_env, arg1, 0, 0);
@@ -5433,30 +5430,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         ret = get_errno(chroot(p));
         unlock_user(p, arg1, 0);
         return ret;
-#ifdef TARGET_NR_dup2
-    case TARGET_NR_dup2:
-        ret = get_errno(dup2(arg1, arg2));
-        if (ret >= 0) {
-            fd_trans_dup(arg1, arg2);
-        }
-        return ret;
-#endif
-#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
-    case TARGET_NR_dup3:
-    {
-        int host_flags;
-
-        if ((arg3 & ~TARGET_O_CLOEXEC) != 0) {
-            return -EINVAL;
-        }
-        host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl);
-        ret = get_errno(dup3(arg1, arg2, host_flags));
-        if (ret >= 0) {
-            fd_trans_dup(arg1, arg2);
-        }
-        return ret;
-    }
-#endif
 #ifdef TARGET_NR_getpgrp
     case TARGET_NR_getpgrp:
         return get_errno(getpgrp());
diff --git a/linux-user/strace.list b/linux-user/strace.list
index cdbc59bffd..2f78f4685b 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -91,12 +91,6 @@
 #ifdef TARGET_NR_dipc
 { TARGET_NR_dipc, "dipc" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_dup
-{ TARGET_NR_dup, "dup" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_dup2
-{ TARGET_NR_dup2, "dup2" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_epoll_create
 { TARGET_NR_epoll_create, "epoll_create" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 43/74] linux-user: Split out pipe, pipe2
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (41 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 42/74] linux-user: Split out dup, dup2, dup3 Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 44/74] linux-user: Split out times Richard Henderson
                   ` (33 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Note that pipe2 is universally available for guests.
Implement host support with syscall when !CONFIG_PIPE2.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     | 10 ++++++
 linux-user/syscall-file.inc.c | 51 +++++++++++++++++++++++++++
 linux-user/syscall.c          | 65 +++++++----------------------------
 linux-user/strace.list        |  6 ----
 4 files changed, 74 insertions(+), 58 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 062adddd75..bd3301a72f 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -132,6 +132,16 @@ SYSCALL_DEF(open_by_handle_at, ARG_DEC, ARG_PTR, ARG_OPENFLAG);
 #ifdef TARGET_NR_pause
 SYSCALL_DEF(pause);
 #endif
+#ifdef TARGET_NR_pipe
+# if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || \
+     defined(TARGET_SH4) || defined(TARGET_SPARC)
+/* ??? We have no way for strace to display the second returned fd.  */
+SYSCALL_DEF(pipe);
+# else
+SYSCALL_DEF(pipe, ARG_PTR);
+# endif
+#endif
+SYSCALL_DEF(pipe2, ARG_PTR, ARG_OPENFLAG);
 SYSCALL_DEF_FULL(pread64, .impl = impl_pread64,
                  .args = args_pread64_pwrite64,
                  .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 });
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 7d97dd1ec1..5bd9eaa002 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -726,6 +726,57 @@ SYSCALL_IMPL(open_by_handle_at)
     return ret;
 }
 
+static abi_long do_pipe(CPUArchState *cpu_env, abi_ulong target_fds,
+                        int target_flags, bool is_pipe2)
+{
+    int host_flags = target_to_host_bitmask(target_flags, fcntl_flags_tbl);
+    int host_fds[2];
+    abi_long ret;
+
+    ret = pipe2(host_fds, host_flags);
+    if (is_error(ret)) {
+        return get_errno(ret);
+    }
+
+    /*
+     * Several targets have special calling conventions for the original
+     * pipe syscall, but didn't replicate this into the pipe2 syscall.
+     */
+    if (!is_pipe2) {
+#if defined(TARGET_ALPHA)
+        cpu_env->ir[IR_A4] = host_fds[1];
+        return host_fds[0];
+#elif defined(TARGET_MIPS)
+        cpu_env->active_tc.gpr[3] = host_fds[1];
+        return host_fds[0];
+#elif defined(TARGET_SH4)
+        cpu_env->gregs[1] = host_fds[1];
+        return host_fds[0];
+#elif defined(TARGET_SPARC)
+        cpu_env->regwptr[1] = host_fds[1];
+        return host_fds[0];
+#endif
+    }
+
+    if (put_user_s32(host_fds[0], target_fds)
+        || put_user_s32(host_fds[1], target_fds + 4)) {
+        return -TARGET_EFAULT;
+    }
+    return 0;
+}
+
+#ifdef TARGET_NR_pipe
+SYSCALL_IMPL(pipe)
+{
+    return do_pipe(cpu_env, arg1, 0, false);
+}
+#endif
+
+SYSCALL_IMPL(pipe2)
+{
+    return do_pipe(cpu_env, arg1, arg2, true);
+}
+
 /*
  * Both pread64 and pwrite64 merge args into a 64-bit offset,
  * but the input registers and ordering are target specific.
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index bab9a57ee0..cda1f8a205 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -207,6 +207,9 @@ _syscall0(int, sys_gettid)
 #ifndef __NR_dup3
 #define __NR_dup3  -1
 #endif
+#ifndef __NR_pipe2
+#define __NR_pipe2  -1
+#endif
 #ifndef __NR_syncfs
 #define __NR_syncfs  -1
 #endif
@@ -273,6 +276,16 @@ _syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type,
 #ifndef CONFIG_SYNCFS
 _syscall1(int, syncfs, int, fd)
 #endif
+#ifndef CONFIG_PIPE2
+static int pipe2(int *fds, int flags)
+{
+    if (flags) {
+        return syscall(__NR_pipe2, fds, flags);
+    } else {
+        return pipe(fds);
+    }
+}
+#endif
 
 static bitmask_transtbl fcntl_flags_tbl[] = {
   { TARGET_O_ACCMODE,   TARGET_O_WRONLY,    O_ACCMODE,   O_WRONLY,    },
@@ -1124,49 +1137,6 @@ static abi_long do_old_select(abi_ulong arg1)
 #endif
 #endif
 
-static abi_long do_pipe2(int host_pipe[], int flags)
-{
-#ifdef CONFIG_PIPE2
-    return pipe2(host_pipe, flags);
-#else
-    return -ENOSYS;
-#endif
-}
-
-static abi_long do_pipe(void *cpu_env, abi_ulong pipedes,
-                        int flags, int is_pipe2)
-{
-    int host_pipe[2];
-    abi_long ret;
-    ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe);
-
-    if (is_error(ret))
-        return get_errno(ret);
-
-    /* Several targets have special calling conventions for the original
-       pipe syscall, but didn't replicate this into the pipe2 syscall.  */
-    if (!is_pipe2) {
-#if defined(TARGET_ALPHA)
-        ((CPUAlphaState *)cpu_env)->ir[IR_A4] = host_pipe[1];
-        return host_pipe[0];
-#elif defined(TARGET_MIPS)
-        ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1];
-        return host_pipe[0];
-#elif defined(TARGET_SH4)
-        ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
-        return host_pipe[0];
-#elif defined(TARGET_SPARC)
-        ((CPUSPARCState*)cpu_env)->regwptr[1] = host_pipe[1];
-        return host_pipe[0];
-#endif
-    }
-
-    if (put_user_s32(host_pipe[0], pipedes)
-        || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0])))
-        return -TARGET_EFAULT;
-    return get_errno(ret);
-}
-
 static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
                                               abi_ulong target_addr,
                                               socklen_t len)
@@ -5376,15 +5346,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_pipe
-    case TARGET_NR_pipe:
-        return do_pipe(cpu_env, arg1, 0, 0);
-#endif
-#ifdef TARGET_NR_pipe2
-    case TARGET_NR_pipe2:
-        return do_pipe(cpu_env, arg1,
-                       target_to_host_bitmask(arg2, fcntl_flags_tbl), 1);
-#endif
     case TARGET_NR_times:
         {
             struct target_tms *tmsp;
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 2f78f4685b..a1c3dd98e0 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -860,9 +860,6 @@
 #ifdef TARGET_NR_personality
 { TARGET_NR_personality, "personality" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_pipe
-{ TARGET_NR_pipe, "pipe" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_pivot_root
 { TARGET_NR_pivot_root, "pivot_root" , NULL, NULL, NULL },
 #endif
@@ -1377,9 +1374,6 @@
 #ifdef TARGET_NR_sync_file_range2
 { TARGET_NR_sync_file_range2, "sync_file_range2", NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_pipe2
-{ TARGET_NR_pipe2, "pipe2", NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_atomic_cmpxchg_32
 { TARGET_NR_atomic_cmpxchg_32, "atomic_cmpxchg_32", NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 44/74] linux-user: Split out times
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (42 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 43/74] linux-user: Split out pipe, pipe2 Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 45/74] linux-user: Split out acct Richard Henderson
                   ` (32 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  1 +
 linux-user/syscall-proc.inc.c | 25 +++++++++++++++++++++++++
 linux-user/syscall.c          | 18 ------------------
 linux-user/strace.list        |  3 ---
 4 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index bd3301a72f..25d5aaccd1 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -204,6 +204,7 @@ SYSCALL_DEF(syncfs, ARG_DEC);
 #ifdef TARGET_NR_time
 SYSCALL_DEF(time, ARG_PTR);
 #endif
+SYSCALL_DEF(times, ARG_PTR);
 #ifdef TARGET_NR_umount
 SYSCALL_DEF(umount, ARG_STR);
 #endif
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
index e29c2ede25..517f84e139 100644
--- a/linux-user/syscall-proc.inc.c
+++ b/linux-user/syscall-proc.inc.c
@@ -468,6 +468,31 @@ SYSCALL_IMPL(nice)
 }
 #endif
 
+SYSCALL_IMPL(times)
+{
+    abi_ulong target_buf = arg1;
+    struct tms tms;
+    abi_long ret;
+
+    ret = get_errno(times(&tms));
+    if (target_buf) {
+        struct target_tms *tmsp = lock_user(VERIFY_WRITE, target_buf,
+                                            sizeof(struct target_tms), 0);
+        if (!tmsp) {
+            return -TARGET_EFAULT;
+        }
+        tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime));
+        tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime));
+        tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime));
+        tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime));
+        unlock_user(tmsp, target_buf, sizeof(struct target_tms));
+    }
+    if (!is_error(ret)) {
+        ret = host_to_target_clock_t(ret);
+    }
+    return ret;
+}
+
 /*
  * Map host to target signal numbers for the wait family of syscalls.
  * Assume all other status bits are the same.
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index cda1f8a205..cdca0dbe4f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5346,24 +5346,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_times:
-        {
-            struct target_tms *tmsp;
-            struct tms tms;
-            ret = get_errno(times(&tms));
-            if (arg1) {
-                tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
-                if (!tmsp)
-                    return -TARGET_EFAULT;
-                tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime));
-                tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime));
-                tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime));
-                tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime));
-            }
-            if (!is_error(ret))
-                ret = host_to_target_clock_t(ret);
-        }
-        return ret;
     case TARGET_NR_acct:
         if (arg1 == 0) {
             ret = get_errno(acct(NULL));
diff --git a/linux-user/strace.list b/linux-user/strace.list
index a1c3dd98e0..85e3de87d8 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1290,9 +1290,6 @@
 #ifdef TARGET_NR_timerfd_settime
 { TARGET_NR_timerfd_settime, "timerfd_settime" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_times
-{ TARGET_NR_times, "times" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_tkill
 { TARGET_NR_tkill, "tkill" , NULL, print_tkill, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 45/74] linux-user: Split out acct
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (43 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 44/74] linux-user: Split out times Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 46/74] linux-user: Move syscall_init to the end Richard Henderson
                   ` (31 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  1 +
 linux-user/syscall-file.inc.c | 18 ++++++++++++++++++
 linux-user/syscall.c          | 11 -----------
 linux-user/strace.list        |  3 ---
 4 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 25d5aaccd1..f8f280f376 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -19,6 +19,7 @@
 #ifdef TARGET_NR_access
 SYSCALL_DEF(access, ARG_STR, ARG_ACCESSFLAG);
 #endif
+SYSCALL_DEF(acct, ARG_STR);
 #ifdef TARGET_NR_alarm
 SYSCALL_DEF(alarm, ARG_DEC);
 #endif
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 5bd9eaa002..4080ab250e 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -36,6 +36,24 @@ SYSCALL_IMPL(access)
 }
 #endif
 
+SYSCALL_IMPL(acct)
+{
+    abi_ulong target_path = arg1;
+    abi_long ret;
+
+    if (target_path == 0) {
+        ret = get_errno(acct(NULL));
+    } else {
+        char *p = lock_user_string(target_path);
+        if (!p) {
+            return -TARGET_EFAULT;
+        }
+        ret = get_errno(acct(path(p)));
+        unlock_user(p, target_path, 0);
+    }
+    return ret;
+}
+
 SYSCALL_IMPL(chdir)
 {
     abi_ulong target_path = arg1;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index cdca0dbe4f..5343486a58 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5346,17 +5346,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_acct:
-        if (arg1 == 0) {
-            ret = get_errno(acct(NULL));
-        } else {
-            if (!(p = lock_user_string(arg1))) {
-                return -TARGET_EFAULT;
-            }
-            ret = get_errno(acct(path(p)));
-            unlock_user(p, arg1, 0);
-        }
-        return ret;
     case TARGET_NR_ioctl:
         return do_ioctl(arg1, arg2, arg3);
 #ifdef TARGET_NR_fcntl
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 85e3de87d8..ce5e02975b 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -9,9 +9,6 @@
 #ifdef TARGET_NR_accept4
 { TARGET_NR_accept4, "accept4" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_acct
-{ TARGET_NR_acct, "acct" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_add_key
 { TARGET_NR_add_key, "add_key" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 46/74] linux-user: Move syscall_init to the end
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (44 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 45/74] linux-user: Split out acct Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 47/74] linux-user: Split out ioctl Richard Henderson
                   ` (30 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

No functional change.  This will aid moving everything
related to ioctls to a separate file.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall.c | 113 +++++++++++++++++++++++--------------------
 1 file changed, 61 insertions(+), 52 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 5343486a58..d0e76c392e 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4831,58 +4831,6 @@ _syscall1(int, sys_setgid, gid_t, gid)
 _syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
 _syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
 
-void syscall_init(void)
-{
-    IOCTLEntry *ie;
-    const argtype *arg_type;
-    int size;
-    int i;
-
-    thunk_init(STRUCT_MAX);
-
-#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
-#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
-#include "syscall_types.h"
-#undef STRUCT
-#undef STRUCT_SPECIAL
-
-    /* Build target_to_host_errno_table[] table from
-     * host_to_target_errno_table[]. */
-    for (i = 0; i < ERRNO_TABLE_SIZE; i++) {
-        target_to_host_errno_table[host_to_target_errno_table[i]] = i;
-    }
-
-    /* we patch the ioctl size if necessary. We rely on the fact that
-       no ioctl has all the bits at '1' in the size field */
-    ie = ioctl_entries;
-    while (ie->target_cmd != 0) {
-        if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
-            TARGET_IOC_SIZEMASK) {
-            arg_type = ie->arg_type;
-            if (arg_type[0] != TYPE_PTR) {
-                fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
-                        ie->target_cmd);
-                exit(1);
-            }
-            arg_type++;
-            size = thunk_type_size(arg_type, 0);
-            ie->target_cmd = (ie->target_cmd &
-                              ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
-                (size << TARGET_IOC_SIZESHIFT);
-        }
-
-        /* automatic consistency check if same arch */
-#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
-    (defined(__x86_64__) && defined(TARGET_X86_64))
-        if (unlikely(ie->target_cmd != ie->host_cmd)) {
-            fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
-                    ie->name, ie->target_cmd, ie->host_cmd);
-        }
-#endif
-        ie++;
-    }
-}
-
 static inline uint64_t target_offset64(abi_ulong word0, abi_ulong word1)
 {
 #if TARGET_ABI_BITS == 64
@@ -9072,3 +9020,64 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     trace_guest_user_syscall_ret(cpu, num, ret);
     return ret;
 }
+
+void syscall_init(void)
+{
+    IOCTLEntry *ie;
+    const argtype *arg_type;
+    int size;
+    int i;
+
+    thunk_init(STRUCT_MAX);
+
+#define STRUCT(name, ...) \
+    thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
+#define STRUCT_SPECIAL(name) \
+    thunk_register_struct_direct(STRUCT_ ## name, #name, \
+                                 &struct_ ## name ## _def);
+
+#include "syscall_types.h"
+
+#undef STRUCT
+#undef STRUCT_SPECIAL
+
+    /*
+     * Build target_to_host_errno_table[] table from
+     * host_to_target_errno_table[].
+     */
+    for (i = 0; i < ERRNO_TABLE_SIZE; i++) {
+        target_to_host_errno_table[host_to_target_errno_table[i]] = i;
+    }
+
+    /*
+     * We patch the ioctl size if necessary.  We rely on the fact that
+     * no ioctl has all the bits at '1' in the size field.
+     */
+    ie = ioctl_entries;
+    while (ie->target_cmd != 0) {
+        if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
+            TARGET_IOC_SIZEMASK) {
+            arg_type = ie->arg_type;
+            if (arg_type[0] != TYPE_PTR) {
+                fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
+                        ie->target_cmd);
+                exit(1);
+            }
+            arg_type++;
+            size = thunk_type_size(arg_type, 0);
+            ie->target_cmd = (ie->target_cmd &
+                              ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
+                (size << TARGET_IOC_SIZESHIFT);
+        }
+
+        /* automatic consistency check if same arch */
+#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
+    (defined(__x86_64__) && defined(TARGET_X86_64))
+        if (unlikely(ie->target_cmd != ie->host_cmd)) {
+            fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
+                    ie->name, ie->target_cmd, ie->host_cmd);
+        }
+#endif
+        ie++;
+    }
+}
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 47/74] linux-user: Split out ioctl
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (45 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 46/74] linux-user: Move syscall_init to the end Richard Henderson
@ 2019-05-19 20:36 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 48/74] linux-user: Fix types in ioctl logging Richard Henderson
                   ` (29 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v7: Do not accidentally change type of "cmd".
---
 linux-user/syscall-defs.h      |   1 +
 linux-user/syscall-ioctl.inc.c | 873 +++++++++++++++++++++++++++++++++
 linux-user/syscall.c           | 852 +-------------------------------
 linux-user/strace.list         |   3 -
 4 files changed, 875 insertions(+), 854 deletions(-)
 create mode 100644 linux-user/syscall-ioctl.inc.c

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index f8f280f376..f58b9745a4 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -61,6 +61,7 @@ SYSCALL_DEF(getppid);
 #ifdef TARGET_NR_getxpid
 SYSCALL_DEF(getxpid);
 #endif
+SYSCALL_DEF(ioctl, ARG_DEC, ARG_HEX);
 #ifdef TARGET_NR_ipc
 SYSCALL_DEF_ARGS(ipc, ARG_HEX, ARG_DEC, ARG_DEC, ARG_HEX, ARG_PTR, ARG_HEX);
 #endif
diff --git a/linux-user/syscall-ioctl.inc.c b/linux-user/syscall-ioctl.inc.c
new file mode 100644
index 0000000000..be3f0b4b92
--- /dev/null
+++ b/linux-user/syscall-ioctl.inc.c
@@ -0,0 +1,873 @@
+/*
+ *  Linux ioctl syscall implementation
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+typedef struct IOCTLEntry IOCTLEntry;
+
+typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
+                             int fd, int cmd, abi_long arg);
+
+struct IOCTLEntry {
+    int target_cmd;
+    unsigned int host_cmd;
+    const char *name;
+    int access;
+    do_ioctl_fn *do_ioctl;
+    const argtype arg_type[5];
+};
+
+#define IOC_R 0x0001
+#define IOC_W 0x0002
+#define IOC_RW (IOC_R | IOC_W)
+
+#define MAX_STRUCT_SIZE 4096
+
+#ifdef CONFIG_FIEMAP
+/*
+ * So fiemap access checks don't overflow on 32 bit systems.
+ * This is very slightly smaller than the limit imposed by
+ * the underlying kernel.
+ */
+#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap))  \
+                            / sizeof(struct fiemap_extent))
+
+static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
+                                       int fd, int cmd, abi_long arg)
+{
+    /*
+     * The parameter for this ioctl is a struct fiemap followed
+     * by an array of struct fiemap_extent whose size is set
+     * in fiemap->fm_extent_count. The array is filled in by the
+     * ioctl.
+     */
+    int target_size_in, target_size_out;
+    struct fiemap *fm;
+    const argtype *arg_type = ie->arg_type;
+    const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
+    void *argptr, *p;
+    abi_long ret;
+    int i, extent_size = thunk_type_size(extent_arg_type, 0);
+    uint32_t outbufsz;
+    int free_fm = 0;
+
+    assert(arg_type[0] == TYPE_PTR);
+    assert(ie->access == IOC_RW);
+    arg_type++;
+    target_size_in = thunk_type_size(arg_type, 0);
+    argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
+    if (!argptr) {
+        return -TARGET_EFAULT;
+    }
+    thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+    unlock_user(argptr, arg, 0);
+    fm = (struct fiemap *)buf_temp;
+    if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
+        return -TARGET_EINVAL;
+    }
+
+    outbufsz = sizeof(*fm) + sizeof(struct fiemap_extent) * fm->fm_extent_count;
+
+    if (outbufsz > MAX_STRUCT_SIZE) {
+        /*
+         * We can't fit all the extents into the fixed size buffer.
+         * Allocate one that is large enough and use it instead.
+         */
+        fm = g_try_malloc(outbufsz);
+        if (!fm) {
+            return -TARGET_ENOMEM;
+        }
+        memcpy(fm, buf_temp, sizeof(struct fiemap));
+        free_fm = 1;
+    }
+    ret = get_errno(safe_ioctl(fd, ie->host_cmd, fm));
+    if (!is_error(ret)) {
+        target_size_out = target_size_in;
+        /*
+         * An extent_count of 0 means we were only counting the extents
+         * so there are no structs to copy
+         */
+        if (fm->fm_extent_count != 0) {
+            target_size_out += fm->fm_mapped_extents * extent_size;
+        }
+        argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
+        if (!argptr) {
+            ret = -TARGET_EFAULT;
+        } else {
+            /* Convert the struct fiemap */
+            thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
+            if (fm->fm_extent_count != 0) {
+                p = argptr + target_size_in;
+                /* ...and then all the struct fiemap_extents */
+                for (i = 0; i < fm->fm_mapped_extents; i++) {
+                    thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
+                                  THUNK_TARGET);
+                    p += extent_size;
+                }
+            }
+            unlock_user(argptr, arg, target_size_out);
+        }
+    }
+    if (free_fm) {
+        g_free(fm);
+    }
+    return ret;
+}
+#endif
+
+static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
+                                int fd, int cmd, abi_long arg)
+{
+    const argtype *arg_type = ie->arg_type;
+    int target_size;
+    void *argptr;
+    int ret;
+    struct ifconf *host_ifconf;
+    uint32_t outbufsz;
+    const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
+    int target_ifreq_size;
+    int nb_ifreq;
+    int free_buf = 0;
+    int i;
+    int target_ifc_len;
+    abi_long target_ifc_buf;
+    int host_ifc_len;
+    char *host_ifc_buf;
+
+    assert(arg_type[0] == TYPE_PTR);
+    assert(ie->access == IOC_RW);
+
+    arg_type++;
+    target_size = thunk_type_size(arg_type, 0);
+
+    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+    if (!argptr) {
+        return -TARGET_EFAULT;
+    }
+    thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+    unlock_user(argptr, arg, 0);
+
+    host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
+    target_ifc_len = host_ifconf->ifc_len;
+    target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
+
+    target_ifreq_size = thunk_type_size(ifreq_arg_type, 0);
+    nb_ifreq = target_ifc_len / target_ifreq_size;
+    host_ifc_len = nb_ifreq * sizeof(struct ifreq);
+
+    outbufsz = sizeof(*host_ifconf) + host_ifc_len;
+    if (outbufsz > MAX_STRUCT_SIZE) {
+        /*
+         * We can't fit all the extents into the fixed size buffer.
+         * Allocate one that is large enough and use it instead.
+         */
+        host_ifconf = malloc(outbufsz);
+        if (!host_ifconf) {
+            return -TARGET_ENOMEM;
+        }
+        memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
+        free_buf = 1;
+    }
+    host_ifc_buf = (char *)host_ifconf + sizeof(*host_ifconf);
+
+    host_ifconf->ifc_len = host_ifc_len;
+    host_ifconf->ifc_buf = host_ifc_buf;
+
+    ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_ifconf));
+    if (!is_error(ret)) {
+        /* convert host ifc_len to target ifc_len */
+
+        nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
+        target_ifc_len = nb_ifreq * target_ifreq_size;
+        host_ifconf->ifc_len = target_ifc_len;
+
+        /* restore target ifc_buf */
+
+        host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
+
+        /* copy struct ifconf to target user */
+
+        argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
+        if (!argptr) {
+            return -TARGET_EFAULT;
+        }
+        thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
+        unlock_user(argptr, arg, target_size);
+
+        /* copy ifreq[] to target user */
+
+        argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
+        for (i = 0; i < nb_ifreq ; i++) {
+            thunk_convert(argptr + i * target_ifreq_size,
+                          host_ifc_buf + i * sizeof(struct ifreq),
+                          ifreq_arg_type, THUNK_TARGET);
+        }
+        unlock_user(argptr, target_ifc_buf, target_ifc_len);
+    }
+
+    if (free_buf) {
+        free(host_ifconf);
+    }
+
+    return ret;
+}
+
+#if defined(CONFIG_USBFS)
+#if HOST_LONG_BITS > 64
+#error USBDEVFS thunks do not support >64 bit hosts yet.
+#endif
+struct live_urb {
+    uint64_t target_urb_adr;
+    uint64_t target_buf_adr;
+    char *target_buf_ptr;
+    struct usbdevfs_urb host_urb;
+};
+
+static GHashTable *usbdevfs_urb_hashtable(void)
+{
+    static GHashTable *urb_hashtable;
+
+    if (!urb_hashtable) {
+        urb_hashtable = g_hash_table_new(g_int64_hash, g_int64_equal);
+    }
+    return urb_hashtable;
+}
+
+static void urb_hashtable_insert(struct live_urb *urb)
+{
+    GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
+    g_hash_table_insert(urb_hashtable, urb, urb);
+}
+
+static struct live_urb *urb_hashtable_lookup(uint64_t target_urb_adr)
+{
+    GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
+    return g_hash_table_lookup(urb_hashtable, &target_urb_adr);
+}
+
+static void urb_hashtable_remove(struct live_urb *urb)
+{
+    GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
+    g_hash_table_remove(urb_hashtable, urb);
+}
+
+static abi_long
+do_ioctl_usbdevfs_reapurb(const IOCTLEntry *ie, uint8_t *buf_temp,
+                          int fd, int cmd, abi_long arg)
+{
+    const argtype usbfsurb_arg_type[] = { MK_STRUCT(STRUCT_usbdevfs_urb) };
+    const argtype ptrvoid_arg_type[] = { TYPE_PTRVOID, 0, 0 };
+    struct live_urb *lurb;
+    void *argptr;
+    uint64_t hurb;
+    int target_size;
+    uintptr_t target_urb_adr;
+    abi_long ret;
+
+    target_size = thunk_type_size(usbfsurb_arg_type, THUNK_TARGET);
+
+    memset(buf_temp, 0, sizeof(uint64_t));
+    ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
+    if (is_error(ret)) {
+        return ret;
+    }
+
+    memcpy(&hurb, buf_temp, sizeof(uint64_t));
+    lurb = (void *)((uintptr_t)hurb - offsetof(struct live_urb, host_urb));
+    if (!lurb->target_urb_adr) {
+        return -TARGET_EFAULT;
+    }
+    urb_hashtable_remove(lurb);
+    unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr,
+                lurb->host_urb.buffer_length);
+    lurb->target_buf_ptr = NULL;
+
+    /* restore the guest buffer pointer */
+    lurb->host_urb.buffer = (void *)(uintptr_t)lurb->target_buf_adr;
+
+    /* update the guest urb struct */
+    argptr = lock_user(VERIFY_WRITE, lurb->target_urb_adr, target_size, 0);
+    if (!argptr) {
+        g_free(lurb);
+        return -TARGET_EFAULT;
+    }
+    thunk_convert(argptr, &lurb->host_urb, usbfsurb_arg_type, THUNK_TARGET);
+    unlock_user(argptr, lurb->target_urb_adr, target_size);
+
+    target_size = thunk_type_size(ptrvoid_arg_type, THUNK_TARGET);
+    /* write back the urb handle */
+    argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
+    if (!argptr) {
+        g_free(lurb);
+        return -TARGET_EFAULT;
+    }
+
+    /* GHashTable uses 64-bit keys but thunk_convert expects uintptr_t */
+    target_urb_adr = lurb->target_urb_adr;
+    thunk_convert(argptr, &target_urb_adr, ptrvoid_arg_type, THUNK_TARGET);
+    unlock_user(argptr, arg, target_size);
+
+    g_free(lurb);
+    return ret;
+}
+
+static abi_long
+do_ioctl_usbdevfs_discardurb(const IOCTLEntry *ie,
+                             uint8_t *buf_temp __attribute__((unused)),
+                             int fd, int cmd, abi_long arg)
+{
+    struct live_urb *lurb;
+
+    /* map target address back to host URB with metadata. */
+    lurb = urb_hashtable_lookup(arg);
+    if (!lurb) {
+        return -TARGET_EFAULT;
+    }
+    return get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
+}
+
+static abi_long
+do_ioctl_usbdevfs_submiturb(const IOCTLEntry *ie, uint8_t *buf_temp,
+                            int fd, int cmd, abi_long arg)
+{
+    const argtype *arg_type = ie->arg_type;
+    int target_size;
+    abi_long ret;
+    void *argptr;
+    int rw_dir;
+    struct live_urb *lurb;
+
+    /*
+     * each submitted URB needs to map to a unique ID for the
+     * kernel, and that unique ID needs to be a pointer to
+     * host memory.  hence, we need to malloc for each URB.
+     * isochronous transfers have a variable length struct.
+     */
+    arg_type++;
+    target_size = thunk_type_size(arg_type, THUNK_TARGET);
+
+    /* construct host copy of urb and metadata */
+    lurb = g_try_malloc0(sizeof(struct live_urb));
+    if (!lurb) {
+        return -TARGET_ENOMEM;
+    }
+
+    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+    if (!argptr) {
+        g_free(lurb);
+        return -TARGET_EFAULT;
+    }
+    thunk_convert(&lurb->host_urb, argptr, arg_type, THUNK_HOST);
+    unlock_user(argptr, arg, 0);
+
+    lurb->target_urb_adr = arg;
+    lurb->target_buf_adr = (uintptr_t)lurb->host_urb.buffer;
+
+    /* buffer space used depends on endpoint type so lock the entire buffer */
+    /* control type urbs should check the buffer contents for true direction */
+    rw_dir = lurb->host_urb.endpoint & USB_DIR_IN ? VERIFY_WRITE : VERIFY_READ;
+    lurb->target_buf_ptr = lock_user(rw_dir, lurb->target_buf_adr,
+                                     lurb->host_urb.buffer_length, 1);
+    if (lurb->target_buf_ptr == NULL) {
+        g_free(lurb);
+        return -TARGET_EFAULT;
+    }
+
+    /* update buffer pointer in host copy */
+    lurb->host_urb.buffer = lurb->target_buf_ptr;
+
+    ret = get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
+    if (is_error(ret)) {
+        unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr, 0);
+        g_free(lurb);
+    } else {
+        urb_hashtable_insert(lurb);
+    }
+
+    return ret;
+}
+#endif /* CONFIG_USBFS */
+
+static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
+                            int cmd, abi_long arg)
+{
+    void *argptr;
+    struct dm_ioctl *host_dm;
+    abi_long guest_data;
+    uint32_t guest_data_size;
+    int target_size;
+    const argtype *arg_type = ie->arg_type;
+    abi_long ret;
+    void *big_buf = NULL;
+    char *host_data;
+
+    arg_type++;
+    target_size = thunk_type_size(arg_type, 0);
+    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+    if (!argptr) {
+        ret = -TARGET_EFAULT;
+        goto out;
+    }
+    thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+    unlock_user(argptr, arg, 0);
+
+    /* buf_temp is too small, so fetch things into a bigger buffer */
+    big_buf = g_malloc0(((struct dm_ioctl *)buf_temp)->data_size * 2);
+    memcpy(big_buf, buf_temp, target_size);
+    buf_temp = big_buf;
+    host_dm = big_buf;
+
+    guest_data = arg + host_dm->data_start;
+    if ((guest_data - arg) < 0) {
+        ret = -TARGET_EINVAL;
+        goto out;
+    }
+    guest_data_size = host_dm->data_size - host_dm->data_start;
+    host_data = (char *)host_dm + host_dm->data_start;
+
+    argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
+    if (!argptr) {
+        ret = -TARGET_EFAULT;
+        goto out;
+    }
+
+    switch (ie->host_cmd) {
+    case DM_REMOVE_ALL:
+    case DM_LIST_DEVICES:
+    case DM_DEV_CREATE:
+    case DM_DEV_REMOVE:
+    case DM_DEV_SUSPEND:
+    case DM_DEV_STATUS:
+    case DM_DEV_WAIT:
+    case DM_TABLE_STATUS:
+    case DM_TABLE_CLEAR:
+    case DM_TABLE_DEPS:
+    case DM_LIST_VERSIONS:
+        /* no input data */
+        break;
+    case DM_DEV_RENAME:
+    case DM_DEV_SET_GEOMETRY:
+        /* data contains only strings */
+        memcpy(host_data, argptr, guest_data_size);
+        break;
+    case DM_TARGET_MSG:
+        memcpy(host_data, argptr, guest_data_size);
+        *(uint64_t *)host_data = tswap64(*(uint64_t *)argptr);
+        break;
+    case DM_TABLE_LOAD:
+    {
+        void *gspec = argptr;
+        void *cur_data = host_data;
+        const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
+        int spec_size = thunk_type_size(arg_type, 0);
+        int i;
+
+        for (i = 0; i < host_dm->target_count; i++) {
+            struct dm_target_spec *spec = cur_data;
+            uint32_t next;
+            int slen;
+
+            thunk_convert(spec, gspec, arg_type, THUNK_HOST);
+            slen = strlen((char *)gspec + spec_size) + 1;
+            next = spec->next;
+            spec->next = sizeof(*spec) + slen;
+            strcpy((char *)&spec[1], gspec + spec_size);
+            gspec += next;
+            cur_data += spec->next;
+        }
+        break;
+    }
+    default:
+        ret = -TARGET_EINVAL;
+        unlock_user(argptr, guest_data, 0);
+        goto out;
+    }
+    unlock_user(argptr, guest_data, 0);
+
+    ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
+    if (!is_error(ret)) {
+        guest_data = arg + host_dm->data_start;
+        guest_data_size = host_dm->data_size - host_dm->data_start;
+        argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
+        switch (ie->host_cmd) {
+        case DM_REMOVE_ALL:
+        case DM_DEV_CREATE:
+        case DM_DEV_REMOVE:
+        case DM_DEV_RENAME:
+        case DM_DEV_SUSPEND:
+        case DM_DEV_STATUS:
+        case DM_TABLE_LOAD:
+        case DM_TABLE_CLEAR:
+        case DM_TARGET_MSG:
+        case DM_DEV_SET_GEOMETRY:
+            /* no return data */
+            break;
+        case DM_LIST_DEVICES:
+        {
+            struct dm_name_list *nl = (void *)host_dm + host_dm->data_start;
+            uint32_t remaining_data = guest_data_size;
+            void *cur_data = argptr;
+            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
+            int nl_size = 12; /* can't use thunk_size due to alignment */
+
+            while (1) {
+                uint32_t next = nl->next;
+                if (next) {
+                    nl->next = nl_size + (strlen(nl->name) + 1);
+                }
+                if (remaining_data < nl->next) {
+                    host_dm->flags |= DM_BUFFER_FULL_FLAG;
+                    break;
+                }
+                thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
+                strcpy(cur_data + nl_size, nl->name);
+                cur_data += nl->next;
+                remaining_data -= nl->next;
+                if (!next) {
+                    break;
+                }
+                nl = (void *)nl + next;
+            }
+            break;
+        }
+        case DM_DEV_WAIT:
+        case DM_TABLE_STATUS:
+        {
+            struct dm_target_spec *spec
+                = (void *)host_dm + host_dm->data_start;
+            void *cur_data = argptr;
+            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
+            int spec_size = thunk_type_size(arg_type, 0);
+            int i;
+
+            for (i = 0; i < host_dm->target_count; i++) {
+                uint32_t next = spec->next;
+                int slen = strlen((char *)&spec[1]) + 1;
+                spec->next = (cur_data - argptr) + spec_size + slen;
+                if (guest_data_size < spec->next) {
+                    host_dm->flags |= DM_BUFFER_FULL_FLAG;
+                    break;
+                }
+                thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
+                strcpy(cur_data + spec_size, (char *)&spec[1]);
+                cur_data = argptr + spec->next;
+                spec = (void *)host_dm + host_dm->data_start + next;
+            }
+            break;
+        }
+        case DM_TABLE_DEPS:
+        {
+            void *hdata = (void *)host_dm + host_dm->data_start;
+            int count = *(uint32_t *)hdata;
+            uint64_t *hdev = hdata + 8;
+            uint64_t *gdev = argptr + 8;
+            int i;
+
+            *(uint32_t *)argptr = tswap32(count);
+            for (i = 0; i < count; i++) {
+                *gdev = tswap64(*hdev);
+                gdev++;
+                hdev++;
+            }
+            break;
+        }
+        case DM_LIST_VERSIONS:
+        {
+            struct dm_target_versions *vers
+                = (void *)host_dm + host_dm->data_start;
+            uint32_t remaining_data = guest_data_size;
+            void *cur_data = argptr;
+            const argtype arg_type[]
+                = { MK_STRUCT(STRUCT_dm_target_versions) };
+            int vers_size = thunk_type_size(arg_type, 0);
+
+            while (1) {
+                uint32_t next = vers->next;
+                if (next) {
+                    vers->next = vers_size + strlen(vers->name) + 1;
+                }
+                if (remaining_data < vers->next) {
+                    host_dm->flags |= DM_BUFFER_FULL_FLAG;
+                    break;
+                }
+                thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
+                strcpy(cur_data + vers_size, vers->name);
+                cur_data += vers->next;
+                remaining_data -= vers->next;
+                if (!next) {
+                    break;
+                }
+                vers = (void *)vers + next;
+            }
+            break;
+        }
+        default:
+            unlock_user(argptr, guest_data, 0);
+            ret = -TARGET_EINVAL;
+            goto out;
+        }
+        unlock_user(argptr, guest_data, guest_data_size);
+
+        argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
+        if (!argptr) {
+            ret = -TARGET_EFAULT;
+            goto out;
+        }
+        thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
+        unlock_user(argptr, arg, target_size);
+    }
+out:
+    g_free(big_buf);
+    return ret;
+}
+
+static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
+                               int cmd, abi_long arg)
+{
+    void *argptr;
+    int target_size;
+    const argtype *arg_type = ie->arg_type;
+    const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) };
+    abi_long ret;
+    struct blkpg_ioctl_arg *host_blkpg = (void *)buf_temp;
+    struct blkpg_partition host_part;
+
+    /* Read and convert blkpg */
+    arg_type++;
+    target_size = thunk_type_size(arg_type, 0);
+    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+    if (!argptr) {
+        ret = -TARGET_EFAULT;
+        goto out;
+    }
+    thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+    unlock_user(argptr, arg, 0);
+
+    switch (host_blkpg->op) {
+    case BLKPG_ADD_PARTITION:
+    case BLKPG_DEL_PARTITION:
+        /* payload is struct blkpg_partition */
+        break;
+    default:
+        /* Unknown opcode */
+        ret = -TARGET_EINVAL;
+        goto out;
+    }
+
+    /* Read and convert blkpg->data */
+    arg = (abi_long)(uintptr_t)host_blkpg->data;
+    target_size = thunk_type_size(part_arg_type, 0);
+    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+    if (!argptr) {
+        ret = -TARGET_EFAULT;
+        goto out;
+    }
+    thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST);
+    unlock_user(argptr, arg, 0);
+
+    /* Swizzle the data pointer to our local copy and call! */
+    host_blkpg->data = &host_part;
+    ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_blkpg));
+
+out:
+    return ret;
+}
+
+static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
+                            int fd, int cmd, abi_long arg)
+{
+    const argtype *arg_type = ie->arg_type;
+    const StructEntry *se;
+    const argtype *field_types;
+    const int *dst_offsets, *src_offsets;
+    int target_size;
+    void *argptr;
+    abi_ulong *target_rt_dev_ptr = NULL;
+    unsigned long *host_rt_dev_ptr = NULL;
+    abi_long ret;
+    int i;
+
+    assert(ie->access == IOC_W);
+    assert(*arg_type == TYPE_PTR);
+    arg_type++;
+    assert(*arg_type == TYPE_STRUCT);
+    target_size = thunk_type_size(arg_type, 0);
+    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+    if (!argptr) {
+        return -TARGET_EFAULT;
+    }
+    arg_type++;
+    assert(*arg_type == (int)STRUCT_rtentry);
+    se = struct_entries + *arg_type++;
+    assert(se->convert[0] == NULL);
+    /* convert struct here to be able to catch rt_dev string */
+    field_types = se->field_types;
+    dst_offsets = se->field_offsets[THUNK_HOST];
+    src_offsets = se->field_offsets[THUNK_TARGET];
+    for (i = 0; i < se->nb_fields; i++) {
+        if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
+            assert(*field_types == TYPE_PTRVOID);
+            target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]);
+            host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
+            if (*target_rt_dev_ptr != 0) {
+                *host_rt_dev_ptr = (unsigned long)lock_user_string(
+                    tswapal(*target_rt_dev_ptr));
+                if (!*host_rt_dev_ptr) {
+                    unlock_user(argptr, arg, 0);
+                    return -TARGET_EFAULT;
+                }
+            } else {
+                *host_rt_dev_ptr = 0;
+            }
+            field_types++;
+            continue;
+        }
+        field_types = thunk_convert(buf_temp + dst_offsets[i],
+                                    argptr + src_offsets[i],
+                                    field_types, THUNK_HOST);
+    }
+    unlock_user(argptr, arg, 0);
+
+    ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
+    if (*host_rt_dev_ptr != 0) {
+        unlock_user((void *)*host_rt_dev_ptr,
+                    *target_rt_dev_ptr, 0);
+    }
+    return ret;
+}
+
+static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
+                                     int fd, int cmd, abi_long arg)
+{
+    int sig = target_to_host_signal(arg);
+    return get_errno(safe_ioctl(fd, ie->host_cmd, sig));
+}
+
+#ifdef TIOCGPTPEER
+static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
+                                     int fd, int cmd, abi_long arg)
+{
+    int flags = target_to_host_bitmask(arg, fcntl_flags_tbl);
+    return get_errno(safe_ioctl(fd, ie->host_cmd, flags));
+}
+#endif
+
+static IOCTLEntry ioctl_entries[] = {
+#define IOCTL(cmd, access, ...)                                 \
+    { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
+#define IOCTL_SPECIAL(cmd, access, dofn, ...)                           \
+    { TARGET_ ## cmd, cmd, #cmd, access, dofn, {  __VA_ARGS__ } },
+#define IOCTL_IGNORE(cmd)                       \
+    { TARGET_ ## cmd, 0, #cmd },
+#include "ioctls.h"
+    { 0, 0, },
+};
+
+/* ??? Implement proper locking for ioctls.  */
+SYSCALL_IMPL(ioctl)
+{
+    int fd = arg1;
+    int cmd = arg2;
+    abi_ulong arg = arg3;
+    const IOCTLEntry *ie;
+    const argtype *arg_type;
+    abi_long ret;
+    uint8_t buf_temp[MAX_STRUCT_SIZE];
+    int target_size;
+    void *argptr;
+
+    for (ie = ioctl_entries; ; ie++) {
+        if (ie->target_cmd == 0) {
+            gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
+            return -TARGET_ENOSYS;
+        }
+        if (ie->target_cmd == cmd) {
+            break;
+        }
+    }
+
+    arg_type = ie->arg_type;
+    if (ie->do_ioctl) {
+        return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
+    } else if (!ie->host_cmd) {
+        /*
+         * Some architectures define BSD ioctls in their headers
+         * that are not implemented in Linux.
+         */
+        return -TARGET_ENOSYS;
+    }
+
+    switch (arg_type[0]) {
+    case TYPE_NULL:
+        /* no argument */
+        ret = get_errno(safe_ioctl(fd, ie->host_cmd));
+        break;
+    case TYPE_PTRVOID:
+    case TYPE_INT:
+        ret = get_errno(safe_ioctl(fd, ie->host_cmd, arg));
+        break;
+    case TYPE_PTR:
+        arg_type++;
+        target_size = thunk_type_size(arg_type, 0);
+        switch (ie->access) {
+        case IOC_R:
+            ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
+            if (!is_error(ret)) {
+                argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
+                if (!argptr) {
+                    return -TARGET_EFAULT;
+                }
+                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
+                unlock_user(argptr, arg, target_size);
+            }
+            break;
+        case IOC_W:
+            argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+            if (!argptr) {
+                return -TARGET_EFAULT;
+            }
+            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+            unlock_user(argptr, arg, 0);
+            ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
+            break;
+        default:
+        case IOC_RW:
+            argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+            if (!argptr) {
+                return -TARGET_EFAULT;
+            }
+            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+            unlock_user(argptr, arg, 0);
+            ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
+            if (!is_error(ret)) {
+                argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
+                if (!argptr) {
+                    return -TARGET_EFAULT;
+                }
+                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
+                unlock_user(argptr, arg, target_size);
+            }
+            break;
+        }
+        break;
+    default:
+        gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
+                 (long)cmd, arg_type[0]);
+        ret = -TARGET_ENOSYS;
+        break;
+    }
+    return ret;
+}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index d0e76c392e..8f90affe2f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2979,855 +2979,6 @@ STRUCT_MAX
 #undef STRUCT
 #undef STRUCT_SPECIAL
 
-typedef struct IOCTLEntry IOCTLEntry;
-
-typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
-                             int fd, int cmd, abi_long arg);
-
-struct IOCTLEntry {
-    int target_cmd;
-    unsigned int host_cmd;
-    const char *name;
-    int access;
-    do_ioctl_fn *do_ioctl;
-    const argtype arg_type[5];
-};
-
-#define IOC_R 0x0001
-#define IOC_W 0x0002
-#define IOC_RW (IOC_R | IOC_W)
-
-#define MAX_STRUCT_SIZE 4096
-
-#ifdef CONFIG_FIEMAP
-/* So fiemap access checks don't overflow on 32 bit systems.
- * This is very slightly smaller than the limit imposed by
- * the underlying kernel.
- */
-#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap))  \
-                            / sizeof(struct fiemap_extent))
-
-static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
-                                       int fd, int cmd, abi_long arg)
-{
-    /* The parameter for this ioctl is a struct fiemap followed
-     * by an array of struct fiemap_extent whose size is set
-     * in fiemap->fm_extent_count. The array is filled in by the
-     * ioctl.
-     */
-    int target_size_in, target_size_out;
-    struct fiemap *fm;
-    const argtype *arg_type = ie->arg_type;
-    const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
-    void *argptr, *p;
-    abi_long ret;
-    int i, extent_size = thunk_type_size(extent_arg_type, 0);
-    uint32_t outbufsz;
-    int free_fm = 0;
-
-    assert(arg_type[0] == TYPE_PTR);
-    assert(ie->access == IOC_RW);
-    arg_type++;
-    target_size_in = thunk_type_size(arg_type, 0);
-    argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
-    if (!argptr) {
-        return -TARGET_EFAULT;
-    }
-    thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
-    unlock_user(argptr, arg, 0);
-    fm = (struct fiemap *)buf_temp;
-    if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
-        return -TARGET_EINVAL;
-    }
-
-    outbufsz = sizeof (*fm) +
-        (sizeof(struct fiemap_extent) * fm->fm_extent_count);
-
-    if (outbufsz > MAX_STRUCT_SIZE) {
-        /* We can't fit all the extents into the fixed size buffer.
-         * Allocate one that is large enough and use it instead.
-         */
-        fm = g_try_malloc(outbufsz);
-        if (!fm) {
-            return -TARGET_ENOMEM;
-        }
-        memcpy(fm, buf_temp, sizeof(struct fiemap));
-        free_fm = 1;
-    }
-    ret = get_errno(safe_ioctl(fd, ie->host_cmd, fm));
-    if (!is_error(ret)) {
-        target_size_out = target_size_in;
-        /* An extent_count of 0 means we were only counting the extents
-         * so there are no structs to copy
-         */
-        if (fm->fm_extent_count != 0) {
-            target_size_out += fm->fm_mapped_extents * extent_size;
-        }
-        argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
-        if (!argptr) {
-            ret = -TARGET_EFAULT;
-        } else {
-            /* Convert the struct fiemap */
-            thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
-            if (fm->fm_extent_count != 0) {
-                p = argptr + target_size_in;
-                /* ...and then all the struct fiemap_extents */
-                for (i = 0; i < fm->fm_mapped_extents; i++) {
-                    thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
-                                  THUNK_TARGET);
-                    p += extent_size;
-                }
-            }
-            unlock_user(argptr, arg, target_size_out);
-        }
-    }
-    if (free_fm) {
-        g_free(fm);
-    }
-    return ret;
-}
-#endif
-
-static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
-                                int fd, int cmd, abi_long arg)
-{
-    const argtype *arg_type = ie->arg_type;
-    int target_size;
-    void *argptr;
-    int ret;
-    struct ifconf *host_ifconf;
-    uint32_t outbufsz;
-    const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
-    int target_ifreq_size;
-    int nb_ifreq;
-    int free_buf = 0;
-    int i;
-    int target_ifc_len;
-    abi_long target_ifc_buf;
-    int host_ifc_len;
-    char *host_ifc_buf;
-
-    assert(arg_type[0] == TYPE_PTR);
-    assert(ie->access == IOC_RW);
-
-    arg_type++;
-    target_size = thunk_type_size(arg_type, 0);
-
-    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
-    if (!argptr)
-        return -TARGET_EFAULT;
-    thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
-    unlock_user(argptr, arg, 0);
-
-    host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
-    target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
-    target_ifreq_size = thunk_type_size(ifreq_arg_type, 0);
-
-    if (target_ifc_buf != 0) {
-        target_ifc_len = host_ifconf->ifc_len;
-        nb_ifreq = target_ifc_len / target_ifreq_size;
-        host_ifc_len = nb_ifreq * sizeof(struct ifreq);
-
-        outbufsz = sizeof(*host_ifconf) + host_ifc_len;
-        if (outbufsz > MAX_STRUCT_SIZE) {
-            /*
-             * We can't fit all the extents into the fixed size buffer.
-             * Allocate one that is large enough and use it instead.
-             */
-            host_ifconf = malloc(outbufsz);
-            if (!host_ifconf) {
-                return -TARGET_ENOMEM;
-            }
-            memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
-            free_buf = 1;
-        }
-        host_ifc_buf = (char *)host_ifconf + sizeof(*host_ifconf);
-
-        host_ifconf->ifc_len = host_ifc_len;
-    } else {
-      host_ifc_buf = NULL;
-    }
-    host_ifconf->ifc_buf = host_ifc_buf;
-
-    ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_ifconf));
-    if (!is_error(ret)) {
-	/* convert host ifc_len to target ifc_len */
-
-        nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
-        target_ifc_len = nb_ifreq * target_ifreq_size;
-        host_ifconf->ifc_len = target_ifc_len;
-
-	/* restore target ifc_buf */
-
-        host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
-
-	/* copy struct ifconf to target user */
-
-        argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
-        if (!argptr)
-            return -TARGET_EFAULT;
-        thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
-        unlock_user(argptr, arg, target_size);
-
-        if (target_ifc_buf != 0) {
-            /* copy ifreq[] to target user */
-            argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
-            for (i = 0; i < nb_ifreq ; i++) {
-                thunk_convert(argptr + i * target_ifreq_size,
-                              host_ifc_buf + i * sizeof(struct ifreq),
-                              ifreq_arg_type, THUNK_TARGET);
-            }
-            unlock_user(argptr, target_ifc_buf, target_ifc_len);
-        }
-    }
-
-    if (free_buf) {
-        free(host_ifconf);
-    }
-
-    return ret;
-}
-
-#if defined(CONFIG_USBFS)
-#if HOST_LONG_BITS > 64
-#error USBDEVFS thunks do not support >64 bit hosts yet.
-#endif
-struct live_urb {
-    uint64_t target_urb_adr;
-    uint64_t target_buf_adr;
-    char *target_buf_ptr;
-    struct usbdevfs_urb host_urb;
-};
-
-static GHashTable *usbdevfs_urb_hashtable(void)
-{
-    static GHashTable *urb_hashtable;
-
-    if (!urb_hashtable) {
-        urb_hashtable = g_hash_table_new(g_int64_hash, g_int64_equal);
-    }
-    return urb_hashtable;
-}
-
-static void urb_hashtable_insert(struct live_urb *urb)
-{
-    GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
-    g_hash_table_insert(urb_hashtable, urb, urb);
-}
-
-static struct live_urb *urb_hashtable_lookup(uint64_t target_urb_adr)
-{
-    GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
-    return g_hash_table_lookup(urb_hashtable, &target_urb_adr);
-}
-
-static void urb_hashtable_remove(struct live_urb *urb)
-{
-    GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
-    g_hash_table_remove(urb_hashtable, urb);
-}
-
-static abi_long
-do_ioctl_usbdevfs_reapurb(const IOCTLEntry *ie, uint8_t *buf_temp,
-                          int fd, int cmd, abi_long arg)
-{
-    const argtype usbfsurb_arg_type[] = { MK_STRUCT(STRUCT_usbdevfs_urb) };
-    const argtype ptrvoid_arg_type[] = { TYPE_PTRVOID, 0, 0 };
-    struct live_urb *lurb;
-    void *argptr;
-    uint64_t hurb;
-    int target_size;
-    uintptr_t target_urb_adr;
-    abi_long ret;
-
-    target_size = thunk_type_size(usbfsurb_arg_type, THUNK_TARGET);
-
-    memset(buf_temp, 0, sizeof(uint64_t));
-    ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
-    if (is_error(ret)) {
-        return ret;
-    }
-
-    memcpy(&hurb, buf_temp, sizeof(uint64_t));
-    lurb = (void *)((uintptr_t)hurb - offsetof(struct live_urb, host_urb));
-    if (!lurb->target_urb_adr) {
-        return -TARGET_EFAULT;
-    }
-    urb_hashtable_remove(lurb);
-    unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr,
-        lurb->host_urb.buffer_length);
-    lurb->target_buf_ptr = NULL;
-
-    /* restore the guest buffer pointer */
-    lurb->host_urb.buffer = (void *)(uintptr_t)lurb->target_buf_adr;
-
-    /* update the guest urb struct */
-    argptr = lock_user(VERIFY_WRITE, lurb->target_urb_adr, target_size, 0);
-    if (!argptr) {
-        g_free(lurb);
-        return -TARGET_EFAULT;
-    }
-    thunk_convert(argptr, &lurb->host_urb, usbfsurb_arg_type, THUNK_TARGET);
-    unlock_user(argptr, lurb->target_urb_adr, target_size);
-
-    target_size = thunk_type_size(ptrvoid_arg_type, THUNK_TARGET);
-    /* write back the urb handle */
-    argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
-    if (!argptr) {
-        g_free(lurb);
-        return -TARGET_EFAULT;
-    }
-
-    /* GHashTable uses 64-bit keys but thunk_convert expects uintptr_t */
-    target_urb_adr = lurb->target_urb_adr;
-    thunk_convert(argptr, &target_urb_adr, ptrvoid_arg_type, THUNK_TARGET);
-    unlock_user(argptr, arg, target_size);
-
-    g_free(lurb);
-    return ret;
-}
-
-static abi_long
-do_ioctl_usbdevfs_discardurb(const IOCTLEntry *ie,
-                             uint8_t *buf_temp __attribute__((unused)),
-                             int fd, int cmd, abi_long arg)
-{
-    struct live_urb *lurb;
-
-    /* map target address back to host URB with metadata. */
-    lurb = urb_hashtable_lookup(arg);
-    if (!lurb) {
-        return -TARGET_EFAULT;
-    }
-    return get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
-}
-
-static abi_long
-do_ioctl_usbdevfs_submiturb(const IOCTLEntry *ie, uint8_t *buf_temp,
-                            int fd, int cmd, abi_long arg)
-{
-    const argtype *arg_type = ie->arg_type;
-    int target_size;
-    abi_long ret;
-    void *argptr;
-    int rw_dir;
-    struct live_urb *lurb;
-
-    /*
-     * each submitted URB needs to map to a unique ID for the
-     * kernel, and that unique ID needs to be a pointer to
-     * host memory.  hence, we need to malloc for each URB.
-     * isochronous transfers have a variable length struct.
-     */
-    arg_type++;
-    target_size = thunk_type_size(arg_type, THUNK_TARGET);
-
-    /* construct host copy of urb and metadata */
-    lurb = g_try_malloc0(sizeof(struct live_urb));
-    if (!lurb) {
-        return -TARGET_ENOMEM;
-    }
-
-    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
-    if (!argptr) {
-        g_free(lurb);
-        return -TARGET_EFAULT;
-    }
-    thunk_convert(&lurb->host_urb, argptr, arg_type, THUNK_HOST);
-    unlock_user(argptr, arg, 0);
-
-    lurb->target_urb_adr = arg;
-    lurb->target_buf_adr = (uintptr_t)lurb->host_urb.buffer;
-
-    /* buffer space used depends on endpoint type so lock the entire buffer */
-    /* control type urbs should check the buffer contents for true direction */
-    rw_dir = lurb->host_urb.endpoint & USB_DIR_IN ? VERIFY_WRITE : VERIFY_READ;
-    lurb->target_buf_ptr = lock_user(rw_dir, lurb->target_buf_adr,
-        lurb->host_urb.buffer_length, 1);
-    if (lurb->target_buf_ptr == NULL) {
-        g_free(lurb);
-        return -TARGET_EFAULT;
-    }
-
-    /* update buffer pointer in host copy */
-    lurb->host_urb.buffer = lurb->target_buf_ptr;
-
-    ret = get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
-    if (is_error(ret)) {
-        unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr, 0);
-        g_free(lurb);
-    } else {
-        urb_hashtable_insert(lurb);
-    }
-
-    return ret;
-}
-#endif /* CONFIG_USBFS */
-
-static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
-                            int cmd, abi_long arg)
-{
-    void *argptr;
-    struct dm_ioctl *host_dm;
-    abi_long guest_data;
-    uint32_t guest_data_size;
-    int target_size;
-    const argtype *arg_type = ie->arg_type;
-    abi_long ret;
-    void *big_buf = NULL;
-    char *host_data;
-
-    arg_type++;
-    target_size = thunk_type_size(arg_type, 0);
-    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
-    if (!argptr) {
-        ret = -TARGET_EFAULT;
-        goto out;
-    }
-    thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
-    unlock_user(argptr, arg, 0);
-
-    /* buf_temp is too small, so fetch things into a bigger buffer */
-    big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
-    memcpy(big_buf, buf_temp, target_size);
-    buf_temp = big_buf;
-    host_dm = big_buf;
-
-    guest_data = arg + host_dm->data_start;
-    if ((guest_data - arg) < 0) {
-        ret = -TARGET_EINVAL;
-        goto out;
-    }
-    guest_data_size = host_dm->data_size - host_dm->data_start;
-    host_data = (char*)host_dm + host_dm->data_start;
-
-    argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
-    if (!argptr) {
-        ret = -TARGET_EFAULT;
-        goto out;
-    }
-
-    switch (ie->host_cmd) {
-    case DM_REMOVE_ALL:
-    case DM_LIST_DEVICES:
-    case DM_DEV_CREATE:
-    case DM_DEV_REMOVE:
-    case DM_DEV_SUSPEND:
-    case DM_DEV_STATUS:
-    case DM_DEV_WAIT:
-    case DM_TABLE_STATUS:
-    case DM_TABLE_CLEAR:
-    case DM_TABLE_DEPS:
-    case DM_LIST_VERSIONS:
-        /* no input data */
-        break;
-    case DM_DEV_RENAME:
-    case DM_DEV_SET_GEOMETRY:
-        /* data contains only strings */
-        memcpy(host_data, argptr, guest_data_size);
-        break;
-    case DM_TARGET_MSG:
-        memcpy(host_data, argptr, guest_data_size);
-        *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
-        break;
-    case DM_TABLE_LOAD:
-    {
-        void *gspec = argptr;
-        void *cur_data = host_data;
-        const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
-        int spec_size = thunk_type_size(arg_type, 0);
-        int i;
-
-        for (i = 0; i < host_dm->target_count; i++) {
-            struct dm_target_spec *spec = cur_data;
-            uint32_t next;
-            int slen;
-
-            thunk_convert(spec, gspec, arg_type, THUNK_HOST);
-            slen = strlen((char*)gspec + spec_size) + 1;
-            next = spec->next;
-            spec->next = sizeof(*spec) + slen;
-            strcpy((char*)&spec[1], gspec + spec_size);
-            gspec += next;
-            cur_data += spec->next;
-        }
-        break;
-    }
-    default:
-        ret = -TARGET_EINVAL;
-        unlock_user(argptr, guest_data, 0);
-        goto out;
-    }
-    unlock_user(argptr, guest_data, 0);
-
-    ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
-    if (!is_error(ret)) {
-        guest_data = arg + host_dm->data_start;
-        guest_data_size = host_dm->data_size - host_dm->data_start;
-        argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
-        switch (ie->host_cmd) {
-        case DM_REMOVE_ALL:
-        case DM_DEV_CREATE:
-        case DM_DEV_REMOVE:
-        case DM_DEV_RENAME:
-        case DM_DEV_SUSPEND:
-        case DM_DEV_STATUS:
-        case DM_TABLE_LOAD:
-        case DM_TABLE_CLEAR:
-        case DM_TARGET_MSG:
-        case DM_DEV_SET_GEOMETRY:
-            /* no return data */
-            break;
-        case DM_LIST_DEVICES:
-        {
-            struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
-            uint32_t remaining_data = guest_data_size;
-            void *cur_data = argptr;
-            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
-            int nl_size = 12; /* can't use thunk_size due to alignment */
-
-            while (1) {
-                uint32_t next = nl->next;
-                if (next) {
-                    nl->next = nl_size + (strlen(nl->name) + 1);
-                }
-                if (remaining_data < nl->next) {
-                    host_dm->flags |= DM_BUFFER_FULL_FLAG;
-                    break;
-                }
-                thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
-                strcpy(cur_data + nl_size, nl->name);
-                cur_data += nl->next;
-                remaining_data -= nl->next;
-                if (!next) {
-                    break;
-                }
-                nl = (void*)nl + next;
-            }
-            break;
-        }
-        case DM_DEV_WAIT:
-        case DM_TABLE_STATUS:
-        {
-            struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
-            void *cur_data = argptr;
-            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
-            int spec_size = thunk_type_size(arg_type, 0);
-            int i;
-
-            for (i = 0; i < host_dm->target_count; i++) {
-                uint32_t next = spec->next;
-                int slen = strlen((char*)&spec[1]) + 1;
-                spec->next = (cur_data - argptr) + spec_size + slen;
-                if (guest_data_size < spec->next) {
-                    host_dm->flags |= DM_BUFFER_FULL_FLAG;
-                    break;
-                }
-                thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
-                strcpy(cur_data + spec_size, (char*)&spec[1]);
-                cur_data = argptr + spec->next;
-                spec = (void*)host_dm + host_dm->data_start + next;
-            }
-            break;
-        }
-        case DM_TABLE_DEPS:
-        {
-            void *hdata = (void*)host_dm + host_dm->data_start;
-            int count = *(uint32_t*)hdata;
-            uint64_t *hdev = hdata + 8;
-            uint64_t *gdev = argptr + 8;
-            int i;
-
-            *(uint32_t*)argptr = tswap32(count);
-            for (i = 0; i < count; i++) {
-                *gdev = tswap64(*hdev);
-                gdev++;
-                hdev++;
-            }
-            break;
-        }
-        case DM_LIST_VERSIONS:
-        {
-            struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
-            uint32_t remaining_data = guest_data_size;
-            void *cur_data = argptr;
-            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
-            int vers_size = thunk_type_size(arg_type, 0);
-
-            while (1) {
-                uint32_t next = vers->next;
-                if (next) {
-                    vers->next = vers_size + (strlen(vers->name) + 1);
-                }
-                if (remaining_data < vers->next) {
-                    host_dm->flags |= DM_BUFFER_FULL_FLAG;
-                    break;
-                }
-                thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
-                strcpy(cur_data + vers_size, vers->name);
-                cur_data += vers->next;
-                remaining_data -= vers->next;
-                if (!next) {
-                    break;
-                }
-                vers = (void*)vers + next;
-            }
-            break;
-        }
-        default:
-            unlock_user(argptr, guest_data, 0);
-            ret = -TARGET_EINVAL;
-            goto out;
-        }
-        unlock_user(argptr, guest_data, guest_data_size);
-
-        argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
-        if (!argptr) {
-            ret = -TARGET_EFAULT;
-            goto out;
-        }
-        thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
-        unlock_user(argptr, arg, target_size);
-    }
-out:
-    g_free(big_buf);
-    return ret;
-}
-
-static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
-                               int cmd, abi_long arg)
-{
-    void *argptr;
-    int target_size;
-    const argtype *arg_type = ie->arg_type;
-    const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) };
-    abi_long ret;
-
-    struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp;
-    struct blkpg_partition host_part;
-
-    /* Read and convert blkpg */
-    arg_type++;
-    target_size = thunk_type_size(arg_type, 0);
-    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
-    if (!argptr) {
-        ret = -TARGET_EFAULT;
-        goto out;
-    }
-    thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
-    unlock_user(argptr, arg, 0);
-
-    switch (host_blkpg->op) {
-    case BLKPG_ADD_PARTITION:
-    case BLKPG_DEL_PARTITION:
-        /* payload is struct blkpg_partition */
-        break;
-    default:
-        /* Unknown opcode */
-        ret = -TARGET_EINVAL;
-        goto out;
-    }
-
-    /* Read and convert blkpg->data */
-    arg = (abi_long)(uintptr_t)host_blkpg->data;
-    target_size = thunk_type_size(part_arg_type, 0);
-    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
-    if (!argptr) {
-        ret = -TARGET_EFAULT;
-        goto out;
-    }
-    thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST);
-    unlock_user(argptr, arg, 0);
-
-    /* Swizzle the data pointer to our local copy and call! */
-    host_blkpg->data = &host_part;
-    ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_blkpg));
-
-out:
-    return ret;
-}
-
-static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
-                                int fd, int cmd, abi_long arg)
-{
-    const argtype *arg_type = ie->arg_type;
-    const StructEntry *se;
-    const argtype *field_types;
-    const int *dst_offsets, *src_offsets;
-    int target_size;
-    void *argptr;
-    abi_ulong *target_rt_dev_ptr = NULL;
-    unsigned long *host_rt_dev_ptr = NULL;
-    abi_long ret;
-    int i;
-
-    assert(ie->access == IOC_W);
-    assert(*arg_type == TYPE_PTR);
-    arg_type++;
-    assert(*arg_type == TYPE_STRUCT);
-    target_size = thunk_type_size(arg_type, 0);
-    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
-    if (!argptr) {
-        return -TARGET_EFAULT;
-    }
-    arg_type++;
-    assert(*arg_type == (int)STRUCT_rtentry);
-    se = struct_entries + *arg_type++;
-    assert(se->convert[0] == NULL);
-    /* convert struct here to be able to catch rt_dev string */
-    field_types = se->field_types;
-    dst_offsets = se->field_offsets[THUNK_HOST];
-    src_offsets = se->field_offsets[THUNK_TARGET];
-    for (i = 0; i < se->nb_fields; i++) {
-        if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
-            assert(*field_types == TYPE_PTRVOID);
-            target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]);
-            host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
-            if (*target_rt_dev_ptr != 0) {
-                *host_rt_dev_ptr = (unsigned long)lock_user_string(
-                                                  tswapal(*target_rt_dev_ptr));
-                if (!*host_rt_dev_ptr) {
-                    unlock_user(argptr, arg, 0);
-                    return -TARGET_EFAULT;
-                }
-            } else {
-                *host_rt_dev_ptr = 0;
-            }
-            field_types++;
-            continue;
-        }
-        field_types = thunk_convert(buf_temp + dst_offsets[i],
-                                    argptr + src_offsets[i],
-                                    field_types, THUNK_HOST);
-    }
-    unlock_user(argptr, arg, 0);
-
-    ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
-
-    assert(host_rt_dev_ptr != NULL);
-    assert(target_rt_dev_ptr != NULL);
-    if (*host_rt_dev_ptr != 0) {
-        unlock_user((void *)*host_rt_dev_ptr,
-                    *target_rt_dev_ptr, 0);
-    }
-    return ret;
-}
-
-static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
-                                     int fd, int cmd, abi_long arg)
-{
-    int sig = target_to_host_signal(arg);
-    return get_errno(safe_ioctl(fd, ie->host_cmd, sig));
-}
-
-#ifdef TIOCGPTPEER
-static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
-                                     int fd, int cmd, abi_long arg)
-{
-    int flags = target_to_host_bitmask(arg, fcntl_flags_tbl);
-    return get_errno(safe_ioctl(fd, ie->host_cmd, flags));
-}
-#endif
-
-static IOCTLEntry ioctl_entries[] = {
-#define IOCTL(cmd, access, ...) \
-    { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
-#define IOCTL_SPECIAL(cmd, access, dofn, ...)                      \
-    { TARGET_ ## cmd, cmd, #cmd, access, dofn, {  __VA_ARGS__ } },
-#define IOCTL_IGNORE(cmd) \
-    { TARGET_ ## cmd, 0, #cmd },
-#include "ioctls.h"
-    { 0, 0, },
-};
-
-/* ??? Implement proper locking for ioctls.  */
-/* do_ioctl() Must return target values and target errnos. */
-static abi_long do_ioctl(int fd, int cmd, abi_long arg)
-{
-    const IOCTLEntry *ie;
-    const argtype *arg_type;
-    abi_long ret;
-    uint8_t buf_temp[MAX_STRUCT_SIZE];
-    int target_size;
-    void *argptr;
-
-    ie = ioctl_entries;
-    for(;;) {
-        if (ie->target_cmd == 0) {
-            gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
-            return -TARGET_ENOSYS;
-        }
-        if (ie->target_cmd == cmd)
-            break;
-        ie++;
-    }
-    arg_type = ie->arg_type;
-    if (ie->do_ioctl) {
-        return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
-    } else if (!ie->host_cmd) {
-        /* Some architectures define BSD ioctls in their headers
-           that are not implemented in Linux.  */
-        return -TARGET_ENOSYS;
-    }
-
-    switch(arg_type[0]) {
-    case TYPE_NULL:
-        /* no argument */
-        ret = get_errno(safe_ioctl(fd, ie->host_cmd));
-        break;
-    case TYPE_PTRVOID:
-    case TYPE_INT:
-        ret = get_errno(safe_ioctl(fd, ie->host_cmd, arg));
-        break;
-    case TYPE_PTR:
-        arg_type++;
-        target_size = thunk_type_size(arg_type, 0);
-        switch(ie->access) {
-        case IOC_R:
-            ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
-            if (!is_error(ret)) {
-                argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
-                if (!argptr)
-                    return -TARGET_EFAULT;
-                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
-                unlock_user(argptr, arg, target_size);
-            }
-            break;
-        case IOC_W:
-            argptr = lock_user(VERIFY_READ, arg, target_size, 1);
-            if (!argptr)
-                return -TARGET_EFAULT;
-            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
-            unlock_user(argptr, arg, 0);
-            ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
-            break;
-        default:
-        case IOC_RW:
-            argptr = lock_user(VERIFY_READ, arg, target_size, 1);
-            if (!argptr)
-                return -TARGET_EFAULT;
-            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
-            unlock_user(argptr, arg, 0);
-            ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
-            if (!is_error(ret)) {
-                argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
-                if (!argptr)
-                    return -TARGET_EFAULT;
-                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
-                unlock_user(argptr, arg, target_size);
-            }
-            break;
-        }
-        break;
-    default:
-        gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
-                 (long)cmd, arg_type[0]);
-        ret = -TARGET_ENOSYS;
-        break;
-    }
-    return ret;
-}
-
 static const bitmask_transtbl iflag_tbl[] = {
         { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
         { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
@@ -5294,8 +4445,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_ioctl:
-        return do_ioctl(arg1, arg2, arg3);
 #ifdef TARGET_NR_fcntl
     case TARGET_NR_fcntl:
         return do_fcntl(arg1, arg2, arg3);
@@ -8900,6 +8049,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
                                 int64_t arg5, int64_t arg6)
 
 #include "syscall-file.inc.c"
+#include "syscall-ioctl.inc.c"
 #include "syscall-ipc.inc.c"
 #include "syscall-mem.inc.c"
 #include "syscall-proc.inc.c"
diff --git a/linux-user/strace.list b/linux-user/strace.list
index ce5e02975b..efc64cd29f 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -365,9 +365,6 @@
 #ifdef TARGET_NR_io_cancel
 { TARGET_NR_io_cancel, "io_cancel" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_ioctl
-{ TARGET_NR_ioctl, "ioctl" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_io_destroy
 { TARGET_NR_io_destroy, "io_destroy" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 48/74] linux-user: Fix types in ioctl logging
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (46 preceding siblings ...)
  2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 47/74] linux-user: Split out ioctl Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 49/74] linux-user: Remove sentinel from ioctl_entries Richard Henderson
                   ` (28 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

There is no need to cast "int" to "long"; just use the
correct format in the first place.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-ioctl.inc.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/linux-user/syscall-ioctl.inc.c b/linux-user/syscall-ioctl.inc.c
index be3f0b4b92..15d87b9663 100644
--- a/linux-user/syscall-ioctl.inc.c
+++ b/linux-user/syscall-ioctl.inc.c
@@ -791,7 +791,7 @@ SYSCALL_IMPL(ioctl)
 
     for (ie = ioctl_entries; ; ie++) {
         if (ie->target_cmd == 0) {
-            gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
+            gemu_log("Unsupported ioctl: cmd=0x%04x\n", cmd);
             return -TARGET_ENOSYS;
         }
         if (ie->target_cmd == cmd) {
@@ -864,8 +864,8 @@ SYSCALL_IMPL(ioctl)
         }
         break;
     default:
-        gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
-                 (long)cmd, arg_type[0]);
+        gemu_log("Unsupported ioctl type: cmd=0x%04x type=%d\n",
+                 cmd, arg_type[0]);
         ret = -TARGET_ENOSYS;
         break;
     }
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 49/74] linux-user: Remove sentinel from ioctl_entries
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (47 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 48/74] linux-user: Fix types in ioctl logging Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 50/74] linux-user: Split out fcntl, fcntl64 Richard Henderson
                   ` (27 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Iterate based on the size of the array instead.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-ioctl.inc.c | 14 +++++++-------
 linux-user/syscall.c           |  6 ++----
 2 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/linux-user/syscall-ioctl.inc.c b/linux-user/syscall-ioctl.inc.c
index 15d87b9663..fc7df62017 100644
--- a/linux-user/syscall-ioctl.inc.c
+++ b/linux-user/syscall-ioctl.inc.c
@@ -773,7 +773,6 @@ static IOCTLEntry ioctl_entries[] = {
 #define IOCTL_IGNORE(cmd)                       \
     { TARGET_ ## cmd, 0, #cmd },
 #include "ioctls.h"
-    { 0, 0, },
 };
 
 /* ??? Implement proper locking for ioctls.  */
@@ -789,16 +788,17 @@ SYSCALL_IMPL(ioctl)
     int target_size;
     void *argptr;
 
-    for (ie = ioctl_entries; ; ie++) {
-        if (ie->target_cmd == 0) {
-            gemu_log("Unsupported ioctl: cmd=0x%04x\n", cmd);
-            return -TARGET_ENOSYS;
-        }
+    for (ie = ioctl_entries;
+         ie < ioctl_entries + ARRAY_SIZE(ioctl_entries);
+         ie++) {
         if (ie->target_cmd == cmd) {
-            break;
+            goto found;
         }
     }
+    gemu_log("Unsupported ioctl: cmd=0x%04x\n", cmd);
+    return -TARGET_ENOSYS;
 
+ found:
     arg_type = ie->arg_type;
     if (ie->do_ioctl) {
         return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 8f90affe2f..5871d3e711 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8173,7 +8173,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 
 void syscall_init(void)
 {
-    IOCTLEntry *ie;
     const argtype *arg_type;
     int size;
     int i;
@@ -8203,8 +8202,8 @@ void syscall_init(void)
      * We patch the ioctl size if necessary.  We rely on the fact that
      * no ioctl has all the bits at '1' in the size field.
      */
-    ie = ioctl_entries;
-    while (ie->target_cmd != 0) {
+    for (i = 0; i < ARRAY_SIZE(ioctl_entries); i++) {
+        IOCTLEntry *ie = &ioctl_entries[i];
         if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
             TARGET_IOC_SIZEMASK) {
             arg_type = ie->arg_type;
@@ -8228,6 +8227,5 @@ void syscall_init(void)
                     ie->name, ie->target_cmd, ie->host_cmd);
         }
 #endif
-        ie++;
     }
 }
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 50/74] linux-user: Split out fcntl, fcntl64
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (48 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 49/74] linux-user: Remove sentinel from ioctl_entries Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 51/74] linux-user: Split out setpgid Richard Henderson
                   ` (26 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Preserving strace functionality is tricky with this one.
Rearrange to lookup structures that contain the data for
both execution and strace for each command.

Do not allow lookup of 64-bit fcntl commands from 32-bit fcntl.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h      |   6 +
 linux-user/strace.c            | 100 ----------
 linux-user/syscall-fcntl.inc.c | 322 +++++++++++++++++++++++++++++++++
 linux-user/syscall.c           | 256 +-------------------------
 linux-user/strace.list         |   6 -
 5 files changed, 329 insertions(+), 361 deletions(-)
 create mode 100644 linux-user/syscall-fcntl.inc.c

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index f58b9745a4..5cf39f2bb9 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -46,6 +46,12 @@ SYSCALL_DEF(execveat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_PTR, ARG_ATFLAG);
 SYSCALL_DEF(faccessat, ARG_ATDIRFD, ARG_STR, ARG_ACCESSFLAG);
 SYSCALL_DEF(fchmod, ARG_DEC, ARG_MODEFLAG);
 SYSCALL_DEF(fchmodat, ARG_ATDIRFD, ARG_STR, ARG_MODEFLAG);
+#ifdef TARGET_NR_fcntl
+SYSCALL_DEF_FULL(fcntl, .impl = impl_fcntl, .print = print_fcntl);
+#endif
+#if TARGET_ABI_BITS == 32
+SYSCALL_DEF_FULL(fcntl64, .impl = impl_fcntl64, .print = print_fcntl64);
+#endif
 #ifdef TARGET_NR_futimesat
 SYSCALL_DEF(futimesat, ARG_ATDIRFD, ARG_STR, ARG_PTR);
 #endif
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 2b31998dbd..560284b3c3 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1184,106 +1184,6 @@ print_fchownat(const struct syscallname *name,
 }
 #endif
 
-#if defined(TARGET_NR_fcntl) || defined(TARGET_NR_fcntl64)
-static void
-print_fcntl(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_raw_param("%d", arg0, 0);
-    switch(arg1) {
-    case TARGET_F_DUPFD:
-        gemu_log("F_DUPFD,");
-        print_raw_param(TARGET_ABI_FMT_ld, arg2, 1);
-        break;
-    case TARGET_F_GETFD:
-        gemu_log("F_GETFD");
-        break;
-    case TARGET_F_SETFD:
-        gemu_log("F_SETFD,");
-        print_raw_param(TARGET_ABI_FMT_ld, arg2, 1);
-        break;
-    case TARGET_F_GETFL:
-        gemu_log("F_GETFL");
-        break;
-    case TARGET_F_SETFL:
-        gemu_log("F_SETFL,");
-        print_open_flags(arg2, 1);
-        break;
-    case TARGET_F_GETLK:
-        gemu_log("F_GETLK,");
-        print_pointer(arg2, 1);
-        break;
-    case TARGET_F_SETLK:
-        gemu_log("F_SETLK,");
-        print_pointer(arg2, 1);
-        break;
-    case TARGET_F_SETLKW:
-        gemu_log("F_SETLKW,");
-        print_pointer(arg2, 1);
-        break;
-    case TARGET_F_GETOWN:
-        gemu_log("F_GETOWN");
-        break;
-    case TARGET_F_SETOWN:
-        gemu_log("F_SETOWN,");
-        print_raw_param(TARGET_ABI_FMT_ld, arg2, 0);
-        break;
-    case TARGET_F_GETSIG:
-        gemu_log("F_GETSIG");
-        break;
-    case TARGET_F_SETSIG:
-        gemu_log("F_SETSIG,");
-        print_raw_param(TARGET_ABI_FMT_ld, arg2, 0);
-        break;
-#if TARGET_ABI_BITS == 32
-    case TARGET_F_GETLK64:
-        gemu_log("F_GETLK64,");
-        print_pointer(arg2, 1);
-        break;
-    case TARGET_F_SETLK64:
-        gemu_log("F_SETLK64,");
-        print_pointer(arg2, 1);
-        break;
-    case TARGET_F_SETLKW64:
-        gemu_log("F_SETLKW64,");
-        print_pointer(arg2, 1);
-        break;
-#endif
-    case TARGET_F_SETLEASE:
-        gemu_log("F_SETLEASE,");
-        print_raw_param(TARGET_ABI_FMT_ld, arg2, 0);
-        break;
-    case TARGET_F_GETLEASE:
-        gemu_log("F_GETLEASE");
-        break;
-    case TARGET_F_SETPIPE_SZ:
-        gemu_log("F_SETPIPE_SZ,");
-        print_raw_param(TARGET_ABI_FMT_ld, arg2, 1);
-        break;
-    case TARGET_F_GETPIPE_SZ:
-        gemu_log("F_GETPIPE_SZ");
-        break;
-    case TARGET_F_DUPFD_CLOEXEC:
-        gemu_log("F_DUPFD_CLOEXEC,");
-        print_raw_param(TARGET_ABI_FMT_ld, arg2, 1);
-        break;
-    case TARGET_F_NOTIFY:
-        gemu_log("F_NOTIFY,");
-        print_raw_param(TARGET_ABI_FMT_ld, arg2, 0);
-        break;
-    default:
-        print_raw_param(TARGET_ABI_FMT_ld, arg1, 0);
-        print_pointer(arg2, 1);
-        break;
-    }
-    print_syscall_epilogue(name);
-}
-#define print_fcntl64   print_fcntl
-#endif
-
-
 #if defined(TARGET_NR_socket)
 static void
 print_socket(const struct syscallname *name,
diff --git a/linux-user/syscall-fcntl.inc.c b/linux-user/syscall-fcntl.inc.c
new file mode 100644
index 0000000000..768682bd17
--- /dev/null
+++ b/linux-user/syscall-fcntl.inc.c
@@ -0,0 +1,322 @@
+/*
+ *  Linux fcntl syscall implementation
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+typedef struct FcntlEntry FcntlEntry;
+
+typedef abi_long FcntlFn(int fd, int host_cmd, abi_long arg);
+
+struct FcntlEntry {
+    const char *name;
+    FcntlFn *host_fn;
+    int host_cmd;
+    SyscallArgType arg_type;
+};
+
+static abi_long do_fcntl_int(int fd, int host_cmd, abi_long arg)
+{
+    return get_errno(safe_fcntl(fd, host_cmd, arg));
+}
+
+static abi_long do_fcntl_getfl(int fd, int host_cmd, abi_long arg)
+{
+    abi_long ret = get_errno(safe_fcntl(fd, host_cmd));
+    if (!is_error(ret)) {
+        ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
+    }
+    return ret;
+}
+
+static abi_long do_fcntl_setfl(int fd, int host_cmd, abi_long arg)
+{
+    return get_errno(safe_fcntl(fd, host_cmd,
+                                target_to_host_bitmask(arg, fcntl_flags_tbl)));
+}
+
+static abi_long do_fcntl_getlk_1(int fd, int host_cmd, abi_long arg,
+                                 from_flock64_fn *copy_from,
+                                 to_flock64_fn *copy_to)
+{
+    struct flock64 fl64;
+    abi_long ret;
+
+    ret = copy_from(&fl64, arg);
+    if (ret == 0) {
+        ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
+        if (ret == 0) {
+            ret = copy_to(arg, &fl64);
+        }
+    }
+    return ret;
+}
+
+static abi_long do_fcntl_setlk_1(int fd, int host_cmd, abi_long arg,
+                                 from_flock64_fn *copy_from)
+{
+    struct flock64 fl64;
+    abi_long ret;
+
+    ret = copy_from(&fl64, arg);
+    if (ret == 0) {
+        ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
+    }
+    return ret;
+}
+
+static abi_long do_fcntl_getlk(int fd, int cmd, abi_long arg)
+{
+    return do_fcntl_getlk_1(fd, cmd, arg,
+                            copy_from_user_flock,
+                            copy_to_user_flock);
+}
+
+static abi_long do_fcntl_setlk(int fd, int cmd, abi_long arg)
+{
+    return do_fcntl_setlk_1(fd, cmd, arg, copy_from_user_flock);
+}
+
+static abi_long do_fcntl_getlk64(int fd, int cmd, abi_long arg)
+{
+    return do_fcntl_getlk_1(fd, cmd, arg,
+                            copy_from_user_flock64,
+                            copy_to_user_flock64);
+}
+
+static abi_long do_fcntl_setlk64(int fd, int cmd, abi_long arg)
+{
+    return do_fcntl_setlk_1(fd, cmd, arg, copy_from_user_flock64);
+}
+
+#if defined(TARGET_ARM) && TARGET_ABI_BITS == 32
+static abi_long do_fcntl_oabi_getlk64(int fd, int cmd, abi_long arg)
+{
+    return do_fcntl_getlk_1(fd, cmd, arg,
+                            copy_from_user_oabi_flock64,
+                            copy_to_user_oabi_flock64);
+}
+
+static abi_long do_fcntl_oabi_setlk64(int fd, int cmd, abi_long arg)
+{
+    return do_fcntl_setlk_1(fd, cmd, arg, copy_from_user_oabi_flock64);
+}
+#endif /* TARGET_ARM */
+
+#ifdef F_GETOWN_EX
+static abi_long do_fcntl_getown_ex(int fd, int cmd, abi_long arg)
+{
+    struct f_owner_ex fox;
+    abi_long ret = get_errno(safe_fcntl(fd, cmd, &fox));
+
+    if (!is_error(ret)) {
+        struct target_f_owner_ex *target_fox;
+        if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0)) {
+            return -TARGET_EFAULT;
+        }
+        target_fox->type = tswap32(fox.type);
+        target_fox->pid = tswap32(fox.pid);
+        unlock_user_struct(target_fox, arg, 1);
+    }
+    return ret;
+}
+
+static abi_long do_fcntl_setown_ex(int fd, int cmd, abi_long arg)
+{
+    struct target_f_owner_ex *target_fox;
+    struct f_owner_ex fox;
+
+    if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1)) {
+        return -TARGET_EFAULT;
+    }
+    fox.type = tswap32(target_fox->type);
+    fox.pid = tswap32(target_fox->pid);
+    unlock_user_struct(target_fox, arg, 0);
+    return get_errno(safe_fcntl(fd, cmd, &fox));
+}
+#endif /* F_GETOWN_EX */
+
+static const FcntlEntry *target_fcntl_cmd(int cmd, int is_64)
+{
+#define CMD2(T, H, A, FN)                                            \
+    case TARGET_##T: do {                                            \
+        static const FcntlEntry ent_##T = {                          \
+            .name = #T, .host_cmd = H, .host_fn = FN, .arg_type = A  \
+        };                                                           \
+        return &ent_##T;                                             \
+    } while(0)
+
+#define CMD1(T, A, FN)                                               \
+    case TARGET_##T: do {                                            \
+        static const FcntlEntry ent_##T = {                          \
+            .name = #T, .host_cmd = T, .host_fn = FN, .arg_type = A  \
+        };                                                           \
+        return &ent_##T;                                             \
+    } while(0)
+
+#if TARGET_ABI_BITS == 64
+# ifdef __powerpc64__
+/*
+ * On PPC64, glibc headers has the F_*LK* defined to 12, 13 and 14 and
+ * is not supported by kernel. The glibc fcntl call actually adjusts
+ * them to 5, 6 and 7 before making the syscall(). Since we make the
+ * syscall directly, adjust to what is supported by the kernel.
+ */
+#  define HOST_CMD_ADJ64(C)  (C - (F_GETLK64 - 5))
+# else
+#  define HOST_CMD_ADJ64(C)  C
+# endif
+# define CMD64(T, FN)                                                \
+    case TARGET_##T: do {                                            \
+        static const FcntlEntry ent_##T = {                          \
+            .name = #T, .host_cmd = HOST_CMD_ADJ64(T),               \
+            .host_fn = do_fcntl_##FN, .arg_type = ARG_PTR            \
+        };                                                           \
+        return &ent_##T;                                             \
+    } while(0)
+#elif defined(TARGET_ARM)
+# define CMD64(T, FN)                                                \
+    case TARGET_##T: do {                                            \
+        if (!is_64) {                                                \
+            return NULL;                                             \
+        } else if (is_64 > 0) {                                      \
+            static const FcntlEntry ent_##T = {                      \
+                .name = #T, .host_cmd = T,                           \
+                .host_fn = do_fcntl_##FN, .arg_type = ARG_PTR        \
+            };                                                       \
+            return &ent_##T;                                         \
+        } else {                                                     \
+            static const FcntlEntry ent_oabi_##T = {                 \
+                .name = #T, .host_cmd = T,                           \
+                .host_fn = do_fcntl_oabi_##FN, .arg_type = ARG_PTR   \
+            };                                                       \
+            return &ent_oabi_##T;                                    \
+        }                                                            \
+    } while (0)
+#else
+# define CMD64(T, FN)                                                \
+    case TARGET_##T: do {                                            \
+        static const FcntlEntry ent_##T = {                          \
+            .name = #T, .host_cmd = T,                               \
+            .host_fn = do_fcntl_##FN, .arg_type = ARG_PTR            \
+        };                                                           \
+        return is_64 ? &ent_##T : NULL;                              \
+    } while (0)
+#endif
+
+    switch (cmd) {
+    CMD1(F_DUPFD, ARG_DEC, do_fcntl_int);
+    CMD1(F_GETFD, ARG_NONE, do_fcntl_int);
+    CMD1(F_SETFD, ARG_DEC, do_fcntl_int);
+    CMD1(F_GETFL, ARG_NONE, do_fcntl_getfl);
+    CMD1(F_SETFL, ARG_DEC, do_fcntl_setfl);
+
+    CMD2(F_GETLK, F_GETLK64, ARG_PTR, do_fcntl_getlk);
+    CMD2(F_SETLK, F_SETLK64, ARG_PTR, do_fcntl_setlk);
+    CMD2(F_SETLKW, F_SETLKW64, ARG_PTR, do_fcntl_setlk);
+
+    CMD1(F_GETOWN, ARG_NONE, do_fcntl_int);
+    CMD1(F_SETOWN, ARG_DEC, do_fcntl_int);
+    CMD1(F_GETSIG, ARG_NONE, do_fcntl_int);
+    CMD1(F_SETSIG, ARG_DEC, do_fcntl_int);
+
+    CMD64(F_GETLK64, getlk64);
+    CMD64(F_SETLK64, setlk64);
+    CMD64(F_SETLKW64, setlk64);
+
+    CMD1(F_GETLEASE, ARG_NONE, do_fcntl_int);
+    CMD1(F_SETLEASE, ARG_DEC, do_fcntl_int);
+#ifdef F_DUPFD_CLOEXEC
+    CMD1(F_DUPFD_CLOEXEC, ARG_DEC, do_fcntl_int);
+#endif
+    CMD1(F_NOTIFY, ARG_DEC, do_fcntl_int);
+#ifdef F_GETOWN_EX
+    CMD1(F_GETOWN_EX, ARG_PTR, do_fcntl_getown_ex);
+    CMD1(F_SETOWN_EX, ARG_PTR, do_fcntl_setown_ex);
+#endif
+#ifdef F_SETPIPE_SZ
+    CMD1(F_SETPIPE_SZ, ARG_DEC, do_fcntl_int);
+    CMD1(F_GETPIPE_SZ, ARG_DEC, do_fcntl_int);
+#endif
+    }
+    return NULL;
+
+#undef CMD1
+#undef CMD2
+#undef CMD64
+#undef HOST_CMD_ADJ64
+}
+
+static abi_long do_fcntl(int fd, int target_cmd, abi_ulong arg, int is_64)
+{
+    const FcntlEntry *ent = target_fcntl_cmd(target_cmd, is_64);
+
+    if (ent == NULL) {
+        return -TARGET_EINVAL;
+    }
+    return ent->host_fn(fd, ent->host_cmd, arg);
+}
+
+static void do_print_fcntl(const SyscallDef *def, int fd, int target_cmd,
+                           abi_ulong arg, int is_64)
+{
+    const FcntlEntry *ent = target_fcntl_cmd(target_cmd, is_64);
+
+    switch (ent->arg_type) {
+    case ARG_NONE:
+        gemu_log("%d %s(%d,%s)", getpid(), def->name, fd, ent->name);
+        break;
+    case ARG_DEC:
+        gemu_log("%d %s(%d,%s," TARGET_ABI_FMT_ld ")",
+                 getpid(), def->name, fd, ent->name, arg);
+        break;
+    case ARG_PTR:
+        gemu_log("%d %s(%d,%s,0x" TARGET_ABI_FMT_lx ")",
+                 getpid(), def->name, fd, ent->name, arg);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
+
+#ifdef TARGET_NR_fcntl
+SYSCALL_IMPL(fcntl)
+{
+    return do_fcntl(arg1, arg2, arg3, 0);
+}
+
+static void print_fcntl(const SyscallDef *def, int64_t in[6])
+{
+    return do_print_fcntl(def, in[0], in[1], in[2], 0);
+}
+#endif
+
+#if TARGET_ABI_BITS == 32
+SYSCALL_IMPL(fcntl64)
+{
+    int is_64 = 1;
+#ifdef TARGET_ARM
+    if (!cpu_env->eabi) {
+        is_64 = -1;
+    }
+#endif
+    return do_fcntl(arg1, arg2, arg3, is_64);
+}
+
+static void print_fcntl64(const SyscallDef *def, int64_t in[6])
+{
+    return do_print_fcntl(def, in[0], in[1], in[2], 1);
+}
+#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 5871d3e711..45fe05ac78 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -3513,102 +3513,6 @@ static void *clone_func(void *arg)
     return NULL;
 }
 
-/* warning : doesn't handle linux specific flags... */
-static int target_to_host_fcntl_cmd(int cmd)
-{
-    int ret;
-
-    switch(cmd) {
-    case TARGET_F_DUPFD:
-    case TARGET_F_GETFD:
-    case TARGET_F_SETFD:
-    case TARGET_F_GETFL:
-    case TARGET_F_SETFL:
-        ret = cmd;
-        break;
-    case TARGET_F_GETLK:
-        ret = F_GETLK64;
-        break;
-    case TARGET_F_SETLK:
-        ret = F_SETLK64;
-        break;
-    case TARGET_F_SETLKW:
-        ret = F_SETLKW64;
-        break;
-    case TARGET_F_GETOWN:
-        ret = F_GETOWN;
-        break;
-    case TARGET_F_SETOWN:
-        ret = F_SETOWN;
-        break;
-    case TARGET_F_GETSIG:
-        ret = F_GETSIG;
-        break;
-    case TARGET_F_SETSIG:
-        ret = F_SETSIG;
-        break;
-#if TARGET_ABI_BITS == 32
-    case TARGET_F_GETLK64:
-        ret = F_GETLK64;
-        break;
-    case TARGET_F_SETLK64:
-        ret = F_SETLK64;
-        break;
-    case TARGET_F_SETLKW64:
-        ret = F_SETLKW64;
-        break;
-#endif
-    case TARGET_F_SETLEASE:
-        ret = F_SETLEASE;
-        break;
-    case TARGET_F_GETLEASE:
-        ret = F_GETLEASE;
-        break;
-#ifdef F_DUPFD_CLOEXEC
-    case TARGET_F_DUPFD_CLOEXEC:
-        ret = F_DUPFD_CLOEXEC;
-        break;
-#endif
-    case TARGET_F_NOTIFY:
-        ret = F_NOTIFY;
-        break;
-#ifdef F_GETOWN_EX
-    case TARGET_F_GETOWN_EX:
-        ret = F_GETOWN_EX;
-        break;
-#endif
-#ifdef F_SETOWN_EX
-    case TARGET_F_SETOWN_EX:
-        ret = F_SETOWN_EX;
-        break;
-#endif
-#ifdef F_SETPIPE_SZ
-    case TARGET_F_SETPIPE_SZ:
-        ret = F_SETPIPE_SZ;
-        break;
-    case TARGET_F_GETPIPE_SZ:
-        ret = F_GETPIPE_SZ;
-        break;
-#endif
-    default:
-        ret = -TARGET_EINVAL;
-        break;
-    }
-
-#if defined(__powerpc64__)
-    /* On PPC64, glibc headers has the F_*LK* defined to 12, 13 and 14 and
-     * is not supported by kernel. The glibc fcntl call actually adjusts
-     * them to 5, 6 and 7 before making the syscall(). Since we make the
-     * syscall directly, adjust to what is supported by the kernel.
-     */
-    if (ret >= F_GETLK64 && ret <= F_SETLKW64) {
-        ret -= F_GETLK64 - 5;
-    }
-#endif
-
-    return ret;
-}
-
 #define FLOCK_TRANSTBL \
     switch (type) { \
     TRANSTBL_CONVERT(F_RDLCK); \
@@ -3774,114 +3678,6 @@ static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr,
     return 0;
 }
 
-static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
-{
-    struct flock64 fl64;
-#ifdef F_GETOWN_EX
-    struct f_owner_ex fox;
-    struct target_f_owner_ex *target_fox;
-#endif
-    abi_long ret;
-    int host_cmd = target_to_host_fcntl_cmd(cmd);
-
-    if (host_cmd == -TARGET_EINVAL)
-	    return host_cmd;
-
-    switch(cmd) {
-    case TARGET_F_GETLK:
-        ret = copy_from_user_flock(&fl64, arg);
-        if (ret) {
-            return ret;
-        }
-        ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
-        if (ret == 0) {
-            ret = copy_to_user_flock(arg, &fl64);
-        }
-        break;
-
-    case TARGET_F_SETLK:
-    case TARGET_F_SETLKW:
-        ret = copy_from_user_flock(&fl64, arg);
-        if (ret) {
-            return ret;
-        }
-        ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
-        break;
-
-    case TARGET_F_GETLK64:
-        ret = copy_from_user_flock64(&fl64, arg);
-        if (ret) {
-            return ret;
-        }
-        ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
-        if (ret == 0) {
-            ret = copy_to_user_flock64(arg, &fl64);
-        }
-        break;
-    case TARGET_F_SETLK64:
-    case TARGET_F_SETLKW64:
-        ret = copy_from_user_flock64(&fl64, arg);
-        if (ret) {
-            return ret;
-        }
-        ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
-        break;
-
-    case TARGET_F_GETFL:
-        ret = get_errno(safe_fcntl(fd, host_cmd, arg));
-        if (ret >= 0) {
-            ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
-        }
-        break;
-
-    case TARGET_F_SETFL:
-        ret = get_errno(safe_fcntl(fd, host_cmd,
-                                   target_to_host_bitmask(arg,
-                                                          fcntl_flags_tbl)));
-        break;
-
-#ifdef F_GETOWN_EX
-    case TARGET_F_GETOWN_EX:
-        ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
-        if (ret >= 0) {
-            if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0))
-                return -TARGET_EFAULT;
-            target_fox->type = tswap32(fox.type);
-            target_fox->pid = tswap32(fox.pid);
-            unlock_user_struct(target_fox, arg, 1);
-        }
-        break;
-#endif
-
-#ifdef F_SETOWN_EX
-    case TARGET_F_SETOWN_EX:
-        if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1))
-            return -TARGET_EFAULT;
-        fox.type = tswap32(target_fox->type);
-        fox.pid = tswap32(target_fox->pid);
-        unlock_user_struct(target_fox, arg, 0);
-        ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
-        break;
-#endif
-
-    case TARGET_F_SETOWN:
-    case TARGET_F_GETOWN:
-    case TARGET_F_SETSIG:
-    case TARGET_F_GETSIG:
-    case TARGET_F_SETLEASE:
-    case TARGET_F_GETLEASE:
-    case TARGET_F_SETPIPE_SZ:
-    case TARGET_F_GETPIPE_SZ:
-        ret = get_errno(safe_fcntl(fd, host_cmd, arg));
-        break;
-
-    default:
-        ret = get_errno(safe_fcntl(fd, cmd, arg));
-        break;
-    }
-    return ret;
-}
-
 #ifdef USE_UID16
 
 static inline int high2lowuid(int uid)
@@ -4445,10 +4241,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_fcntl
-    case TARGET_NR_fcntl:
-        return do_fcntl(arg1, arg2, arg3);
-#endif
     case TARGET_NR_setpgid:
         return get_errno(setpgid(arg1, arg2));
     case TARGET_NR_umask:
@@ -7015,53 +6807,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
            This is a hint, so ignoring and returning success is ok.  */
         return 0;
 #endif
-#if TARGET_ABI_BITS == 32
-    case TARGET_NR_fcntl64:
-    {
-	int cmd;
-	struct flock64 fl;
-        from_flock64_fn *copyfrom = copy_from_user_flock64;
-        to_flock64_fn *copyto = copy_to_user_flock64;
-
-#ifdef TARGET_ARM
-        if (!((CPUARMState *)cpu_env)->eabi) {
-            copyfrom = copy_from_user_oabi_flock64;
-            copyto = copy_to_user_oabi_flock64;
-        }
-#endif
-
-	cmd = target_to_host_fcntl_cmd(arg2);
-        if (cmd == -TARGET_EINVAL) {
-            return cmd;
-        }
-
-        switch(arg2) {
-        case TARGET_F_GETLK64:
-            ret = copyfrom(&fl, arg3);
-            if (ret) {
-                break;
-            }
-            ret = get_errno(safe_fcntl(arg1, cmd, &fl));
-            if (ret == 0) {
-                ret = copyto(arg3, &fl);
-            }
-	    break;
-
-        case TARGET_F_SETLK64:
-        case TARGET_F_SETLKW64:
-            ret = copyfrom(&fl, arg3);
-            if (ret) {
-                break;
-            }
-            ret = get_errno(safe_fcntl(arg1, cmd, &fl));
-	    break;
-        default:
-            ret = do_fcntl(arg1, arg2, arg3);
-            break;
-        }
-        return ret;
-    }
-#endif
 #ifdef TARGET_NR_cacheflush
     case TARGET_NR_cacheflush:
         /* self-modifying code is handled automatically, so nothing needed */
@@ -8048,6 +7793,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
                                 int64_t arg2, int64_t arg3, int64_t arg4, \
                                 int64_t arg5, int64_t arg6)
 
+#include "syscall-fcntl.inc.c"
 #include "syscall-file.inc.c"
 #include "syscall-ioctl.inc.c"
 #include "syscall-ipc.inc.c"
diff --git a/linux-user/strace.list b/linux-user/strace.list
index efc64cd29f..68e202ca15 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -157,12 +157,6 @@
 #ifdef TARGET_NR_fchownat
 { TARGET_NR_fchownat, "fchownat" , NULL, print_fchownat, NULL },
 #endif
-#ifdef TARGET_NR_fcntl
-{ TARGET_NR_fcntl, "fcntl" , NULL, print_fcntl, NULL },
-#endif
-#ifdef TARGET_NR_fcntl64
-{ TARGET_NR_fcntl64, "fcntl64" , NULL, print_fcntl64, NULL },
-#endif
 #ifdef TARGET_NR_fdatasync
 { TARGET_NR_fdatasync, "fdatasync" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 51/74] linux-user: Split out setpgid
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (49 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 50/74] linux-user: Split out fcntl, fcntl64 Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 52/74] linux-user: Split out umask Richard Henderson
                   ` (25 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     | 1 +
 linux-user/syscall-proc.inc.c | 5 +++++
 linux-user/syscall.c          | 2 --
 linux-user/strace.list        | 3 ---
 4 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 5cf39f2bb9..6de7b84351 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -187,6 +187,7 @@ SYSCALL_DEF(semctl, ARG_DEC, ARG_DEC, ARG_DEC, ARG_HEX);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semget)
 SYSCALL_DEF(semget, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
+SYSCALL_DEF(setpgid, ARG_DEC, ARG_DEC);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semop)
 SYSCALL_DEF(semop, ARG_DEC, ARG_PTR, ARG_DEC);
 #endif
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
index 517f84e139..5bd27d1d4b 100644
--- a/linux-user/syscall-proc.inc.c
+++ b/linux-user/syscall-proc.inc.c
@@ -468,6 +468,11 @@ SYSCALL_IMPL(nice)
 }
 #endif
 
+SYSCALL_IMPL(setpgid)
+{
+    return get_errno(setpgid(arg1, arg2));
+}
+
 SYSCALL_IMPL(times)
 {
     abi_ulong target_buf = arg1;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 45fe05ac78..dcb35e1228 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4241,8 +4241,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_setpgid:
-        return get_errno(setpgid(arg1, arg2));
     case TARGET_NR_umask:
         return get_errno(umask(arg1));
     case TARGET_NR_chroot:
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 68e202ca15..4a527b0c65 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1073,9 +1073,6 @@
 #ifdef TARGET_NR_setns
 { TARGET_NR_setns, "setns" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_setpgid
-{ TARGET_NR_setpgid, "setpgid" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_setpgrp
 { TARGET_NR_setpgrp, "setpgrp" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 52/74] linux-user: Split out umask
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (50 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 51/74] linux-user: Split out setpgid Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 53/74] linux-user: Split out chroot Richard Henderson
                   ` (24 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     | 1 +
 linux-user/syscall-file.inc.c | 5 +++++
 linux-user/syscall.c          | 2 --
 linux-user/strace.list        | 3 ---
 4 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 6de7b84351..b6538350a3 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -214,6 +214,7 @@ SYSCALL_DEF(syncfs, ARG_DEC);
 SYSCALL_DEF(time, ARG_PTR);
 #endif
 SYSCALL_DEF(times, ARG_PTR);
+SYSCALL_DEF(umask, ARG_OCT);
 #ifdef TARGET_NR_umount
 SYSCALL_DEF(umount, ARG_STR);
 #endif
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 4080ab250e..cbde6d906f 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -1117,6 +1117,11 @@ SYSCALL_IMPL(rmdir)
 }
 #endif
 
+SYSCALL_IMPL(umask)
+{
+    return get_errno(umask(arg1));
+}
+
 SYSCALL_IMPL(unlinkat)
 {
     return do_unlinkat(arg1, arg2, arg3);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index dcb35e1228..419edceab2 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4241,8 +4241,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_umask:
-        return get_errno(umask(arg1));
     case TARGET_NR_chroot:
         if (!(p = lock_user_string(arg1)))
             return -TARGET_EFAULT;
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 4a527b0c65..61d22ad16b 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1293,9 +1293,6 @@
 #ifdef TARGET_NR_ulimit
 { TARGET_NR_ulimit, "ulimit" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_umask
-{ TARGET_NR_umask, "umask" , "%s(%#o)", NULL, NULL },
-#endif
 #ifdef TARGET_NR_uname
 { TARGET_NR_uname, "uname" , "%s(%p)", NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 53/74] linux-user: Split out chroot
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (51 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 52/74] linux-user: Split out umask Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 54/74] linux-user: Split out getpgid, getpgrp Richard Henderson
                   ` (23 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  1 +
 linux-user/strace.c           | 12 ------------
 linux-user/syscall-file.inc.c | 13 +++++++++++++
 linux-user/syscall.c          |  6 ------
 linux-user/strace.list        |  3 ---
 5 files changed, 14 insertions(+), 21 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index b6538350a3..b93ca1f78a 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -30,6 +30,7 @@ SYSCALL_DEF(chdir, ARG_STR);
 #ifdef TARGET_NR_chmod
 SYSCALL_DEF(chmod, ARG_STR, ARG_MODEFLAG);
 #endif
+SYSCALL_DEF(chroot, ARG_STR);
 SYSCALL_DEF_ARGS(clone, ARG_CLONEFLAG, ARG_PTR, ARG_PTR, ARG_PTR, ARG_PTR);
 SYSCALL_DEF(close, ARG_DEC);
 #ifdef TARGET_NR_creat
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 560284b3c3..787bf41307 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1130,18 +1130,6 @@ print_accept(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_chroot
-static void
-print_chroot(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_clock_adjtime
 static void
 print_clock_adjtime(const struct syscallname *name,
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index cbde6d906f..6e730e3152 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -88,6 +88,19 @@ SYSCALL_IMPL(chmod)
 }
 #endif
 
+SYSCALL_IMPL(chroot)
+{
+    char *p = lock_user_string(arg1);
+    abi_long ret;
+
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(chroot(p));
+    unlock_user(p, arg1, 0);
+    return ret;
+}
+
 SYSCALL_IMPL(close)
 {
     int fd = arg1;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 419edceab2..255765aaa7 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4241,12 +4241,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_chroot:
-        if (!(p = lock_user_string(arg1)))
-            return -TARGET_EFAULT;
-        ret = get_errno(chroot(p));
-        unlock_user(p, arg1, 0);
-        return ret;
 #ifdef TARGET_NR_getpgrp
     case TARGET_NR_getpgrp:
         return get_errno(getpgrp());
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 61d22ad16b..7679e844b6 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -58,9 +58,6 @@
 #ifdef TARGET_NR_chown32
 { TARGET_NR_chown32, "chown32" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_chroot
-{ TARGET_NR_chroot, "chroot" , NULL, print_chroot, NULL },
-#endif
 #ifdef TARGET_NR_clock_adjtime
 { TARGET_NR_clock_adjtime, "clock_adjtime" , NULL, print_clock_adjtime, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 54/74] linux-user: Split out getpgid, getpgrp
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (52 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 53/74] linux-user: Split out chroot Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 55/74] linux-user: Split out getsid, setsid Richard Henderson
                   ` (22 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  4 ++++
 linux-user/syscall-proc.inc.c | 12 ++++++++++++
 linux-user/syscall.c          |  6 ------
 linux-user/strace.list        |  6 ------
 4 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index b93ca1f78a..2ade9ec749 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -59,6 +59,10 @@ SYSCALL_DEF(futimesat, ARG_ATDIRFD, ARG_STR, ARG_PTR);
 #ifdef TARGET_NR_fork
 SYSCALL_DEF(fork);
 #endif
+SYSCALL_DEF(getpgid, ARG_DEC);
+#ifdef TARGET_NR_getpgrp
+SYSCALL_DEF(getpgrp);
+#endif
 #ifdef TARGET_NR_getpid
 SYSCALL_DEF(getpid);
 #endif
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
index 5bd27d1d4b..39de5b7863 100644
--- a/linux-user/syscall-proc.inc.c
+++ b/linux-user/syscall-proc.inc.c
@@ -438,6 +438,18 @@ SYSCALL_IMPL(fork)
 }
 #endif
 
+SYSCALL_IMPL(getpgid)
+{
+    return get_errno(getpgid(arg1));
+}
+
+#ifdef TARGET_NR_getpgrp
+SYSCALL_IMPL(getpgrp)
+{
+    return get_errno(getpgrp());
+}
+#endif
+
 #ifdef TARGET_NR_getpid
 SYSCALL_IMPL(getpid)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 255765aaa7..75989a01bf 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4241,10 +4241,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_getpgrp
-    case TARGET_NR_getpgrp:
-        return get_errno(getpgrp());
-#endif
     case TARGET_NR_setsid:
         return get_errno(setsid());
 #ifdef TARGET_NR_sigaction
@@ -5388,8 +5384,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         }
         return ret;
 #endif
-    case TARGET_NR_getpgid:
-        return get_errno(getpgid(arg1));
     case TARGET_NR_fchdir:
         return get_errno(fchdir(arg1));
     case TARGET_NR_personality:
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 7679e844b6..d283c924a7 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -262,12 +262,6 @@
 #ifdef TARGET_NR_getpeername
 { TARGET_NR_getpeername, "getpeername" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_getpgid
-{ TARGET_NR_getpgid, "getpgid" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_getpgrp
-{ TARGET_NR_getpgrp, "getpgrp" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_getpmsg
 { TARGET_NR_getpmsg, "getpmsg" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 55/74] linux-user: Split out getsid, setsid
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (53 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 54/74] linux-user: Split out getpgid, getpgrp Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 56/74] linux-user: Split out sigaction, rt_sigaction Richard Henderson
                   ` (21 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  2 ++
 linux-user/syscall-proc.inc.c | 10 ++++++++++
 linux-user/syscall.c          |  4 ----
 linux-user/strace.list        |  6 ------
 4 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 2ade9ec749..cd2c127c41 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -69,6 +69,7 @@ SYSCALL_DEF(getpid);
 #ifdef TARGET_NR_getppid
 SYSCALL_DEF(getppid);
 #endif
+SYSCALL_DEF(getsid, ARG_DEC);
 #ifdef TARGET_NR_getxpid
 SYSCALL_DEF(getxpid);
 #endif
@@ -193,6 +194,7 @@ SYSCALL_DEF(semctl, ARG_DEC, ARG_DEC, ARG_DEC, ARG_HEX);
 SYSCALL_DEF(semget, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
 SYSCALL_DEF(setpgid, ARG_DEC, ARG_DEC);
+SYSCALL_DEF(setsid);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semop)
 SYSCALL_DEF(semop, ARG_DEC, ARG_PTR, ARG_DEC);
 #endif
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
index 39de5b7863..567df54581 100644
--- a/linux-user/syscall-proc.inc.c
+++ b/linux-user/syscall-proc.inc.c
@@ -464,6 +464,11 @@ SYSCALL_IMPL(getppid)
 }
 #endif
 
+SYSCALL_IMPL(getsid)
+{
+    return get_errno(getsid(arg1));
+}
+
 #ifdef TARGET_NR_getxpid
 SYSCALL_IMPL(getxpid)
 {
@@ -485,6 +490,11 @@ SYSCALL_IMPL(setpgid)
     return get_errno(setpgid(arg1, arg2));
 }
 
+SYSCALL_IMPL(setsid)
+{
+    return get_errno(setsid());
+}
+
 SYSCALL_IMPL(times)
 {
     abi_ulong target_buf = arg1;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 75989a01bf..0e9f4fd5ae 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4241,8 +4241,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_setsid:
-        return get_errno(setsid());
 #ifdef TARGET_NR_sigaction
     case TARGET_NR_sigaction:
         {
@@ -5664,8 +5662,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         /* NOTE: the flock constant seems to be the same for every
            Linux platform */
         return get_errno(safe_flock(arg1, arg2));
-    case TARGET_NR_getsid:
-        return get_errno(getsid(arg1));
 #if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
     case TARGET_NR_fdatasync:
         return get_errno(fdatasync(arg1));
diff --git a/linux-user/strace.list b/linux-user/strace.list
index d283c924a7..bf87a6d4cb 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -292,9 +292,6 @@
 #ifdef TARGET_NR_getrusage
 { TARGET_NR_getrusage, "getrusage" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_getsid
-{ TARGET_NR_getsid, "getsid" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_getsockname
 { TARGET_NR_getsockname, "getsockname" , NULL, NULL, NULL },
 #endif
@@ -1100,9 +1097,6 @@
 #ifdef TARGET_NR_set_robust_list
 { TARGET_NR_set_robust_list, "set_robust_list" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_setsid
-{ TARGET_NR_setsid, "setsid" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_setsockopt
 { TARGET_NR_setsockopt, "setsockopt" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 56/74] linux-user: Split out sigaction, rt_sigaction
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (54 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 55/74] linux-user: Split out getsid, setsid Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 57/74] linux-user: Split out sgetmask, ssetmask Richard Henderson
                   ` (20 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h    |  10 ++
 linux-user/strace.c          |  14 ---
 linux-user/syscall-sig.inc.c | 172 +++++++++++++++++++++++++++++++++++
 linux-user/syscall.c         | 160 --------------------------------
 linux-user/strace.list       |   6 --
 5 files changed, 182 insertions(+), 180 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index cd2c127c41..b62bffeb68 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -187,6 +187,13 @@ SYSCALL_DEF(readv, ARG_DEC, ARG_PTR, ARG_DEC);
 #ifdef TARGET_NR_rmdir
 SYSCALL_DEF(rmdir, ARG_STR);
 #endif
+#if defined(TARGET_ALPHA)
+SYSCALL_DEF(rt_sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR, ARG_DEC, ARG_PTR);
+#elif defined(TARGET_SPARC)
+SYSCALL_DEF(rt_sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR, ARG_PTR, ARG_DEC);
+#else
+SYSCALL_DEF(rt_sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR, ARG_DEC);
+#endif
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semctl)
 SYSCALL_DEF(semctl, ARG_DEC, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
@@ -212,6 +219,9 @@ SYSCALL_DEF(shmdt, ARG_PTR);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_shmget)
 SYSCALL_DEF(shmget, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
+#ifdef TARGET_NR_sigaction
+SYSCALL_DEF(sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR);
+#endif
 #ifdef TARGET_NR_stime
 SYSCALL_DEF(stime, ARG_PTR);
 #endif
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 787bf41307..83dd755c73 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1564,20 +1564,6 @@ print_fstat(const struct syscallname *name,
 #define print_fstat64     print_fstat
 #endif
 
-#ifdef TARGET_NR_rt_sigaction
-static void
-print_rt_sigaction(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_signal(arg0, 0);
-    print_pointer(arg1, 0);
-    print_pointer(arg2, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_rt_sigprocmask
 static void
 print_rt_sigprocmask(const struct syscallname *name,
diff --git a/linux-user/syscall-sig.inc.c b/linux-user/syscall-sig.inc.c
index a4fbcc567d..918d58878f 100644
--- a/linux-user/syscall-sig.inc.c
+++ b/linux-user/syscall-sig.inc.c
@@ -39,3 +39,175 @@ SYSCALL_IMPL(pause)
     return -TARGET_EINTR;
 }
 #endif
+
+SYSCALL_IMPL(rt_sigaction)
+{
+    abi_long ret;
+#if defined(TARGET_ALPHA)
+    /*
+     * For Alpha and SPARC this is a 5 argument syscall, with
+     * a 'restorer' parameter which must be copied into the
+     * sa_restorer field of the sigaction struct.
+     * For Alpha that 'restorer' is arg5; for SPARC it is arg4,
+     * and arg5 is the sigsetsize.
+     * Alpha also has a separate rt_sigaction struct that it uses
+     * here; SPARC uses the usual sigaction struct.
+     */
+    struct target_rt_sigaction *rt_act;
+    struct target_sigaction act, oact, *pact = NULL;
+
+    if (arg4 != sizeof(target_sigset_t)) {
+        return -TARGET_EINVAL;
+    }
+    if (arg2) {
+        if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1)) {
+            return -TARGET_EFAULT;
+        }
+        act._sa_handler = rt_act->_sa_handler;
+        act.sa_mask = rt_act->sa_mask;
+        act.sa_flags = rt_act->sa_flags;
+        act.sa_restorer = arg5;
+        unlock_user_struct(rt_act, arg2, 0);
+        pact = &act;
+    }
+    ret = get_errno(do_sigaction(arg1, pact, &oact));
+    if (!is_error(ret) && arg3) {
+        if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0)) {
+            return -TARGET_EFAULT;
+        }
+        rt_act->_sa_handler = oact._sa_handler;
+        rt_act->sa_mask = oact.sa_mask;
+        rt_act->sa_flags = oact.sa_flags;
+        unlock_user_struct(rt_act, arg3, 1);
+    }
+#else
+# ifdef TARGET_SPARC
+    target_ulong restorer = arg4;
+    target_ulong sigsetsize = arg5;
+# else
+    target_ulong sigsetsize = arg4;
+# endif
+    struct target_sigaction act, oact, *pact = NULL;
+
+    if (sigsetsize != sizeof(target_sigset_t)) {
+        return -TARGET_EINVAL;
+    }
+    if (arg2) {
+        if (!lock_user_struct(VERIFY_READ, pact, arg2, 1)) {
+            return -TARGET_EFAULT;
+        }
+        act = *pact;
+        unlock_user_struct(pact, arg2, 0);
+# ifdef TARGET_ARCH_HAS_KA_RESTORER
+        act.ka_restorer = restorer;
+# endif
+        pact = &act;
+    }
+
+    ret = get_errno(do_sigaction(arg1, pact, &oact));
+
+    if (!is_error(ret) && arg3) {
+        if (!lock_user_struct(VERIFY_WRITE, pact, arg3, 0)) {
+            return -TARGET_EFAULT;
+        }
+        *pact = oact;
+        unlock_user_struct(pact, arg3, 1);
+    }
+#endif
+    return ret;
+}
+
+#ifdef TARGET_NR_sigaction
+SYSCALL_IMPL(sigaction)
+{
+    abi_long ret;
+#if defined(TARGET_ALPHA)
+    struct target_sigaction act, oact, *pact = NULL;
+    struct target_old_sigaction *old_act;
+
+    if (arg2) {
+        if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) {
+            return -TARGET_EFAULT;
+        }
+        act._sa_handler = old_act->_sa_handler;
+        target_siginitset(&act.sa_mask, old_act->sa_mask);
+        act.sa_flags = old_act->sa_flags;
+        act.sa_restorer = 0;
+        unlock_user_struct(old_act, arg2, 0);
+        pact = &act;
+    }
+
+    ret = get_errno(do_sigaction(arg1, pact, &oact));
+
+    if (!is_error(ret) && arg3) {
+        if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) {
+            return -TARGET_EFAULT;
+        }
+        old_act->_sa_handler = oact._sa_handler;
+        old_act->sa_mask = oact.sa_mask.sig[0];
+        old_act->sa_flags = oact.sa_flags;
+        unlock_user_struct(old_act, arg3, 1);
+    }
+#elif defined(TARGET_MIPS)
+    struct target_sigaction act, oact, *pact = NULL, *old_act;
+
+    if (arg2) {
+        if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) {
+            return -TARGET_EFAULT;
+        }
+        act._sa_handler = old_act->_sa_handler;
+        target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
+        act.sa_flags = old_act->sa_flags;
+        unlock_user_struct(old_act, arg2, 0);
+        pact = &act;
+    }
+
+    ret = get_errno(do_sigaction(arg1, pact, &oact));
+
+    if (!is_error(ret) && arg3) {
+        if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) {
+            return -TARGET_EFAULT;
+        }
+        old_act->_sa_handler = oact._sa_handler;
+        old_act->sa_flags = oact.sa_flags;
+        old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
+        old_act->sa_mask.sig[1] = 0;
+        old_act->sa_mask.sig[2] = 0;
+        old_act->sa_mask.sig[3] = 0;
+        unlock_user_struct(old_act, arg3, 1);
+    }
+#else
+    struct target_old_sigaction *old_act;
+    struct target_sigaction act, oact, *pact = NULL;
+
+    if (arg2) {
+        if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) {
+            return -TARGET_EFAULT;
+        }
+        act._sa_handler = old_act->_sa_handler;
+        target_siginitset(&act.sa_mask, old_act->sa_mask);
+        act.sa_flags = old_act->sa_flags;
+        act.sa_restorer = old_act->sa_restorer;
+#ifdef TARGET_ARCH_HAS_KA_RESTORER
+        act.ka_restorer = 0;
+#endif
+        unlock_user_struct(old_act, arg2, 0);
+        pact = &act;
+    }
+
+    ret = get_errno(do_sigaction(arg1, pact, &oact));
+
+    if (!is_error(ret) && arg3) {
+        if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) {
+            return -TARGET_EFAULT;
+        }
+        old_act->_sa_handler = oact._sa_handler;
+        old_act->sa_mask = oact.sa_mask.sig[0];
+        old_act->sa_flags = oact.sa_flags;
+        old_act->sa_restorer = oact.sa_restorer;
+        unlock_user_struct(old_act, arg3, 1);
+    }
+#endif
+    return ret;
+}
+#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 0e9f4fd5ae..3ef1bfb4ec 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4241,166 +4241,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_sigaction
-    case TARGET_NR_sigaction:
-        {
-#if defined(TARGET_ALPHA)
-            struct target_sigaction act, oact, *pact = 0;
-            struct target_old_sigaction *old_act;
-            if (arg2) {
-                if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
-                    return -TARGET_EFAULT;
-                act._sa_handler = old_act->_sa_handler;
-                target_siginitset(&act.sa_mask, old_act->sa_mask);
-                act.sa_flags = old_act->sa_flags;
-                act.sa_restorer = 0;
-                unlock_user_struct(old_act, arg2, 0);
-                pact = &act;
-            }
-            ret = get_errno(do_sigaction(arg1, pact, &oact));
-            if (!is_error(ret) && arg3) {
-                if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
-                    return -TARGET_EFAULT;
-                old_act->_sa_handler = oact._sa_handler;
-                old_act->sa_mask = oact.sa_mask.sig[0];
-                old_act->sa_flags = oact.sa_flags;
-                unlock_user_struct(old_act, arg3, 1);
-            }
-#elif defined(TARGET_MIPS)
-	    struct target_sigaction act, oact, *pact, *old_act;
-
-	    if (arg2) {
-                if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
-                    return -TARGET_EFAULT;
-		act._sa_handler = old_act->_sa_handler;
-		target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
-		act.sa_flags = old_act->sa_flags;
-		unlock_user_struct(old_act, arg2, 0);
-		pact = &act;
-	    } else {
-		pact = NULL;
-	    }
-
-	    ret = get_errno(do_sigaction(arg1, pact, &oact));
-
-	    if (!is_error(ret) && arg3) {
-                if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
-                    return -TARGET_EFAULT;
-		old_act->_sa_handler = oact._sa_handler;
-		old_act->sa_flags = oact.sa_flags;
-		old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
-		old_act->sa_mask.sig[1] = 0;
-		old_act->sa_mask.sig[2] = 0;
-		old_act->sa_mask.sig[3] = 0;
-		unlock_user_struct(old_act, arg3, 1);
-	    }
-#else
-            struct target_old_sigaction *old_act;
-            struct target_sigaction act, oact, *pact;
-            if (arg2) {
-                if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
-                    return -TARGET_EFAULT;
-                act._sa_handler = old_act->_sa_handler;
-                target_siginitset(&act.sa_mask, old_act->sa_mask);
-                act.sa_flags = old_act->sa_flags;
-                act.sa_restorer = old_act->sa_restorer;
-#ifdef TARGET_ARCH_HAS_KA_RESTORER
-                act.ka_restorer = 0;
-#endif
-                unlock_user_struct(old_act, arg2, 0);
-                pact = &act;
-            } else {
-                pact = NULL;
-            }
-            ret = get_errno(do_sigaction(arg1, pact, &oact));
-            if (!is_error(ret) && arg3) {
-                if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
-                    return -TARGET_EFAULT;
-                old_act->_sa_handler = oact._sa_handler;
-                old_act->sa_mask = oact.sa_mask.sig[0];
-                old_act->sa_flags = oact.sa_flags;
-                old_act->sa_restorer = oact.sa_restorer;
-                unlock_user_struct(old_act, arg3, 1);
-            }
-#endif
-        }
-        return ret;
-#endif
-    case TARGET_NR_rt_sigaction:
-        {
-#if defined(TARGET_ALPHA)
-            /* For Alpha and SPARC this is a 5 argument syscall, with
-             * a 'restorer' parameter which must be copied into the
-             * sa_restorer field of the sigaction struct.
-             * For Alpha that 'restorer' is arg5; for SPARC it is arg4,
-             * and arg5 is the sigsetsize.
-             * Alpha also has a separate rt_sigaction struct that it uses
-             * here; SPARC uses the usual sigaction struct.
-             */
-            struct target_rt_sigaction *rt_act;
-            struct target_sigaction act, oact, *pact = 0;
-
-            if (arg4 != sizeof(target_sigset_t)) {
-                return -TARGET_EINVAL;
-            }
-            if (arg2) {
-                if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1))
-                    return -TARGET_EFAULT;
-                act._sa_handler = rt_act->_sa_handler;
-                act.sa_mask = rt_act->sa_mask;
-                act.sa_flags = rt_act->sa_flags;
-                act.sa_restorer = arg5;
-                unlock_user_struct(rt_act, arg2, 0);
-                pact = &act;
-            }
-            ret = get_errno(do_sigaction(arg1, pact, &oact));
-            if (!is_error(ret) && arg3) {
-                if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0))
-                    return -TARGET_EFAULT;
-                rt_act->_sa_handler = oact._sa_handler;
-                rt_act->sa_mask = oact.sa_mask;
-                rt_act->sa_flags = oact.sa_flags;
-                unlock_user_struct(rt_act, arg3, 1);
-            }
-#else
-#ifdef TARGET_SPARC
-            target_ulong restorer = arg4;
-            target_ulong sigsetsize = arg5;
-#else
-            target_ulong sigsetsize = arg4;
-#endif
-            struct target_sigaction *act;
-            struct target_sigaction *oact;
-
-            if (sigsetsize != sizeof(target_sigset_t)) {
-                return -TARGET_EINVAL;
-            }
-            if (arg2) {
-                if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) {
-                    return -TARGET_EFAULT;
-                }
-#ifdef TARGET_ARCH_HAS_KA_RESTORER
-                act->ka_restorer = restorer;
-#endif
-            } else {
-                act = NULL;
-            }
-            if (arg3) {
-                if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
-                    ret = -TARGET_EFAULT;
-                    goto rt_sigaction_fail;
-                }
-            } else
-                oact = NULL;
-            ret = get_errno(do_sigaction(arg1, act, oact));
-	rt_sigaction_fail:
-            if (act)
-                unlock_user_struct(act, arg2, 0);
-            if (oact)
-                unlock_user_struct(oact, arg3, 1);
-#endif
-        }
-        return ret;
 #ifdef TARGET_NR_sgetmask /* not on alpha */
     case TARGET_NR_sgetmask:
         {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index bf87a6d4cb..20a71adc21 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -926,9 +926,6 @@
 #ifdef TARGET_NR_rmdir
 { TARGET_NR_rmdir, "rmdir" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_rt_sigaction
-{ TARGET_NR_rt_sigaction, "rt_sigaction" , NULL, print_rt_sigaction, NULL },
-#endif
 #ifdef TARGET_NR_rt_sigpending
 { TARGET_NR_rt_sigpending, "rt_sigpending" , NULL, NULL, NULL },
 #endif
@@ -1125,9 +1122,6 @@
 #ifdef TARGET_NR_shutdown
 { TARGET_NR_shutdown, "shutdown" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_sigaction
-{ TARGET_NR_sigaction, "sigaction" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_sigaltstack
 { TARGET_NR_sigaltstack, "sigaltstack" , "%s(%p,%p)", NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 57/74] linux-user: Split out sgetmask, ssetmask
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (55 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 56/74] linux-user: Split out sigaction, rt_sigaction Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 58/74] linux-user: Split out sigprocmask, rt_sigprocmask Richard Henderson
                   ` (19 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h    |  6 ++++++
 linux-user/syscall-sig.inc.c | 32 ++++++++++++++++++++++++++++++++
 linux-user/syscall.c         | 27 ---------------------------
 linux-user/strace.list       |  6 ------
 4 files changed, 38 insertions(+), 33 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index b62bffeb68..99532f75b2 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -222,6 +222,12 @@ SYSCALL_DEF(shmget, ARG_DEC, ARG_DEC, ARG_HEX);
 #ifdef TARGET_NR_sigaction
 SYSCALL_DEF(sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR);
 #endif
+#ifdef TARGET_NR_sgetmask
+SYSCALL_DEF(sgetmask);
+#endif
+#ifdef TARGET_NR_ssetmask
+SYSCALL_DEF(ssetmask, ARG_HEX);
+#endif
 #ifdef TARGET_NR_stime
 SYSCALL_DEF(stime, ARG_PTR);
 #endif
diff --git a/linux-user/syscall-sig.inc.c b/linux-user/syscall-sig.inc.c
index 918d58878f..f50ed16b74 100644
--- a/linux-user/syscall-sig.inc.c
+++ b/linux-user/syscall-sig.inc.c
@@ -211,3 +211,35 @@ SYSCALL_IMPL(sigaction)
     return ret;
 }
 #endif
+
+#ifdef TARGET_NR_sgetmask
+SYSCALL_IMPL(sgetmask)
+{
+    sigset_t cur_set;
+    abi_ulong target_set;
+    abi_long ret = do_sigprocmask(0, NULL, &cur_set);
+
+    if (!ret) {
+        host_to_target_old_sigset(&target_set, &cur_set);
+        ret = target_set;
+    }
+    return ret;
+}
+#endif
+
+#ifdef TARGET_NR_ssetmask
+SYSCALL_IMPL(ssetmask)
+{
+    sigset_t set, oset;
+    abi_ulong target_set = arg1;
+    abi_long ret;
+
+    target_to_host_old_sigset(&set, &target_set);
+    ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
+    if (!ret) {
+        host_to_target_old_sigset(&target_set, &oset);
+        ret = target_set;
+    }
+    return ret;
+}
+#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 3ef1bfb4ec..7bd410bcf0 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4241,33 +4241,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_sgetmask /* not on alpha */
-    case TARGET_NR_sgetmask:
-        {
-            sigset_t cur_set;
-            abi_ulong target_set;
-            ret = do_sigprocmask(0, NULL, &cur_set);
-            if (!ret) {
-                host_to_target_old_sigset(&target_set, &cur_set);
-                ret = target_set;
-            }
-        }
-        return ret;
-#endif
-#ifdef TARGET_NR_ssetmask /* not on alpha */
-    case TARGET_NR_ssetmask:
-        {
-            sigset_t set, oset;
-            abi_ulong target_set = arg1;
-            target_to_host_old_sigset(&set, &target_set);
-            ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
-            if (!ret) {
-                host_to_target_old_sigset(&target_set, &oset);
-                ret = target_set;
-            }
-        }
-        return ret;
-#endif
 #ifdef TARGET_NR_sigprocmask
     case TARGET_NR_sigprocmask:
         {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 20a71adc21..3cad68e081 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1116,9 +1116,6 @@
 #ifdef TARGET_NR_setxattr
 { TARGET_NR_setxattr, "setxattr" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_sgetmask
-{ TARGET_NR_sgetmask, "sgetmask" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_shutdown
 { TARGET_NR_shutdown, "shutdown" , NULL, NULL, NULL },
 #endif
@@ -1158,9 +1155,6 @@
 #ifdef TARGET_NR_splice
 { TARGET_NR_splice, "splice" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_ssetmask
-{ TARGET_NR_ssetmask, "ssetmask" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_stat
 { TARGET_NR_stat, "stat" , NULL, print_stat, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 58/74] linux-user: Split out sigprocmask, rt_sigprocmask
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (56 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 57/74] linux-user: Split out sgetmask, ssetmask Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 59/74] linux-user: Split out sigpending, rt_sigpending Richard Henderson
                   ` (18 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h    |   6 ++
 linux-user/syscall.h         |   1 +
 linux-user/strace.c          |  44 +++++++------
 linux-user/syscall-sig.inc.c | 123 +++++++++++++++++++++++++++++++++++
 linux-user/syscall.c         | 109 -------------------------------
 linux-user/strace.list       |   6 --
 6 files changed, 154 insertions(+), 135 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 99532f75b2..ef77f60524 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -194,6 +194,7 @@ SYSCALL_DEF(rt_sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR, ARG_PTR, ARG_DEC);
 #else
 SYSCALL_DEF(rt_sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR, ARG_DEC);
 #endif
+SYSCALL_DEF(rt_sigprocmask, ARG_SIGPROCMASKHOW, ARG_PTR, ARG_PTR, ARG_DEC);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semctl)
 SYSCALL_DEF(semctl, ARG_DEC, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
@@ -222,6 +223,11 @@ SYSCALL_DEF(shmget, ARG_DEC, ARG_DEC, ARG_HEX);
 #ifdef TARGET_NR_sigaction
 SYSCALL_DEF(sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR);
 #endif
+#if defined(TARGET_ALPHA)
+SYSCALL_DEF(sigprocmask, ARG_SIGPROCMASKHOW, ARG_HEX);
+#elif defined(TARGET_NR_sigprocmask)
+SYSCALL_DEF(sigprocmask, ARG_SIGPROCMASKHOW, ARG_PTR, ARG_PTR);
+#endif
 #ifdef TARGET_NR_sgetmask
 SYSCALL_DEF(sgetmask);
 #endif
diff --git a/linux-user/syscall.h b/linux-user/syscall.h
index 7b197840f5..cf9f3e5e55 100644
--- a/linux-user/syscall.h
+++ b/linux-user/syscall.h
@@ -59,6 +59,7 @@ typedef enum {
     ARG_ATDIRFD,
     ARG_SIGNAL,
     ARG_LSEEKWHENCE,
+    ARG_SIGPROCMASKHOW,
 
     /* These print as sets of flags.  */
     ARG_ACCESSFLAG,
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 83dd755c73..886663af2e 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -102,6 +102,27 @@ add_signal(char *buf, int size, int sig)
     }
 }
 
+static int
+add_sigprocmaskhow(char *buf, int size, int how)
+{
+    const char *str;
+
+    switch (how) {
+    case TARGET_SIG_BLOCK:
+        str = "SIG_BLOCK";
+        break;
+    case TARGET_SIG_UNBLOCK:
+        str = "SIG_UNBLOCK";
+        break;
+    case TARGET_SIG_SETMASK:
+        str = "SIG_SETMASK";
+        break;
+    default:
+        return snprintf(buf, size, "%d", how);
+    }
+    return snprintf(buf, size, "%s", str);
+}
+
 static void
 print_signal(abi_ulong arg, int last)
 {
@@ -1564,26 +1585,6 @@ print_fstat(const struct syscallname *name,
 #define print_fstat64     print_fstat
 #endif
 
-#ifdef TARGET_NR_rt_sigprocmask
-static void
-print_rt_sigprocmask(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    const char *how = "UNKNOWN";
-    print_syscall_prologue(name);
-    switch(arg0) {
-    case TARGET_SIG_BLOCK: how = "SIG_BLOCK"; break;
-    case TARGET_SIG_UNBLOCK: how = "SIG_UNBLOCK"; break;
-    case TARGET_SIG_SETMASK: how = "SIG_SETMASK"; break;
-    }
-    gemu_log("%s,",how);
-    print_pointer(arg1, 0);
-    print_pointer(arg2, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_rt_sigqueueinfo
 static void
 print_rt_sigqueueinfo(const struct syscallname *name,
@@ -2015,6 +2016,9 @@ static void print_syscall_def1(const SyscallDef *def, int64_t args[6])
         case ARG_SIGNAL:
             len = add_signal(b, rest, arg);
             break;
+        case ARG_SIGPROCMASKHOW:
+            len = add_sigprocmaskhow(b, rest, arg);
+            break;
         case ARG_ACCESSFLAG:
             len = add_flags(b, rest, access_flags, arg, false);
             break;
diff --git a/linux-user/syscall-sig.inc.c b/linux-user/syscall-sig.inc.c
index f50ed16b74..8a6518bdaa 100644
--- a/linux-user/syscall-sig.inc.c
+++ b/linux-user/syscall-sig.inc.c
@@ -117,6 +117,53 @@ SYSCALL_IMPL(rt_sigaction)
     return ret;
 }
 
+SYSCALL_IMPL(rt_sigprocmask)
+{
+    int how = 0;
+    sigset_t set, oldset, *set_ptr = NULL;
+    abi_long ret;
+    void *p;
+
+    if (arg4 != sizeof(target_sigset_t)) {
+        return -TARGET_EINVAL;
+    }
+
+    if (arg2) {
+        switch (arg1) {
+        case TARGET_SIG_BLOCK:
+            how = SIG_BLOCK;
+            break;
+        case TARGET_SIG_UNBLOCK:
+            how = SIG_UNBLOCK;
+            break;
+        case TARGET_SIG_SETMASK:
+            how = SIG_SETMASK;
+            break;
+        default:
+            return -TARGET_EINVAL;
+        }
+        p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
+        if (!p) {
+            return -TARGET_EFAULT;
+        }
+        target_to_host_sigset(&set, p);
+        unlock_user(p, arg2, 0);
+        set_ptr = &set;
+    }
+
+    ret = do_sigprocmask(how, set_ptr, &oldset);
+
+    if (!is_error(ret) && arg3) {
+        p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0);
+        if (!p) {
+            return -TARGET_EFAULT;
+        }
+        host_to_target_sigset(p, &oldset);
+        unlock_user(p, arg3, sizeof(target_sigset_t));
+    }
+    return ret;
+}
+
 #ifdef TARGET_NR_sigaction
 SYSCALL_IMPL(sigaction)
 {
@@ -212,6 +259,82 @@ SYSCALL_IMPL(sigaction)
 }
 #endif
 
+#ifdef TARGET_NR_sigprocmask
+SYSCALL_IMPL(sigprocmask)
+{
+#if defined(TARGET_ALPHA)
+    sigset_t set, oldset;
+    abi_ulong mask;
+    int how;
+    abi_long ret;
+
+    switch (arg1) {
+    case TARGET_SIG_BLOCK:
+        how = SIG_BLOCK;
+        break;
+    case TARGET_SIG_UNBLOCK:
+        how = SIG_UNBLOCK;
+        break;
+    case TARGET_SIG_SETMASK:
+        how = SIG_SETMASK;
+        break;
+    default:
+        return -TARGET_EINVAL;
+    }
+    mask = arg2;
+    target_to_host_old_sigset(&set, &mask);
+
+    ret = do_sigprocmask(how, &set, &oldset);
+
+    if (!is_error(ret)) {
+        host_to_target_old_sigset(&mask, &oldset);
+        ret = mask;
+        ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; /* force no error */
+    }
+#else
+    sigset_t set, oldset, *set_ptr = NULL;
+    int how = 0;
+    abi_long ret;
+    void *p;
+
+    if (arg2) {
+        switch (arg1) {
+        case TARGET_SIG_BLOCK:
+            how = SIG_BLOCK;
+            break;
+        case TARGET_SIG_UNBLOCK:
+            how = SIG_UNBLOCK;
+            break;
+        case TARGET_SIG_SETMASK:
+            how = SIG_SETMASK;
+            break;
+        default:
+            return -TARGET_EINVAL;
+        }
+        p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
+        if (!p) {
+            return -TARGET_EFAULT;
+        }
+        target_to_host_old_sigset(&set, p);
+        unlock_user(p, arg2, 0);
+        set_ptr = &set;
+    }
+
+    ret = do_sigprocmask(how, set_ptr, &oldset);
+
+    if (!is_error(ret) && arg3) {
+        p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0);
+        if (!p) {
+            return -TARGET_EFAULT;
+        }
+        host_to_target_old_sigset(p, &oldset);
+        unlock_user(p, arg3, sizeof(target_sigset_t));
+    }
+#endif
+    return ret;
+}
+#endif
+
 #ifdef TARGET_NR_sgetmask
 SYSCALL_IMPL(sgetmask)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 7bd410bcf0..11bbdfade4 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4241,115 +4241,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_sigprocmask
-    case TARGET_NR_sigprocmask:
-        {
-#if defined(TARGET_ALPHA)
-            sigset_t set, oldset;
-            abi_ulong mask;
-            int how;
-
-            switch (arg1) {
-            case TARGET_SIG_BLOCK:
-                how = SIG_BLOCK;
-                break;
-            case TARGET_SIG_UNBLOCK:
-                how = SIG_UNBLOCK;
-                break;
-            case TARGET_SIG_SETMASK:
-                how = SIG_SETMASK;
-                break;
-            default:
-                return -TARGET_EINVAL;
-            }
-            mask = arg2;
-            target_to_host_old_sigset(&set, &mask);
-
-            ret = do_sigprocmask(how, &set, &oldset);
-            if (!is_error(ret)) {
-                host_to_target_old_sigset(&mask, &oldset);
-                ret = mask;
-                ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; /* force no error */
-            }
-#else
-            sigset_t set, oldset, *set_ptr;
-            int how;
-
-            if (arg2) {
-                switch (arg1) {
-                case TARGET_SIG_BLOCK:
-                    how = SIG_BLOCK;
-                    break;
-                case TARGET_SIG_UNBLOCK:
-                    how = SIG_UNBLOCK;
-                    break;
-                case TARGET_SIG_SETMASK:
-                    how = SIG_SETMASK;
-                    break;
-                default:
-                    return -TARGET_EINVAL;
-                }
-                if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
-                    return -TARGET_EFAULT;
-                target_to_host_old_sigset(&set, p);
-                unlock_user(p, arg2, 0);
-                set_ptr = &set;
-            } else {
-                how = 0;
-                set_ptr = NULL;
-            }
-            ret = do_sigprocmask(how, set_ptr, &oldset);
-            if (!is_error(ret) && arg3) {
-                if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
-                    return -TARGET_EFAULT;
-                host_to_target_old_sigset(p, &oldset);
-                unlock_user(p, arg3, sizeof(target_sigset_t));
-            }
-#endif
-        }
-        return ret;
-#endif
-    case TARGET_NR_rt_sigprocmask:
-        {
-            int how = arg1;
-            sigset_t set, oldset, *set_ptr;
-
-            if (arg4 != sizeof(target_sigset_t)) {
-                return -TARGET_EINVAL;
-            }
-
-            if (arg2) {
-                switch(how) {
-                case TARGET_SIG_BLOCK:
-                    how = SIG_BLOCK;
-                    break;
-                case TARGET_SIG_UNBLOCK:
-                    how = SIG_UNBLOCK;
-                    break;
-                case TARGET_SIG_SETMASK:
-                    how = SIG_SETMASK;
-                    break;
-                default:
-                    return -TARGET_EINVAL;
-                }
-                if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
-                    return -TARGET_EFAULT;
-                target_to_host_sigset(&set, p);
-                unlock_user(p, arg2, 0);
-                set_ptr = &set;
-            } else {
-                how = 0;
-                set_ptr = NULL;
-            }
-            ret = do_sigprocmask(how, set_ptr, &oldset);
-            if (!is_error(ret) && arg3) {
-                if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
-                    return -TARGET_EFAULT;
-                host_to_target_sigset(p, &oldset);
-                unlock_user(p, arg3, sizeof(target_sigset_t));
-            }
-        }
-        return ret;
 #ifdef TARGET_NR_sigpending
     case TARGET_NR_sigpending:
         {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 3cad68e081..7157876302 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -929,9 +929,6 @@
 #ifdef TARGET_NR_rt_sigpending
 { TARGET_NR_rt_sigpending, "rt_sigpending" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_rt_sigprocmask
-{ TARGET_NR_rt_sigprocmask, "rt_sigprocmask" , NULL, print_rt_sigprocmask, NULL },
-#endif
 #ifdef TARGET_NR_rt_sigqueueinfo
 { TARGET_NR_rt_sigqueueinfo, "rt_sigqueueinfo" , NULL, print_rt_sigqueueinfo, NULL },
 #endif
@@ -1134,9 +1131,6 @@
 #ifdef TARGET_NR_sigpending
 { TARGET_NR_sigpending, "sigpending" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_sigprocmask
-{ TARGET_NR_sigprocmask, "sigprocmask" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_sigreturn
 { TARGET_NR_sigreturn, "sigreturn" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 59/74] linux-user: Split out sigpending, rt_sigpending
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (57 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 58/74] linux-user: Split out sigprocmask, rt_sigprocmask Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 60/74] linux-user: Split out sigsuspend, rt_sigsuspend Richard Henderson
                   ` (17 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h    |  4 ++++
 linux-user/syscall-sig.inc.c | 45 ++++++++++++++++++++++++++++++++++++
 linux-user/syscall.c         | 36 -----------------------------
 linux-user/strace.list       |  6 -----
 4 files changed, 49 insertions(+), 42 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index ef77f60524..83a69246d0 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -194,6 +194,7 @@ SYSCALL_DEF(rt_sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR, ARG_PTR, ARG_DEC);
 #else
 SYSCALL_DEF(rt_sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR, ARG_DEC);
 #endif
+SYSCALL_DEF(rt_sigpending, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(rt_sigprocmask, ARG_SIGPROCMASKHOW, ARG_PTR, ARG_PTR, ARG_DEC);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semctl)
 SYSCALL_DEF(semctl, ARG_DEC, ARG_DEC, ARG_DEC, ARG_HEX);
@@ -223,6 +224,9 @@ SYSCALL_DEF(shmget, ARG_DEC, ARG_DEC, ARG_HEX);
 #ifdef TARGET_NR_sigaction
 SYSCALL_DEF(sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR);
 #endif
+#ifdef TARGET_NR_sigpending
+SYSCALL_DEF(sigpending, ARG_PTR);
+#endif
 #if defined(TARGET_ALPHA)
 SYSCALL_DEF(sigprocmask, ARG_SIGPROCMASKHOW, ARG_HEX);
 #elif defined(TARGET_NR_sigprocmask)
diff --git a/linux-user/syscall-sig.inc.c b/linux-user/syscall-sig.inc.c
index 8a6518bdaa..fe717a5121 100644
--- a/linux-user/syscall-sig.inc.c
+++ b/linux-user/syscall-sig.inc.c
@@ -117,6 +117,33 @@ SYSCALL_IMPL(rt_sigaction)
     return ret;
 }
 
+SYSCALL_IMPL(rt_sigpending)
+{
+    sigset_t set;
+    abi_long ret;
+
+    /*
+     * Yes, this check is >, not != like most. We follow the kernel's
+     * logic and it does it like this because it implements
+     * NR_sigpending through the same code path, and in that case
+     * the old_sigset_t is smaller in size.
+     */
+    if (arg2 > sizeof(target_sigset_t)) {
+        return -TARGET_EINVAL;
+    }
+
+    ret = get_errno(sigpending(&set));
+    if (!is_error(ret)) {
+        void *p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0);
+        if (!p) {
+            return -TARGET_EFAULT;
+        }
+        host_to_target_sigset(p, &set);
+        unlock_user(p, arg1, sizeof(target_sigset_t));
+    }
+    return ret;
+}
+
 SYSCALL_IMPL(rt_sigprocmask)
 {
     int how = 0;
@@ -259,6 +286,24 @@ SYSCALL_IMPL(sigaction)
 }
 #endif
 
+#ifdef TARGET_NR_sigpending
+SYSCALL_IMPL(sigpending)
+{
+    sigset_t set;
+    abi_long ret = get_errno(sigpending(&set));
+
+    if (!is_error(ret)) {
+        void *p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0);
+        if (!p) {
+            return -TARGET_EFAULT;
+        }
+        host_to_target_old_sigset(p, &set);
+        unlock_user(p, arg1, sizeof(target_sigset_t));
+    }
+    return ret;
+}
+#endif
+
 #ifdef TARGET_NR_sigprocmask
 SYSCALL_IMPL(sigprocmask)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 11bbdfade4..7dda237c95 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4241,42 +4241,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_sigpending
-    case TARGET_NR_sigpending:
-        {
-            sigset_t set;
-            ret = get_errno(sigpending(&set));
-            if (!is_error(ret)) {
-                if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
-                    return -TARGET_EFAULT;
-                host_to_target_old_sigset(p, &set);
-                unlock_user(p, arg1, sizeof(target_sigset_t));
-            }
-        }
-        return ret;
-#endif
-    case TARGET_NR_rt_sigpending:
-        {
-            sigset_t set;
-
-            /* Yes, this check is >, not != like most. We follow the kernel's
-             * logic and it does it like this because it implements
-             * NR_sigpending through the same code path, and in that case
-             * the old_sigset_t is smaller in size.
-             */
-            if (arg2 > sizeof(target_sigset_t)) {
-                return -TARGET_EINVAL;
-            }
-
-            ret = get_errno(sigpending(&set));
-            if (!is_error(ret)) {
-                if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
-                    return -TARGET_EFAULT;
-                host_to_target_sigset(p, &set);
-                unlock_user(p, arg1, sizeof(target_sigset_t));
-            }
-        }
-        return ret;
 #ifdef TARGET_NR_sigsuspend
     case TARGET_NR_sigsuspend:
         {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 7157876302..978e47bf0e 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -926,9 +926,6 @@
 #ifdef TARGET_NR_rmdir
 { TARGET_NR_rmdir, "rmdir" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_rt_sigpending
-{ TARGET_NR_rt_sigpending, "rt_sigpending" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_rt_sigqueueinfo
 { TARGET_NR_rt_sigqueueinfo, "rt_sigqueueinfo" , NULL, print_rt_sigqueueinfo, NULL },
 #endif
@@ -1128,9 +1125,6 @@
 #ifdef TARGET_NR_signalfd4
 { TARGET_NR_signalfd4, "signalfd4" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_sigpending
-{ TARGET_NR_sigpending, "sigpending" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_sigreturn
 { TARGET_NR_sigreturn, "sigreturn" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 60/74] linux-user: Split out sigsuspend, rt_sigsuspend
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (58 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 59/74] linux-user: Split out sigpending, rt_sigpending Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 61/74] linux-user: Split out rt_sigtimedwait Richard Henderson
                   ` (16 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h    |  6 +++++
 linux-user/syscall-sig.inc.c | 51 ++++++++++++++++++++++++++++++++++++
 linux-user/syscall.c         | 42 ++---------------------------
 linux-user/strace.list       |  6 -----
 4 files changed, 59 insertions(+), 46 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 83a69246d0..2b930f5599 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -196,6 +196,7 @@ SYSCALL_DEF(rt_sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR, ARG_DEC);
 #endif
 SYSCALL_DEF(rt_sigpending, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(rt_sigprocmask, ARG_SIGPROCMASKHOW, ARG_PTR, ARG_PTR, ARG_DEC);
+SYSCALL_DEF(rt_sigsuspend, ARG_PTR, ARG_DEC);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semctl)
 SYSCALL_DEF(semctl, ARG_DEC, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
@@ -232,6 +233,11 @@ SYSCALL_DEF(sigprocmask, ARG_SIGPROCMASKHOW, ARG_HEX);
 #elif defined(TARGET_NR_sigprocmask)
 SYSCALL_DEF(sigprocmask, ARG_SIGPROCMASKHOW, ARG_PTR, ARG_PTR);
 #endif
+#if defined(TARGET_ALPHA)
+SYSCALL_DEF(sigsuspend, ARG_HEX);
+#elif defined(TARGET_NR_sigsuspend)
+SYSCALL_DEF(sigsuspend, ARG_PTR);
+#endif
 #ifdef TARGET_NR_sgetmask
 SYSCALL_DEF(sgetmask);
 #endif
diff --git a/linux-user/syscall-sig.inc.c b/linux-user/syscall-sig.inc.c
index fe717a5121..23ea14e2a6 100644
--- a/linux-user/syscall-sig.inc.c
+++ b/linux-user/syscall-sig.inc.c
@@ -191,6 +191,30 @@ SYSCALL_IMPL(rt_sigprocmask)
     return ret;
 }
 
+SYSCALL_IMPL(rt_sigsuspend)
+{
+    CPUState *cpu = ENV_GET_CPU(cpu_env);
+    TaskState *ts = cpu->opaque;
+    abi_long ret;
+    void *p;
+
+    if (arg2 != sizeof(target_sigset_t)) {
+        return -TARGET_EINVAL;
+    }
+    p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    target_to_host_sigset(&ts->sigsuspend_mask, p);
+    unlock_user(p, arg1, 0);
+
+    ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask, SIGSET_T_SIZE));
+    if (ret != -TARGET_ERESTARTSYS) {
+        ts->in_sigsuspend = 1;
+    }
+    return ret;
+}
+
 #ifdef TARGET_NR_sigaction
 SYSCALL_IMPL(sigaction)
 {
@@ -380,6 +404,33 @@ SYSCALL_IMPL(sigprocmask)
 }
 #endif
 
+#ifdef TARGET_NR_sigsuspend
+SYSCALL_IMPL(sigsuspend)
+{
+    CPUState *cpu = ENV_GET_CPU(cpu_env);
+    TaskState *ts = cpu->opaque;
+    abi_long ret;
+
+#if defined(TARGET_ALPHA)
+    abi_ulong mask = arg1;
+    target_to_host_old_sigset(&ts->sigsuspend_mask, &mask);
+#else
+    void *p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    target_to_host_old_sigset(&ts->sigsuspend_mask, p);
+    unlock_user(p, arg1, 0);
+#endif
+
+    ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask, SIGSET_T_SIZE));
+    if (ret != -TARGET_ERESTARTSYS) {
+        ts->in_sigsuspend = 1;
+    }
+    return ret;
+}
+#endif
+
 #ifdef TARGET_NR_sgetmask
 SYSCALL_IMPL(sgetmask)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 7dda237c95..00f4ba8753 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4227,7 +4227,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
                             abi_long arg5, abi_long arg6, abi_long arg7,
                             abi_long arg8)
 {
-    CPUState *cpu = ENV_GET_CPU(cpu_env);
     abi_long ret;
 #if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) \
     || defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) \
@@ -4241,45 +4240,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_sigsuspend
-    case TARGET_NR_sigsuspend:
-        {
-            TaskState *ts = cpu->opaque;
-#if defined(TARGET_ALPHA)
-            abi_ulong mask = arg1;
-            target_to_host_old_sigset(&ts->sigsuspend_mask, &mask);
-#else
-            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
-                return -TARGET_EFAULT;
-            target_to_host_old_sigset(&ts->sigsuspend_mask, p);
-            unlock_user(p, arg1, 0);
-#endif
-            ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
-                                               SIGSET_T_SIZE));
-            if (ret != -TARGET_ERESTARTSYS) {
-                ts->in_sigsuspend = 1;
-            }
-        }
-        return ret;
-#endif
-    case TARGET_NR_rt_sigsuspend:
-        {
-            TaskState *ts = cpu->opaque;
-
-            if (arg2 != sizeof(target_sigset_t)) {
-                return -TARGET_EINVAL;
-            }
-            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
-                return -TARGET_EFAULT;
-            target_to_host_sigset(&ts->sigsuspend_mask, p);
-            unlock_user(p, arg1, 0);
-            ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
-                                               SIGSET_T_SIZE));
-            if (ret != -TARGET_ERESTARTSYS) {
-                ts->in_sigsuspend = 1;
-            }
-        }
-        return ret;
     case TARGET_NR_rt_sigtimedwait:
         {
             sigset_t set;
@@ -6659,6 +6619,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
       return do_set_thread_area(cpu_env, arg1);
 #elif defined(TARGET_M68K)
       {
+          CPUState *cpu = ENV_GET_CPU(cpu_env);
           TaskState *ts = cpu->opaque;
           ts->tp_value = arg1;
           return 0;
@@ -6673,6 +6634,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         return do_get_thread_area(cpu_env, arg1);
 #elif defined(TARGET_M68K)
         {
+            CPUState *cpu = ENV_GET_CPU(cpu_env);
             TaskState *ts = cpu->opaque;
             return ts->tp_value;
         }
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 978e47bf0e..26df8b25cd 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -932,9 +932,6 @@
 #ifdef TARGET_NR_rt_sigreturn
 { TARGET_NR_rt_sigreturn, "rt_sigreturn" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_rt_sigsuspend
-{ TARGET_NR_rt_sigsuspend, "rt_sigsuspend" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_rt_sigtimedwait
 { TARGET_NR_rt_sigtimedwait, "rt_sigtimedwait" , NULL, NULL, NULL },
 #endif
@@ -1128,9 +1125,6 @@
 #ifdef TARGET_NR_sigreturn
 { TARGET_NR_sigreturn, "sigreturn" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_sigsuspend
-{ TARGET_NR_sigsuspend, "sigsuspend" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_socket
 { TARGET_NR_socket, "socket" , NULL, print_socket, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 61/74] linux-user: Split out rt_sigtimedwait
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (59 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 60/74] linux-user: Split out sigsuspend, rt_sigsuspend Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 62/74] linux-user: Split out rt_sigqueueinfo, rt_tgsigqueueinfo Richard Henderson
                   ` (15 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h    |  1 +
 linux-user/syscall-sig.inc.c | 37 ++++++++++++++++++++++++++++++++++++
 linux-user/syscall.c         | 36 -----------------------------------
 linux-user/strace.list       |  3 ---
 4 files changed, 38 insertions(+), 39 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 2b930f5599..24289ed413 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -197,6 +197,7 @@ SYSCALL_DEF(rt_sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(rt_sigpending, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(rt_sigprocmask, ARG_SIGPROCMASKHOW, ARG_PTR, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(rt_sigsuspend, ARG_PTR, ARG_DEC);
+SYSCALL_DEF(rt_sigtimedwait, ARG_PTR, ARG_PTR, ARG_PTR, ARG_DEC);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semctl)
 SYSCALL_DEF(semctl, ARG_DEC, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
diff --git a/linux-user/syscall-sig.inc.c b/linux-user/syscall-sig.inc.c
index 23ea14e2a6..5f2c0ba499 100644
--- a/linux-user/syscall-sig.inc.c
+++ b/linux-user/syscall-sig.inc.c
@@ -215,6 +215,43 @@ SYSCALL_IMPL(rt_sigsuspend)
     return ret;
 }
 
+SYSCALL_IMPL(rt_sigtimedwait)
+{
+    sigset_t set;
+    struct timespec uts, *puts = NULL;
+    siginfo_t uinfo;
+    abi_long ret;
+    void *p;
+
+    if (arg4 != sizeof(target_sigset_t)) {
+        return -TARGET_EINVAL;
+    }
+    p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    target_to_host_sigset(&set, p);
+    unlock_user(p, arg1, 0);
+    if (arg3) {
+        puts = &uts;
+        target_to_host_timespec(puts, arg3);
+    }
+
+    ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts, SIGSET_T_SIZE));
+    if (!is_error(ret)) {
+        if (arg2) {
+            p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0);
+            if (!p) {
+                return -TARGET_EFAULT;
+            }
+            host_to_target_siginfo(p, &uinfo);
+            unlock_user(p, arg2, sizeof(target_siginfo_t));
+        }
+        ret = host_to_target_signal(ret);
+    }
+    return ret;
+}
+
 #ifdef TARGET_NR_sigaction
 SYSCALL_IMPL(sigaction)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 00f4ba8753..8a05d3e32a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4240,42 +4240,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_rt_sigtimedwait:
-        {
-            sigset_t set;
-            struct timespec uts, *puts;
-            siginfo_t uinfo;
-
-            if (arg4 != sizeof(target_sigset_t)) {
-                return -TARGET_EINVAL;
-            }
-
-            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
-                return -TARGET_EFAULT;
-            target_to_host_sigset(&set, p);
-            unlock_user(p, arg1, 0);
-            if (arg3) {
-                puts = &uts;
-                target_to_host_timespec(puts, arg3);
-            } else {
-                puts = NULL;
-            }
-            ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
-                                                 SIGSET_T_SIZE));
-            if (!is_error(ret)) {
-                if (arg2) {
-                    p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
-                                  0);
-                    if (!p) {
-                        return -TARGET_EFAULT;
-                    }
-                    host_to_target_siginfo(p, &uinfo);
-                    unlock_user(p, arg2, sizeof(target_siginfo_t));
-                }
-                ret = host_to_target_signal(ret);
-            }
-        }
-        return ret;
     case TARGET_NR_rt_sigqueueinfo:
         {
             siginfo_t uinfo;
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 26df8b25cd..0b2c057673 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -932,9 +932,6 @@
 #ifdef TARGET_NR_rt_sigreturn
 { TARGET_NR_rt_sigreturn, "rt_sigreturn" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_rt_sigtimedwait
-{ TARGET_NR_rt_sigtimedwait, "rt_sigtimedwait" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_rt_tgsigqueueinfo
 { TARGET_NR_rt_tgsigqueueinfo, "rt_tgsigqueueinfo" , NULL, print_rt_tgsigqueueinfo, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 62/74] linux-user: Split out rt_sigqueueinfo, rt_tgsigqueueinfo
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (60 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 61/74] linux-user: Split out rt_sigtimedwait Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-20  6:04   ` Aleksandar Markovic
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 63/74] linux-user: Split out sigreturn, rt_sigreturn Richard Henderson
                   ` (14 subsequent siblings)
  76 siblings, 1 reply; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

This does drop the (questionable) siginfo_t printing.
But since we already do not handle more important things
in this area like sigset_t, this does not feel a loss.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h    |   2 +
 linux-user/strace.c          | 138 -----------------------------------
 linux-user/syscall-sig.inc.c |  30 ++++++++
 linux-user/syscall.c         |  26 -------
 linux-user/strace.list       |   6 --
 5 files changed, 32 insertions(+), 170 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 24289ed413..11851535e1 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -196,8 +196,10 @@ SYSCALL_DEF(rt_sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR, ARG_DEC);
 #endif
 SYSCALL_DEF(rt_sigpending, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(rt_sigprocmask, ARG_SIGPROCMASKHOW, ARG_PTR, ARG_PTR, ARG_DEC);
+SYSCALL_DEF(rt_sigqueueinfo, ARG_DEC, ARG_SIGNAL, ARG_PTR);
 SYSCALL_DEF(rt_sigsuspend, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(rt_sigtimedwait, ARG_PTR, ARG_PTR, ARG_PTR, ARG_DEC);
+SYSCALL_DEF(rt_tgsigqueueinfo, ARG_DEC, ARG_DEC, ARG_SIGNAL, ARG_PTR);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semctl)
 SYSCALL_DEF(semctl, ARG_DEC, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 886663af2e..2e70a3910c 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -167,93 +167,6 @@ static void print_si_code(int arg)
     gemu_log("%s", codename);
 }
 
-static void get_target_siginfo(target_siginfo_t *tinfo,
-                                const target_siginfo_t *info)
-{
-    abi_ulong sival_ptr;
-
-    int sig;
-    int si_errno;
-    int si_code;
-    int si_type;
-
-    __get_user(sig, &info->si_signo);
-    __get_user(si_errno, &tinfo->si_errno);
-    __get_user(si_code, &info->si_code);
-
-    tinfo->si_signo = sig;
-    tinfo->si_errno = si_errno;
-    tinfo->si_code = si_code;
-
-    /* Ensure we don't leak random junk to the guest later */
-    memset(tinfo->_sifields._pad, 0, sizeof(tinfo->_sifields._pad));
-
-    /* This is awkward, because we have to use a combination of
-     * the si_code and si_signo to figure out which of the union's
-     * members are valid. (Within the host kernel it is always possible
-     * to tell, but the kernel carefully avoids giving userspace the
-     * high 16 bits of si_code, so we don't have the information to
-     * do this the easy way...) We therefore make our best guess,
-     * bearing in mind that a guest can spoof most of the si_codes
-     * via rt_sigqueueinfo() if it likes.
-     *
-     * Once we have made our guess, we record it in the top 16 bits of
-     * the si_code, so that print_siginfo() later can use it.
-     * print_siginfo() will strip these top bits out before printing
-     * the si_code.
-     */
-
-    switch (si_code) {
-    case SI_USER:
-    case SI_TKILL:
-    case SI_KERNEL:
-        /* Sent via kill(), tkill() or tgkill(), or direct from the kernel.
-         * These are the only unspoofable si_code values.
-         */
-        __get_user(tinfo->_sifields._kill._pid, &info->_sifields._kill._pid);
-        __get_user(tinfo->_sifields._kill._uid, &info->_sifields._kill._uid);
-        si_type = QEMU_SI_KILL;
-        break;
-    default:
-        /* Everything else is spoofable. Make best guess based on signal */
-        switch (sig) {
-        case TARGET_SIGCHLD:
-            __get_user(tinfo->_sifields._sigchld._pid,
-                       &info->_sifields._sigchld._pid);
-            __get_user(tinfo->_sifields._sigchld._uid,
-                       &info->_sifields._sigchld._uid);
-            __get_user(tinfo->_sifields._sigchld._status,
-                       &info->_sifields._sigchld._status);
-            __get_user(tinfo->_sifields._sigchld._utime,
-                       &info->_sifields._sigchld._utime);
-            __get_user(tinfo->_sifields._sigchld._stime,
-                       &info->_sifields._sigchld._stime);
-            si_type = QEMU_SI_CHLD;
-            break;
-        case TARGET_SIGIO:
-            __get_user(tinfo->_sifields._sigpoll._band,
-                       &info->_sifields._sigpoll._band);
-            __get_user(tinfo->_sifields._sigpoll._fd,
-                       &info->_sifields._sigpoll._fd);
-            si_type = QEMU_SI_POLL;
-            break;
-        default:
-            /* Assume a sigqueue()/mq_notify()/rt_sigqueueinfo() source. */
-            __get_user(tinfo->_sifields._rt._pid, &info->_sifields._rt._pid);
-            __get_user(tinfo->_sifields._rt._uid, &info->_sifields._rt._uid);
-            /* XXX: potential problem if 64 bit */
-            __get_user(sival_ptr, &info->_sifields._rt._sigval.sival_ptr);
-            tinfo->_sifields._rt._sigval.sival_ptr = sival_ptr;
-
-            si_type = QEMU_SI_RT;
-            break;
-        }
-        break;
-    }
-
-    tinfo->si_code = deposit32(si_code, 16, 16, si_type);
-}
-
 static void print_siginfo(const target_siginfo_t *tinfo)
 {
     /* Print a target_siginfo_t in the format desired for printing
@@ -1585,57 +1498,6 @@ print_fstat(const struct syscallname *name,
 #define print_fstat64     print_fstat
 #endif
 
-#ifdef TARGET_NR_rt_sigqueueinfo
-static void
-print_rt_sigqueueinfo(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    void *p;
-    target_siginfo_t uinfo;
-
-    print_syscall_prologue(name);
-    print_raw_param("%d", arg0, 0);
-    print_signal(arg1, 0);
-    p = lock_user(VERIFY_READ, arg2, sizeof(target_siginfo_t), 1);
-    if (p) {
-        get_target_siginfo(&uinfo, p);
-        print_siginfo(&uinfo);
-
-        unlock_user(p, arg2, 0);
-    } else {
-        print_pointer(arg2, 1);
-    }
-    print_syscall_epilogue(name);
-}
-#endif
-
-#ifdef TARGET_NR_rt_tgsigqueueinfo
-static void
-print_rt_tgsigqueueinfo(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    void *p;
-    target_siginfo_t uinfo;
-
-    print_syscall_prologue(name);
-    print_raw_param("%d", arg0, 0);
-    print_raw_param("%d", arg1, 0);
-    print_signal(arg2, 0);
-    p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
-    if (p) {
-        get_target_siginfo(&uinfo, p);
-        print_siginfo(&uinfo);
-
-        unlock_user(p, arg3, 0);
-    } else {
-        print_pointer(arg3, 1);
-    }
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_syslog
 static void
 print_syslog_action(abi_ulong arg, int last)
diff --git a/linux-user/syscall-sig.inc.c b/linux-user/syscall-sig.inc.c
index 5f2c0ba499..774346838b 100644
--- a/linux-user/syscall-sig.inc.c
+++ b/linux-user/syscall-sig.inc.c
@@ -191,6 +191,21 @@ SYSCALL_IMPL(rt_sigprocmask)
     return ret;
 }
 
+SYSCALL_IMPL(rt_sigqueueinfo)
+{
+    siginfo_t uinfo;
+    void *p;
+
+    p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    target_to_host_siginfo(&uinfo, p);
+    unlock_user(p, arg3, 0);
+
+    return get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
+}
+
 SYSCALL_IMPL(rt_sigsuspend)
 {
     CPUState *cpu = ENV_GET_CPU(cpu_env);
@@ -252,6 +267,21 @@ SYSCALL_IMPL(rt_sigtimedwait)
     return ret;
 }
 
+SYSCALL_IMPL(rt_tgsigqueueinfo)
+{
+    siginfo_t uinfo;
+    void *p;
+
+    p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    target_to_host_siginfo(&uinfo, p);
+    unlock_user(p, arg4, 0);
+
+    return get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo));
+}
+
 #ifdef TARGET_NR_sigaction
 SYSCALL_IMPL(sigaction)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 8a05d3e32a..e489d12103 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4240,32 +4240,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_rt_sigqueueinfo:
-        {
-            siginfo_t uinfo;
-
-            p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
-            if (!p) {
-                return -TARGET_EFAULT;
-            }
-            target_to_host_siginfo(&uinfo, p);
-            unlock_user(p, arg3, 0);
-            ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
-        }
-        return ret;
-    case TARGET_NR_rt_tgsigqueueinfo:
-        {
-            siginfo_t uinfo;
-
-            p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
-            if (!p) {
-                return -TARGET_EFAULT;
-            }
-            target_to_host_siginfo(&uinfo, p);
-            unlock_user(p, arg4, 0);
-            ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo));
-        }
-        return ret;
 #ifdef TARGET_NR_sigreturn
     case TARGET_NR_sigreturn:
         if (block_signals()) {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 0b2c057673..57445a8d81 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -926,15 +926,9 @@
 #ifdef TARGET_NR_rmdir
 { TARGET_NR_rmdir, "rmdir" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_rt_sigqueueinfo
-{ TARGET_NR_rt_sigqueueinfo, "rt_sigqueueinfo" , NULL, print_rt_sigqueueinfo, NULL },
-#endif
 #ifdef TARGET_NR_rt_sigreturn
 { TARGET_NR_rt_sigreturn, "rt_sigreturn" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_rt_tgsigqueueinfo
-{ TARGET_NR_rt_tgsigqueueinfo, "rt_tgsigqueueinfo" , NULL, print_rt_tgsigqueueinfo, NULL },
-#endif
 #ifdef TARGET_NR_sched_getaffinity
 { TARGET_NR_sched_getaffinity, "sched_getaffinity" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 63/74] linux-user: Split out sigreturn, rt_sigreturn
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (61 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 62/74] linux-user: Split out rt_sigqueueinfo, rt_tgsigqueueinfo Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 64/74] linux-user: Split out gethostname, sethostname Richard Henderson
                   ` (13 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h    |  4 ++++
 linux-user/syscall-sig.inc.c | 18 ++++++++++++++++++
 linux-user/syscall.c         | 12 ------------
 linux-user/strace.list       |  6 ------
 4 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 11851535e1..77d750f66f 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -197,6 +197,7 @@ SYSCALL_DEF(rt_sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(rt_sigpending, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(rt_sigprocmask, ARG_SIGPROCMASKHOW, ARG_PTR, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(rt_sigqueueinfo, ARG_DEC, ARG_SIGNAL, ARG_PTR);
+SYSCALL_DEF(rt_sigreturn);
 SYSCALL_DEF(rt_sigsuspend, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(rt_sigtimedwait, ARG_PTR, ARG_PTR, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(rt_tgsigqueueinfo, ARG_DEC, ARG_DEC, ARG_SIGNAL, ARG_PTR);
@@ -236,6 +237,9 @@ SYSCALL_DEF(sigprocmask, ARG_SIGPROCMASKHOW, ARG_HEX);
 #elif defined(TARGET_NR_sigprocmask)
 SYSCALL_DEF(sigprocmask, ARG_SIGPROCMASKHOW, ARG_PTR, ARG_PTR);
 #endif
+#ifdef TARGET_NR_sigreturn
+SYSCALL_DEF(sigreturn);
+#endif
 #if defined(TARGET_ALPHA)
 SYSCALL_DEF(sigsuspend, ARG_HEX);
 #elif defined(TARGET_NR_sigsuspend)
diff --git a/linux-user/syscall-sig.inc.c b/linux-user/syscall-sig.inc.c
index 774346838b..d5c0ccdcc3 100644
--- a/linux-user/syscall-sig.inc.c
+++ b/linux-user/syscall-sig.inc.c
@@ -206,6 +206,14 @@ SYSCALL_IMPL(rt_sigqueueinfo)
     return get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
 }
 
+SYSCALL_IMPL(rt_sigreturn)
+{
+    if (block_signals()) {
+        return -TARGET_ERESTARTSYS;
+    }
+    return do_rt_sigreturn(cpu_env);
+}
+
 SYSCALL_IMPL(rt_sigsuspend)
 {
     CPUState *cpu = ENV_GET_CPU(cpu_env);
@@ -471,6 +479,16 @@ SYSCALL_IMPL(sigprocmask)
 }
 #endif
 
+#ifdef TARGET_NR_sigreturn
+SYSCALL_IMPL(sigreturn)
+{
+    if (block_signals()) {
+        return -TARGET_ERESTARTSYS;
+    }
+    return do_sigreturn(cpu_env);
+}
+#endif
+
 #ifdef TARGET_NR_sigsuspend
 SYSCALL_IMPL(sigsuspend)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index e489d12103..b8b18ac1de 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4240,18 +4240,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_sigreturn
-    case TARGET_NR_sigreturn:
-        if (block_signals()) {
-            return -TARGET_ERESTARTSYS;
-        }
-        return do_sigreturn(cpu_env);
-#endif
-    case TARGET_NR_rt_sigreturn:
-        if (block_signals()) {
-            return -TARGET_ERESTARTSYS;
-        }
-        return do_rt_sigreturn(cpu_env);
     case TARGET_NR_sethostname:
         if (!(p = lock_user_string(arg1)))
             return -TARGET_EFAULT;
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 57445a8d81..b1c2f7851e 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -926,9 +926,6 @@
 #ifdef TARGET_NR_rmdir
 { TARGET_NR_rmdir, "rmdir" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_rt_sigreturn
-{ TARGET_NR_rt_sigreturn, "rt_sigreturn" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_sched_getaffinity
 { TARGET_NR_sched_getaffinity, "sched_getaffinity" , NULL, NULL, NULL },
 #endif
@@ -1113,9 +1110,6 @@
 #ifdef TARGET_NR_signalfd4
 { TARGET_NR_signalfd4, "signalfd4" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_sigreturn
-{ TARGET_NR_sigreturn, "sigreturn" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_socket
 { TARGET_NR_socket, "socket" , NULL, print_socket, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 64/74] linux-user: Split out gethostname, sethostname
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (62 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 63/74] linux-user: Split out sigreturn, rt_sigreturn Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 65/74] linux-user: Split out getrlimit, setrlimit Richard Henderson
                   ` (12 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  4 ++++
 linux-user/syscall-proc.inc.c | 28 ++++++++++++++++++++++++++++
 linux-user/syscall.c          | 19 -------------------
 linux-user/strace.list        |  6 ------
 4 files changed, 32 insertions(+), 25 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 77d750f66f..3ba697fd53 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -59,6 +59,9 @@ SYSCALL_DEF(futimesat, ARG_ATDIRFD, ARG_STR, ARG_PTR);
 #ifdef TARGET_NR_fork
 SYSCALL_DEF(fork);
 #endif
+#ifdef TARGET_NR_gethostname
+SYSCALL_DEF(gethostname, ARG_PTR, ARG_DEC);
+#endif
 SYSCALL_DEF(getpgid, ARG_DEC);
 #ifdef TARGET_NR_getpgrp
 SYSCALL_DEF(getpgrp);
@@ -207,6 +210,7 @@ SYSCALL_DEF(semctl, ARG_DEC, ARG_DEC, ARG_DEC, ARG_HEX);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semget)
 SYSCALL_DEF(semget, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
+SYSCALL_DEF(sethostname, ARG_STR);
 SYSCALL_DEF(setpgid, ARG_DEC, ARG_DEC);
 SYSCALL_DEF(setsid);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semop)
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
index 567df54581..b1a801fb62 100644
--- a/linux-user/syscall-proc.inc.c
+++ b/linux-user/syscall-proc.inc.c
@@ -438,6 +438,21 @@ SYSCALL_IMPL(fork)
 }
 #endif
 
+#ifdef TARGET_NR_gethostname
+SYSCALL_IMPL(gethostname)
+{
+    char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
+    abi_long ret;
+    
+    if (!name) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(gethostname(name, arg2));
+    unlock_user(name, arg1, arg2);
+    return ret;
+}
+#endif
+
 SYSCALL_IMPL(getpgid)
 {
     return get_errno(getpgid(arg1));
@@ -485,6 +500,19 @@ SYSCALL_IMPL(nice)
 }
 #endif
 
+SYSCALL_IMPL(sethostname)
+{
+    void *p = lock_user_string(arg1);
+    abi_long ret;
+
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(sethostname(p, arg2));
+    unlock_user(p, arg1, 0);
+    return ret;
+}
+
 SYSCALL_IMPL(setpgid)
 {
     return get_errno(setpgid(arg1, arg2));
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index b8b18ac1de..6dd4196647 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4240,12 +4240,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_sethostname:
-        if (!(p = lock_user_string(arg1)))
-            return -TARGET_EFAULT;
-        ret = get_errno(sethostname(p, arg2));
-        unlock_user(p, arg1, 0);
-        return ret;
 #ifdef TARGET_NR_setrlimit
     case TARGET_NR_setrlimit:
         {
@@ -7078,19 +7072,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         return ret;
     }
 #endif
-#ifdef TARGET_NR_gethostname
-    case TARGET_NR_gethostname:
-    {
-        char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
-        if (name) {
-            ret = get_errno(gethostname(name, arg2));
-            unlock_user(name, arg1, arg2);
-        } else {
-            ret = -TARGET_EFAULT;
-        }
-        return ret;
-    }
-#endif
 #ifdef TARGET_NR_atomic_cmpxchg_32
     case TARGET_NR_atomic_cmpxchg_32:
     {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index b1c2f7851e..361ceec853 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -244,9 +244,6 @@
 #ifdef TARGET_NR_getgroups32
 { TARGET_NR_getgroups32, "getgroups32" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_gethostname
-{ TARGET_NR_gethostname, "gethostname" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_getitimer
 { TARGET_NR_getitimer, "getitimer" , NULL, NULL, NULL },
 #endif
@@ -1025,9 +1022,6 @@
 #ifdef TARGET_NR_sethae
 { TARGET_NR_sethae, "sethae" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_sethostname
-{ TARGET_NR_sethostname, "sethostname" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_setitimer
 { TARGET_NR_setitimer, "setitimer" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 65/74] linux-user: Split out getrlimit, setrlimit
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (63 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 64/74] linux-user: Split out gethostname, sethostname Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 66/74] linux-user: Split out getrusage Richard Henderson
                   ` (11 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  6 ++++
 linux-user/syscall-proc.inc.c | 52 +++++++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 46 -------------------------------
 linux-user/strace.list        |  6 ----
 4 files changed, 58 insertions(+), 52 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 3ba697fd53..34426a2e23 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -72,6 +72,9 @@ SYSCALL_DEF(getpid);
 #ifdef TARGET_NR_getppid
 SYSCALL_DEF(getppid);
 #endif
+#ifdef TARGET_NR_getrlimit
+SYSCALL_DEF(getrlimit, ARG_DEC, ARG_PTR);
+#endif
 SYSCALL_DEF(getsid, ARG_DEC);
 #ifdef TARGET_NR_getxpid
 SYSCALL_DEF(getxpid);
@@ -212,6 +215,9 @@ SYSCALL_DEF(semget, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
 SYSCALL_DEF(sethostname, ARG_STR);
 SYSCALL_DEF(setpgid, ARG_DEC, ARG_DEC);
+#ifdef TARGET_NR_setrlimit
+SYSCALL_DEF(setrlimit, ARG_DEC, ARG_PTR);
+#endif
 SYSCALL_DEF(setsid);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semop)
 SYSCALL_DEF(semop, ARG_DEC, ARG_PTR, ARG_DEC);
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
index b1a801fb62..1238b08191 100644
--- a/linux-user/syscall-proc.inc.c
+++ b/linux-user/syscall-proc.inc.c
@@ -479,6 +479,26 @@ SYSCALL_IMPL(getppid)
 }
 #endif
 
+#ifdef TARGET_NR_getrlimit
+SYSCALL_IMPL(getrlimit)
+{
+    int resource = target_to_host_resource(arg1);
+    struct target_rlimit *target_rlim;
+    struct rlimit rlim;
+    abi_long ret;
+
+    ret = get_errno(getrlimit(resource, &rlim));
+    if (!is_error(ret)) {
+        if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0)) {
+            return -TARGET_EFAULT;
+        }
+        target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
+        target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
+        unlock_user_struct(target_rlim, arg2, 1);
+    }
+    return ret;
+}
+#endif
 SYSCALL_IMPL(getsid)
 {
     return get_errno(getsid(arg1));
@@ -518,6 +538,38 @@ SYSCALL_IMPL(setpgid)
     return get_errno(setpgid(arg1, arg2));
 }
 
+#ifdef TARGET_NR_setrlimit
+SYSCALL_IMPL(setrlimit)
+{
+    int resource = target_to_host_resource(arg1);
+    struct target_rlimit *target_rlim;
+    struct rlimit rlim;
+
+    if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1)) {
+        return -TARGET_EFAULT;
+    }
+    rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
+    rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
+    unlock_user_struct(target_rlim, arg2, 0);
+
+    /*
+     * If we just passed through resource limit settings for memory then
+     * they would also apply to QEMU's own allocations, and QEMU will
+     * crash or hang or die if its allocations fail. Ideally we would
+     * track the guest allocations in QEMU and apply the limits ourselves.
+     * For now, just tell the guest the call succeeded but don't actually
+     * limit anything.
+     */
+    if (resource != RLIMIT_AS &&
+        resource != RLIMIT_DATA &&
+        resource != RLIMIT_STACK) {
+        return get_errno(setrlimit(resource, &rlim));
+    } else {
+        return 0;
+    }
+}
+#endif
+
 SYSCALL_IMPL(setsid)
 {
     return get_errno(setsid());
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 6dd4196647..401450b0e3 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4240,52 +4240,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_setrlimit
-    case TARGET_NR_setrlimit:
-        {
-            int resource = target_to_host_resource(arg1);
-            struct target_rlimit *target_rlim;
-            struct rlimit rlim;
-            if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
-                return -TARGET_EFAULT;
-            rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
-            rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
-            unlock_user_struct(target_rlim, arg2, 0);
-            /*
-             * If we just passed through resource limit settings for memory then
-             * they would also apply to QEMU's own allocations, and QEMU will
-             * crash or hang or die if its allocations fail. Ideally we would
-             * track the guest allocations in QEMU and apply the limits ourselves.
-             * For now, just tell the guest the call succeeded but don't actually
-             * limit anything.
-             */
-            if (resource != RLIMIT_AS &&
-                resource != RLIMIT_DATA &&
-                resource != RLIMIT_STACK) {
-                return get_errno(setrlimit(resource, &rlim));
-            } else {
-                return 0;
-            }
-        }
-#endif
-#ifdef TARGET_NR_getrlimit
-    case TARGET_NR_getrlimit:
-        {
-            int resource = target_to_host_resource(arg1);
-            struct target_rlimit *target_rlim;
-            struct rlimit rlim;
-
-            ret = get_errno(getrlimit(resource, &rlim));
-            if (!is_error(ret)) {
-                if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
-                    return -TARGET_EFAULT;
-                target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
-                target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
-                unlock_user_struct(target_rlim, arg2, 1);
-            }
-        }
-        return ret;
-#endif
     case TARGET_NR_getrusage:
         {
             struct rusage rusage;
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 361ceec853..711ad9c0aa 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -280,9 +280,6 @@
 #ifdef TARGET_NR_getresuid32
 { TARGET_NR_getresuid32, "getresuid32" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_getrlimit
-{ TARGET_NR_getrlimit, "getrlimit" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_get_robust_list
 { TARGET_NR_get_robust_list, "get_robust_list" , NULL, NULL, NULL },
 #endif
@@ -1061,9 +1058,6 @@
 #ifdef TARGET_NR_setreuid32
 { TARGET_NR_setreuid32, "setreuid32" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_setrlimit
-{ TARGET_NR_setrlimit, "setrlimit" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_set_robust_list
 { TARGET_NR_set_robust_list, "set_robust_list" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 66/74] linux-user: Split out getrusage
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (64 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 65/74] linux-user: Split out getrlimit, setrlimit Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 67/74] linux-user: Split out gettimeofday, settimeofday Richard Henderson
                   ` (10 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  1 +
 linux-user/syscall-proc.inc.c | 12 ++++++++++++
 linux-user/syscall.c          |  9 ---------
 linux-user/strace.list        |  3 ---
 4 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 34426a2e23..446175af84 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -75,6 +75,7 @@ SYSCALL_DEF(getppid);
 #ifdef TARGET_NR_getrlimit
 SYSCALL_DEF(getrlimit, ARG_DEC, ARG_PTR);
 #endif
+SYSCALL_DEF(getrusage, ARG_DEC, ARG_PTR);
 SYSCALL_DEF(getsid, ARG_DEC);
 #ifdef TARGET_NR_getxpid
 SYSCALL_DEF(getxpid);
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
index 1238b08191..bf9e278bf0 100644
--- a/linux-user/syscall-proc.inc.c
+++ b/linux-user/syscall-proc.inc.c
@@ -499,6 +499,18 @@ SYSCALL_IMPL(getrlimit)
     return ret;
 }
 #endif
+
+SYSCALL_IMPL(getrusage)
+{
+    struct rusage rusage;
+    abi_long ret = get_errno(getrusage(arg1, &rusage));
+
+    if (!is_error(ret)) {
+        ret = host_to_target_rusage(arg2, &rusage);
+    }
+    return ret;
+}
+
 SYSCALL_IMPL(getsid)
 {
     return get_errno(getsid(arg1));
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 401450b0e3..5fe52c775d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4240,15 +4240,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_getrusage:
-        {
-            struct rusage rusage;
-            ret = get_errno(getrusage(arg1, &rusage));
-            if (!is_error(ret)) {
-                ret = host_to_target_rusage(arg2, &rusage);
-            }
-        }
-        return ret;
     case TARGET_NR_gettimeofday:
         {
             struct timeval tv;
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 711ad9c0aa..00a32bc616 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -283,9 +283,6 @@
 #ifdef TARGET_NR_get_robust_list
 { TARGET_NR_get_robust_list, "get_robust_list" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_getrusage
-{ TARGET_NR_getrusage, "getrusage" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_getsockname
 { TARGET_NR_getsockname, "getsockname" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 67/74] linux-user: Split out gettimeofday, settimeofday
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (65 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 66/74] linux-user: Split out getrusage Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 68/74] linux-user: Split out select, _newselect Richard Henderson
                   ` (9 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  2 ++
 linux-user/syscall-time.inc.c | 33 +++++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 31 -------------------------------
 linux-user/strace.list        |  6 ------
 4 files changed, 35 insertions(+), 37 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 446175af84..d109754c5f 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -77,6 +77,7 @@ SYSCALL_DEF(getrlimit, ARG_DEC, ARG_PTR);
 #endif
 SYSCALL_DEF(getrusage, ARG_DEC, ARG_PTR);
 SYSCALL_DEF(getsid, ARG_DEC);
+SYSCALL_DEF(gettimeofday, ARG_PTR);
 #ifdef TARGET_NR_getxpid
 SYSCALL_DEF(getxpid);
 #endif
@@ -220,6 +221,7 @@ SYSCALL_DEF(setpgid, ARG_DEC, ARG_DEC);
 SYSCALL_DEF(setrlimit, ARG_DEC, ARG_PTR);
 #endif
 SYSCALL_DEF(setsid);
+SYSCALL_DEF(settimeofday, ARG_PTR, ARG_PTR);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semop)
 SYSCALL_DEF(semop, ARG_DEC, ARG_PTR, ARG_DEC);
 #endif
diff --git a/linux-user/syscall-time.inc.c b/linux-user/syscall-time.inc.c
index d1fb72bde0..1308af64ac 100644
--- a/linux-user/syscall-time.inc.c
+++ b/linux-user/syscall-time.inc.c
@@ -16,6 +16,39 @@
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+SYSCALL_IMPL(gettimeofday)
+{
+    struct timeval tv;
+    abi_long ret = get_errno(gettimeofday(&tv, NULL));
+
+    if (!is_error(ret) && copy_to_user_timeval(arg1, &tv)) {
+        return -TARGET_EFAULT;
+    }
+    return ret;
+}
+
+SYSCALL_IMPL(settimeofday)
+{
+    struct timeval tv, *ptv = NULL;
+    struct timezone tz, *ptz = NULL;
+
+    if (arg1) {
+        if (copy_from_user_timeval(&tv, arg1)) {
+            return -TARGET_EFAULT;
+        }
+        ptv = &tv;
+    }
+
+    if (arg2) {
+        if (copy_from_user_timezone(&tz, arg2)) {
+            return -TARGET_EFAULT;
+        }
+        ptz = &tz;
+    }
+
+    return get_errno(settimeofday(ptv, ptz));
+}
+
 #ifdef TARGET_NR_stime
 SYSCALL_IMPL(stime)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 5fe52c775d..b8bc44364d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4240,37 +4240,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_gettimeofday:
-        {
-            struct timeval tv;
-            ret = get_errno(gettimeofday(&tv, NULL));
-            if (!is_error(ret)) {
-                if (copy_to_user_timeval(arg1, &tv))
-                    return -TARGET_EFAULT;
-            }
-        }
-        return ret;
-    case TARGET_NR_settimeofday:
-        {
-            struct timeval tv, *ptv = NULL;
-            struct timezone tz, *ptz = NULL;
-
-            if (arg1) {
-                if (copy_from_user_timeval(&tv, arg1)) {
-                    return -TARGET_EFAULT;
-                }
-                ptv = &tv;
-            }
-
-            if (arg2) {
-                if (copy_from_user_timezone(&tz, arg2)) {
-                    return -TARGET_EFAULT;
-                }
-                ptz = &tz;
-            }
-
-            return get_errno(settimeofday(ptv, ptz));
-        }
 #if defined(TARGET_NR_select)
     case TARGET_NR_select:
 #if defined(TARGET_WANT_NI_OLD_SELECT)
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 00a32bc616..635b952d2f 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -296,9 +296,6 @@
 #ifdef TARGET_NR_gettid
 { TARGET_NR_gettid, "gettid" , "%s()", NULL, NULL },
 #endif
-#ifdef TARGET_NR_gettimeofday
-{ TARGET_NR_gettimeofday, "gettimeofday" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_getuid
 { TARGET_NR_getuid, "getuid" , "%s()", NULL, NULL },
 #endif
@@ -1068,9 +1065,6 @@
 #ifdef TARGET_NR_set_tid_address
 { TARGET_NR_set_tid_address, "set_tid_address" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_settimeofday
-{ TARGET_NR_settimeofday, "settimeofday" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_setuid
 { TARGET_NR_setuid, "setuid" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 68/74] linux-user: Split out select, _newselect
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (66 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 67/74] linux-user: Split out gettimeofday, settimeofday Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 69/74] linux-user: Split out pselect6 Richard Henderson
                   ` (8 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

This removes the printing of the fdset outputs.  It's hard to see how
this could have been reliable in a multi-threaded program, saving
syscall arguments to global variables.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  11 ++++
 linux-user/strace.c           |  80 -------------------------
 linux-user/syscall-file.inc.c |  91 ++++++++++++++++++++++++++++
 linux-user/syscall.c          | 110 ++++------------------------------
 linux-user/strace.list        |   6 --
 5 files changed, 112 insertions(+), 186 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index d109754c5f..01143414c7 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -143,6 +143,10 @@ SYSCALL_DEF(munlockall);
 SYSCALL_DEF(munmap, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(name_to_handle_at,
             ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_PTR, ARG_ATFLAG);
+#ifdef TARGET_NR__newselect
+SYSCALL_DEF_FULL(_newselect, .impl = impl_select,
+                 .arg_type = { ARG_DEC, ARG_PTR, ARG_PTR, ARG_PTR, ARG_PTR });
+#endif
 #ifdef TARGET_NR_nice
 SYSCALL_DEF(nice, ARG_DEC);
 #endif
@@ -209,6 +213,13 @@ SYSCALL_DEF(rt_sigreturn);
 SYSCALL_DEF(rt_sigsuspend, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(rt_sigtimedwait, ARG_PTR, ARG_PTR, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(rt_tgsigqueueinfo, ARG_DEC, ARG_DEC, ARG_SIGNAL, ARG_PTR);
+#ifdef TARGET_NR_select
+# if defined(TARGET_WANT_NI_OLD_SELECT)
+SYSCALL_DEF_NOSYS(select);
+# else
+SYSCALL_DEF_ARGS(select, ARG_DEC, ARG_PTR, ARG_PTR, ARG_PTR, ARG_PTR);
+# endif
+#endif
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semctl)
 SYSCALL_DEF(semctl, ARG_DEC, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 2e70a3910c..669eca7fa6 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -384,34 +384,6 @@ print_socket_protocol(int domain, int type, int protocol)
 }
 
 
-#ifdef TARGET_NR__newselect
-static void
-print_fdset(int n, abi_ulong target_fds_addr)
-{
-    int i;
-
-    gemu_log("[");
-    if( target_fds_addr ) {
-        abi_long *target_fds;
-
-        target_fds = lock_user(VERIFY_READ,
-                               target_fds_addr,
-                               sizeof(*target_fds)*(n / TARGET_ABI_BITS + 1),
-                               1);
-
-        if (!target_fds)
-            return;
-
-        for (i=n; i>=0; i--) {
-            if ((tswapal(target_fds[i / TARGET_ABI_BITS]) >> (i & (TARGET_ABI_BITS - 1))) & 1)
-                gemu_log("%d,", i );
-            }
-        unlock_user(target_fds, target_fds_addr, 0);
-    }
-    gemu_log("]");
-}
-#endif
-
 #ifdef TARGET_NR_clock_adjtime
 /* IDs of the various system clocks */
 #define TARGET_CLOCK_REALTIME              0
@@ -479,58 +451,6 @@ print_clockid(int clockid, int last)
  * Sysycall specific output functions
  */
 
-/* select */
-#ifdef TARGET_NR__newselect
-static long newselect_arg1 = 0;
-static long newselect_arg2 = 0;
-static long newselect_arg3 = 0;
-static long newselect_arg4 = 0;
-static long newselect_arg5 = 0;
-
-static void
-print_newselect(const struct syscallname *name,
-                abi_long arg1, abi_long arg2, abi_long arg3,
-                abi_long arg4, abi_long arg5, abi_long arg6)
-{
-    gemu_log("%s(" TARGET_ABI_FMT_ld ",", name->name, arg1);
-    print_fdset(arg1, arg2);
-    gemu_log(",");
-    print_fdset(arg1, arg3);
-    gemu_log(",");
-    print_fdset(arg1, arg4);
-    gemu_log(",");
-    print_timeval(arg5, 1);
-    gemu_log(")");
-
-    /* save for use in the return output function below */
-    newselect_arg1=arg1;
-    newselect_arg2=arg2;
-    newselect_arg3=arg3;
-    newselect_arg4=arg4;
-    newselect_arg5=arg5;
-}
-#endif
-
-/*
- * Variants for the return value output function
- */
-
-#ifdef TARGET_NR__newselect
-static void
-print_syscall_ret_newselect(const struct syscallname *name, abi_long ret)
-{
-    gemu_log(" = 0x" TARGET_ABI_FMT_lx " (", ret);
-    print_fdset(newselect_arg1,newselect_arg2);
-    gemu_log(",");
-    print_fdset(newselect_arg1,newselect_arg3);
-    gemu_log(",");
-    print_fdset(newselect_arg1,newselect_arg4);
-    gemu_log(",");
-    print_timeval(newselect_arg5, 1);
-    gemu_log(")\n");
-}
-#endif
-
 /* special meanings of adjtimex()' non-negative return values */
 #define TARGET_TIME_OK       0   /* clock synchronized, no leap second */
 #define TARGET_TIME_INS      1   /* insert leap second */
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 6e730e3152..1d66dc3323 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -1067,6 +1067,97 @@ SYSCALL_IMPL(renameat2)
     return do_renameat2(arg1, arg2, arg3, arg4, arg5);
 }
 
+#if defined(TARGET_NR_select) && defined(TARGET_WANT_OLD_SYS_SELECT)
+SYSCALL_ARGS(select)
+{
+    struct target_sel_arg_struct *sel;
+    abi_ulong inp, outp, exp, tvp;
+    abi_long nsel;
+
+    if (!lock_user_struct(VERIFY_READ, sel, in[0], 1)) {
+        errno = EFAULT;
+        return NULL;
+    }
+    nsel = tswapal(sel->n);
+    inp = tswapal(sel->inp);
+    outp = tswapal(sel->outp);
+    exp = tswapal(sel->exp);
+    tvp = tswapal(sel->tvp);
+    unlock_user_struct(sel, in[0], 0);
+
+    out[0] = nsel;
+    out[1] = inp;
+    out[2] = outp;
+    out[3] = exp;
+    out[4] = tvp;
+    return def;
+}
+#else
+# define args_select NULL
+#endif
+
+#if (defined(TARGET_NR_select) && !defined(TARGET_WANT_NI_OLD_SELECT)) \
+    || defined(TARGET_NR__newselect)
+SYSCALL_IMPL(select)
+{
+    int n = arg1;
+    abi_ulong rfd_addr = arg2;
+    abi_ulong wfd_addr = arg3;
+    abi_ulong efd_addr = arg4;
+    abi_ulong target_tv_addr = arg5;
+    fd_set rfds, wfds, efds;
+    fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
+    struct timeval tv;
+    struct timespec ts, *ts_ptr = NULL;
+    abi_long ret;
+
+    ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
+    if (ret) {
+        return ret;
+    }
+    ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
+    if (ret) {
+        return ret;
+    }
+    ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
+    if (ret) {
+        return ret;
+    }
+
+    if (target_tv_addr) {
+        if (copy_from_user_timeval(&tv, target_tv_addr))
+            return -TARGET_EFAULT;
+        ts.tv_sec = tv.tv_sec;
+        ts.tv_nsec = tv.tv_usec * 1000;
+        ts_ptr = &ts;
+    }
+
+    ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
+                                  ts_ptr, NULL));
+
+    if (!is_error(ret)) {
+        if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) {
+            return -TARGET_EFAULT;
+        }
+        if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) {
+            return -TARGET_EFAULT;
+        }
+        if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) {
+            return -TARGET_EFAULT;
+        }
+        if (target_tv_addr) {
+            tv.tv_sec = ts.tv_sec;
+            tv.tv_usec = ts.tv_nsec / 1000;
+            if (copy_to_user_timeval(target_tv_addr, &tv)) {
+                return -TARGET_EFAULT;
+            }
+        }
+    }
+
+    return ret;
+}
+#endif
+
 SYSCALL_IMPL(sync)
 {
     sync();
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index b8bc44364d..2c8d74a450 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1055,88 +1055,6 @@ static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
 }
 #endif
 
-#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
-/* do_select() must return target values and target errnos. */
-static abi_long do_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;
-    struct timespec ts, *ts_ptr;
-    abi_long ret;
-
-    ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
-    if (ret) {
-        return ret;
-    }
-    ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
-    if (ret) {
-        return ret;
-    }
-    ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
-    if (ret) {
-        return ret;
-    }
-
-    if (target_tv_addr) {
-        if (copy_from_user_timeval(&tv, target_tv_addr))
-            return -TARGET_EFAULT;
-        ts.tv_sec = tv.tv_sec;
-        ts.tv_nsec = tv.tv_usec * 1000;
-        ts_ptr = &ts;
-    } else {
-        ts_ptr = NULL;
-    }
-
-    ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
-                                  ts_ptr, NULL));
-
-    if (!is_error(ret)) {
-        if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
-            return -TARGET_EFAULT;
-        if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
-            return -TARGET_EFAULT;
-        if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
-            return -TARGET_EFAULT;
-
-        if (target_tv_addr) {
-            tv.tv_sec = ts.tv_sec;
-            tv.tv_usec = ts.tv_nsec / 1000;
-            if (copy_to_user_timeval(target_tv_addr, &tv)) {
-                return -TARGET_EFAULT;
-            }
-        }
-    }
-
-    return ret;
-}
-
-#if defined(TARGET_WANT_OLD_SYS_SELECT)
-static abi_long do_old_select(abi_ulong arg1)
-{
-    struct target_sel_arg_struct *sel;
-    abi_ulong inp, outp, exp, tvp;
-    long nsel;
-
-    if (!lock_user_struct(VERIFY_READ, sel, arg1, 1)) {
-        return -TARGET_EFAULT;
-    }
-
-    nsel = tswapal(sel->n);
-    inp = tswapal(sel->inp);
-    outp = tswapal(sel->outp);
-    exp = tswapal(sel->exp);
-    tvp = tswapal(sel->tvp);
-
-    unlock_user_struct(sel, arg1, 0);
-
-    return do_select(nsel, inp, outp, exp, tvp);
-}
-#endif
-#endif
-
 static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
                                               abi_ulong target_addr,
                                               socklen_t len)
@@ -4240,20 +4158,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#if defined(TARGET_NR_select)
-    case TARGET_NR_select:
-#if defined(TARGET_WANT_NI_OLD_SELECT)
-        /* some architectures used to have old_select here
-         * but now ENOSYS it.
-         */
-        ret = -TARGET_ENOSYS;
-#elif defined(TARGET_WANT_OLD_SYS_SELECT)
-        ret = do_old_select(arg1);
-#else
-        ret = do_select(arg1, arg2, arg3, arg4, arg5);
-#endif
-        return ret;
-#endif
 #ifdef TARGET_NR_pselect6
     case TARGET_NR_pselect6:
         {
@@ -5007,10 +4911,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         }
         return ret;
 #endif /* TARGET_NR_getdents64 */
-#if defined(TARGET_NR__newselect)
-    case TARGET_NR__newselect:
-        return do_select(arg1, arg2, arg3, arg4, arg5);
-#endif
 #if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll)
 # ifdef TARGET_NR_poll
     case TARGET_NR_poll:
@@ -7233,6 +7133,12 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
 #include "syscall-sig.inc.c"
 #include "syscall-time.inc.c"
 
+static SyscallImplFn impl_enosys __attribute__((unused));
+SYSCALL_IMPL(enosys)
+{
+    return -TARGET_ENOSYS;
+}
+
 #undef SYSCALL_IMPL
 #undef SYSCALL_ARGS
 
@@ -7254,6 +7160,10 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     SYSCALL_DEF_FULL(NAME, .impl = impl_##NAME, .args = args_##NAME, \
                      .arg_type = { __VA_ARGS__ })
 
+/* Emit a definition that always produces ENOSYS without logging.  */
+#define SYSCALL_DEF_NOSYS(NAME) \
+    SYSCALL_DEF_FULL(NAME, .impl = impl_enosys)
+
 #include "syscall-defs.h"
 
 #undef SYSCALL_DEF
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 635b952d2f..297180d94f 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -470,9 +470,6 @@
 #ifdef TARGET_NR_newfstatat
 { TARGET_NR_newfstatat, "newfstatat" , NULL, print_newfstatat, NULL },
 #endif
-#ifdef TARGET_NR__newselect
-{ TARGET_NR__newselect, "_newselect" , NULL, print_newselect, print_syscall_ret_newselect },
-#endif
 #ifdef TARGET_NR_nfsservctl
 { TARGET_NR_nfsservctl, "nfsservctl" , NULL, NULL, NULL },
 #endif
@@ -962,9 +959,6 @@
 #ifdef TARGET_NR_security
 { TARGET_NR_security, "security" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_select
-{ TARGET_NR_select, "select" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_send
 { TARGET_NR_send, "send" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 69/74] linux-user: Split out pselect6
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (67 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 68/74] linux-user: Split out select, _newselect Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 70/74] linux-user: Split out symlink, symlinkat Richard Henderson
                   ` (7 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |   1 +
 linux-user/syscall-file.inc.c |  96 +++++++++++++++++++++++++++++++
 linux-user/syscall.c          | 103 ----------------------------------
 linux-user/strace.list        |   3 -
 4 files changed, 97 insertions(+), 106 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 01143414c7..c179f69d9f 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -180,6 +180,7 @@ SYSCALL_DEF_FULL(preadv, .impl = impl_preadv,
 SYSCALL_DEF_FULL(pwritev, .impl = impl_pwritev,
                  .args = args_preadv_pwritev,
                  .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 });
+SYSCALL_DEF(pselect6, ARG_DEC, ARG_PTR, ARG_PTR, ARG_PTR, ARG_PTR, ARG_PTR);
 SYSCALL_DEF(read, ARG_DEC, ARG_PTR, ARG_DEC);
 #ifdef TARGET_NR_readlink
 SYSCALL_DEF(readlink, ARG_STR, ARG_PTR, ARG_DEC);
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 1d66dc3323..0a25d39d28 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -934,6 +934,102 @@ SYSCALL_IMPL(pwritev)
     return ret;
 }
 
+SYSCALL_IMPL(pselect6)
+{
+    abi_long n = arg1;
+    abi_ulong rfd_addr = arg2;
+    abi_ulong wfd_addr = arg3;
+    abi_ulong efd_addr = arg4;
+    abi_ulong ts_addr = arg5;
+    fd_set rfds, wfds, efds;
+    fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
+    struct timespec ts, *ts_ptr = NULL;
+    abi_long ret;
+
+    /*
+     * The 6th arg is actually two args smashed together, and since
+     * we are using safe_syscall, we must handle this ourselves.
+     */
+    sigset_t set;
+    struct {
+        sigset_t *set;
+        size_t size;
+    } sig, *sig_ptr = NULL;
+
+    abi_ulong arg_sigset, arg_sigsize, *arg7;
+    target_sigset_t *target_sigset;
+
+    ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
+    if (ret) {
+        return ret;
+    }
+    ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
+    if (ret) {
+        return ret;
+    }
+    ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
+    if (ret) {
+        return ret;
+    }
+
+    if (ts_addr) {
+        if (target_to_host_timespec(&ts, ts_addr)) {
+            return -TARGET_EFAULT;
+        }
+        ts_ptr = &ts;
+    }
+
+    /* Extract the two packed args for the sigset */
+    if (arg6) {
+        sig_ptr = &sig;
+        sig.size = SIGSET_T_SIZE;
+
+        arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
+        if (!arg7) {
+            return -TARGET_EFAULT;
+        }
+        arg_sigset = tswapal(arg7[0]);
+        arg_sigsize = tswapal(arg7[1]);
+        unlock_user(arg7, arg6, 0);
+
+        if (arg_sigset) {
+            sig.set = &set;
+            if (arg_sigsize != sizeof(*target_sigset)) {
+                /* Like the kernel, we enforce correct size sigsets */
+                return -TARGET_EINVAL;
+            }
+            target_sigset = lock_user(VERIFY_READ, arg_sigset,
+                                      sizeof(*target_sigset), 1);
+            if (!target_sigset) {
+                return -TARGET_EFAULT;
+            }
+            target_to_host_sigset(&set, target_sigset);
+            unlock_user(target_sigset, arg_sigset, 0);
+        } else {
+            sig.set = NULL;
+        }
+    }
+
+    ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
+                                  ts_ptr, sig_ptr));
+
+    if (!is_error(ret)) {
+        if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) {
+            return -TARGET_EFAULT;
+        }
+        if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) {
+            return -TARGET_EFAULT;
+        }
+        if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) {
+            return -TARGET_EFAULT;
+        }
+        if (ts_addr && host_to_target_timespec(ts_addr, &ts)) {
+            return -TARGET_EFAULT;
+        }
+    }
+    return ret;
+}
+
 SYSCALL_IMPL(read)
 {
     int fd = arg1;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 2c8d74a450..6355fd62d8 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4158,109 +4158,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_pselect6
-    case TARGET_NR_pselect6:
-        {
-            abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
-            fd_set rfds, wfds, efds;
-            fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
-            struct timespec ts, *ts_ptr;
-
-            /*
-             * The 6th arg is actually two args smashed together,
-             * so we cannot use the C library.
-             */
-            sigset_t set;
-            struct {
-                sigset_t *set;
-                size_t size;
-            } sig, *sig_ptr;
-
-            abi_ulong arg_sigset, arg_sigsize, *arg7;
-            target_sigset_t *target_sigset;
-
-            n = arg1;
-            rfd_addr = arg2;
-            wfd_addr = arg3;
-            efd_addr = arg4;
-            ts_addr = arg5;
-
-            ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
-            if (ret) {
-                return ret;
-            }
-            ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
-            if (ret) {
-                return ret;
-            }
-            ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
-            if (ret) {
-                return ret;
-            }
-
-            /*
-             * This takes a timespec, and not a timeval, so we cannot
-             * use the do_select() helper ...
-             */
-            if (ts_addr) {
-                if (target_to_host_timespec(&ts, ts_addr)) {
-                    return -TARGET_EFAULT;
-                }
-                ts_ptr = &ts;
-            } else {
-                ts_ptr = NULL;
-            }
-
-            /* Extract the two packed args for the sigset */
-            if (arg6) {
-                sig_ptr = &sig;
-                sig.size = SIGSET_T_SIZE;
-
-                arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
-                if (!arg7) {
-                    return -TARGET_EFAULT;
-                }
-                arg_sigset = tswapal(arg7[0]);
-                arg_sigsize = tswapal(arg7[1]);
-                unlock_user(arg7, arg6, 0);
-
-                if (arg_sigset) {
-                    sig.set = &set;
-                    if (arg_sigsize != sizeof(*target_sigset)) {
-                        /* Like the kernel, we enforce correct size sigsets */
-                        return -TARGET_EINVAL;
-                    }
-                    target_sigset = lock_user(VERIFY_READ, arg_sigset,
-                                              sizeof(*target_sigset), 1);
-                    if (!target_sigset) {
-                        return -TARGET_EFAULT;
-                    }
-                    target_to_host_sigset(&set, target_sigset);
-                    unlock_user(target_sigset, arg_sigset, 0);
-                } else {
-                    sig.set = NULL;
-                }
-            } else {
-                sig_ptr = NULL;
-            }
-
-            ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
-                                          ts_ptr, sig_ptr));
-
-            if (!is_error(ret)) {
-                if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
-                    return -TARGET_EFAULT;
-                if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
-                    return -TARGET_EFAULT;
-                if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
-                    return -TARGET_EFAULT;
-
-                if (ts_addr && host_to_target_timespec(ts_addr, &ts))
-                    return -TARGET_EFAULT;
-            }
-        }
-        return ret;
-#endif
 #ifdef TARGET_NR_symlink
     case TARGET_NR_symlink:
         {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 297180d94f..1bb9224b5e 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -848,9 +848,6 @@
 #ifdef TARGET_NR_profil
 { TARGET_NR_profil, "profil" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_pselect6
-{ TARGET_NR_pselect6, "pselect6" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_ptrace
 { TARGET_NR_ptrace, "ptrace" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 70/74] linux-user: Split out symlink, symlinkat
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (68 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 69/74] linux-user: Split out pselect6 Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 71/74] linux-user: Split out swapon, swapoff Richard Henderson
                   ` (6 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  4 ++++
 linux-user/strace.c           | 27 ---------------------------
 linux-user/syscall-file.inc.c | 28 ++++++++++++++++++++++++++++
 linux-user/syscall.c          | 30 ------------------------------
 linux-user/strace.list        |  6 ------
 5 files changed, 32 insertions(+), 63 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index c179f69d9f..5625c268c3 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -279,6 +279,10 @@ SYSCALL_DEF(ssetmask, ARG_HEX);
 #ifdef TARGET_NR_stime
 SYSCALL_DEF(stime, ARG_PTR);
 #endif
+#ifdef TARGET_NR_symlink
+SYSCALL_DEF(symlink, ARG_STR, ARG_STR);
+#endif
+SYSCALL_DEF(symlinkat, ARG_STR, ARG_ATDIRFD, ARG_STR);
 SYSCALL_DEF(sync);
 SYSCALL_DEF(syncfs, ARG_DEC);
 #ifdef TARGET_NR_time
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 669eca7fa6..97755458d3 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1563,33 +1563,6 @@ print_statfs64(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_symlink
-static void
-print_symlink(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 0);
-    print_string(arg1, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
-#ifdef TARGET_NR_symlinkat
-static void
-print_symlinkat(const struct syscallname *name,
-    abi_long arg0, abi_long arg1, abi_long arg2,
-    abi_long arg3, abi_long arg4, abi_long arg5)
-{
-    print_syscall_prologue(name);
-    print_string(arg0, 0);
-    print_at_dirfd(arg1, 0);
-    print_string(arg2, 1);
-    print_syscall_epilogue(name);
-}
-#endif
-
 #ifdef TARGET_NR_utimensat
 static void
 print_utimensat(const struct syscallname *name,
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index 0a25d39d28..e3749f0fb4 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -1254,6 +1254,34 @@ SYSCALL_IMPL(select)
 }
 #endif
 
+static abi_long do_symlinkat(abi_ulong guest_target, int dirfd,
+                             abi_ulong guest_path)
+{
+    char *target = lock_user_string(guest_target);
+    char *path = lock_user_string(guest_path);
+    abi_long ret = -TARGET_EFAULT;
+
+    if (target && path) {
+        ret = get_errno(symlinkat(target, dirfd, path));
+    }
+    unlock_user(path, guest_path, 0);
+    unlock_user(target, guest_target, 0);
+
+    return ret;
+}
+
+#ifdef TARGET_NR_symlink
+SYSCALL_IMPL(symlink)
+{
+    return do_symlinkat(arg1, AT_FDCWD, arg2);
+}
+#endif
+
+SYSCALL_IMPL(symlinkat)
+{
+    return do_symlinkat(arg1, arg2, arg3);
+}
+
 SYSCALL_IMPL(sync)
 {
     sync();
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 6355fd62d8..fccf9ee184 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4158,36 +4158,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_symlink
-    case TARGET_NR_symlink:
-        {
-            void *p2;
-            p = lock_user_string(arg1);
-            p2 = lock_user_string(arg2);
-            if (!p || !p2)
-                ret = -TARGET_EFAULT;
-            else
-                ret = get_errno(symlink(p, p2));
-            unlock_user(p2, arg2, 0);
-            unlock_user(p, arg1, 0);
-        }
-        return ret;
-#endif
-#if defined(TARGET_NR_symlinkat)
-    case TARGET_NR_symlinkat:
-        {
-            void *p2;
-            p  = lock_user_string(arg1);
-            p2 = lock_user_string(arg3);
-            if (!p || !p2)
-                ret = -TARGET_EFAULT;
-            else
-                ret = get_errno(symlinkat(p, arg2, p2));
-            unlock_user(p2, arg3, 0);
-            unlock_user(p, arg1, 0);
-        }
-        return ret;
-#endif
 #ifdef TARGET_NR_swapon
     case TARGET_NR_swapon:
         if (!(p = lock_user_string(arg1)))
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 1bb9224b5e..d9db80335d 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1122,12 +1122,6 @@
 #ifdef TARGET_NR_swapon
 { TARGET_NR_swapon, "swapon" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_symlink
-{ TARGET_NR_symlink, "symlink" , NULL, print_symlink, NULL },
-#endif
-#ifdef TARGET_NR_symlinkat
-{ TARGET_NR_symlinkat, "symlinkat", NULL, print_symlinkat, NULL },
-#endif
 #ifdef TARGET_NR_syscall
 { TARGET_NR_syscall, "syscall" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 71/74] linux-user: Split out swapon, swapoff
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (69 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 70/74] linux-user: Split out symlink, symlinkat Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 72/74] linux-user: Split out reboot Richard Henderson
                   ` (5 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  2 ++
 linux-user/syscall-file.inc.c | 26 ++++++++++++++++++++++++++
 linux-user/syscall.c          | 16 ----------------
 linux-user/strace.list        |  6 ------
 4 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 5625c268c3..34e799d206 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -279,6 +279,8 @@ SYSCALL_DEF(ssetmask, ARG_HEX);
 #ifdef TARGET_NR_stime
 SYSCALL_DEF(stime, ARG_PTR);
 #endif
+SYSCALL_DEF(swapoff, ARG_STR);
+SYSCALL_DEF(swapon, ARG_STR, ARG_HEX);
 #ifdef TARGET_NR_symlink
 SYSCALL_DEF(symlink, ARG_STR, ARG_STR);
 #endif
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index e3749f0fb4..bdf42ad437 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -1254,6 +1254,32 @@ SYSCALL_IMPL(select)
 }
 #endif
 
+SYSCALL_IMPL(swapoff)
+{
+    char *p = lock_user_string(arg1);
+    abi_long ret;
+
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(swapoff(p));
+    unlock_user(p, arg1, 0);
+    return ret;
+}
+
+SYSCALL_IMPL(swapon)
+{
+    char *p = lock_user_string(arg1);
+    abi_long ret;
+
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(swapon(p, arg2));
+    unlock_user(p, arg1, 0);
+    return ret;
+}
+
 static abi_long do_symlinkat(abi_ulong guest_target, int dirfd,
                              abi_ulong guest_path)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index fccf9ee184..ead2e5c2b8 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4158,14 +4158,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_swapon
-    case TARGET_NR_swapon:
-        if (!(p = lock_user_string(arg1)))
-            return -TARGET_EFAULT;
-        ret = get_errno(swapon(p, arg2));
-        unlock_user(p, arg1, 0);
-        return ret;
-#endif
     case TARGET_NR_reboot:
         if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
            /* arg4 must be ignored in all other cases */
@@ -4503,14 +4495,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR_syscall:
         return do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
                           arg6, arg7, arg8, 0);
-#endif
-#ifdef TARGET_NR_swapoff
-    case TARGET_NR_swapoff:
-        if (!(p = lock_user_string(arg1)))
-            return -TARGET_EFAULT;
-        ret = get_errno(swapoff(p));
-        unlock_user(p, arg1, 0);
-        return ret;
 #endif
     case TARGET_NR_sysinfo:
         {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index d9db80335d..3d2e398439 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1116,12 +1116,6 @@
 #ifdef TARGET_NR_swapcontext
 { TARGET_NR_swapcontext, "swapcontext" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_swapoff
-{ TARGET_NR_swapoff, "swapoff" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_swapon
-{ TARGET_NR_swapon, "swapon" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_syscall
 { TARGET_NR_syscall, "syscall" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 72/74] linux-user: Split out reboot
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (70 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 71/74] linux-user: Split out swapon, swapoff Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 73/74] linux-user: Split out truncate, truncate64, ftruncate, ftruncate64 Richard Henderson
                   ` (4 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  1 +
 linux-user/syscall-proc.inc.c | 18 ++++++++++++++++++
 linux-user/syscall.c          | 13 -------------
 linux-user/strace.list        |  3 ---
 4 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 34e799d206..67c908448d 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -188,6 +188,7 @@ SYSCALL_DEF(readlink, ARG_STR, ARG_PTR, ARG_DEC);
 #ifdef TARGET_NR_readlinkat
 SYSCALL_DEF(readlinkat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_DEC);
 #endif
+SYSCALL_DEF(reboot, ARG_HEX, ARG_HEX, ARG_DEC, ARG_PTR);
 #ifdef TARGET_NR_rename
 SYSCALL_DEF(rename, ARG_STR, ARG_STR);
 #endif
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
index bf9e278bf0..408e96a834 100644
--- a/linux-user/syscall-proc.inc.c
+++ b/linux-user/syscall-proc.inc.c
@@ -532,6 +532,24 @@ SYSCALL_IMPL(nice)
 }
 #endif
 
+SYSCALL_IMPL(reboot)
+{
+    abi_long ret;
+
+    if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
+        /* arg4 must be ignored in all other cases */
+        char *p = lock_user_string(arg4);
+        if (!p) {
+            return -TARGET_EFAULT;
+        }
+        ret = get_errno(reboot(arg1, arg2, arg3, p));
+        unlock_user(p, arg4, 0);
+    } else {
+        ret = get_errno(reboot(arg1, arg2, arg3, NULL));
+    }
+    return ret;
+}
+
 SYSCALL_IMPL(sethostname)
 {
     void *p = lock_user_string(arg1);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ead2e5c2b8..80e8b360a9 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4158,19 +4158,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_reboot:
-        if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
-           /* arg4 must be ignored in all other cases */
-           p = lock_user_string(arg4);
-           if (!p) {
-               return -TARGET_EFAULT;
-           }
-           ret = get_errno(reboot(arg1, arg2, arg3, p));
-           unlock_user(p, arg4, 0);
-        } else {
-           ret = get_errno(reboot(arg1, arg2, arg3, NULL));
-        }
-        return ret;
 #ifdef TARGET_NR_truncate
     case TARGET_NR_truncate:
         if (!(p = lock_user_string(arg1)))
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 3d2e398439..3326541f17 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -866,9 +866,6 @@
 #ifdef TARGET_NR_readdir
 { TARGET_NR_readdir, "readdir" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_reboot
-{ TARGET_NR_reboot, "reboot" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_recv
 { TARGET_NR_recv, "recv" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 73/74] linux-user: Split out truncate, truncate64, ftruncate, ftruncate64
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (71 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 72/74] linux-user: Split out reboot Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 74/74] linux-user: Split out getpriority, setpriority Richard Henderson
                   ` (3 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     | 16 +++++++++++++++
 linux-user/syscall-file.inc.c | 32 +++++++++++++++++++++++++++++
 linux-user/syscall.c          | 38 -----------------------------------
 linux-user/strace.list        | 12 -----------
 4 files changed, 48 insertions(+), 50 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 67c908448d..8b2d95d19e 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -59,6 +59,14 @@ SYSCALL_DEF(futimesat, ARG_ATDIRFD, ARG_STR, ARG_PTR);
 #ifdef TARGET_NR_fork
 SYSCALL_DEF(fork);
 #endif
+#ifdef TARGET_NR_ftruncate
+SYSCALL_DEF(ftruncate, ARG_DEC, ARG_DEC);
+#endif
+#ifdef TARGET_NR_ftruncate64
+SYSCALL_DEF_FULL(ftruncate64, .impl = impl_ftruncate,
+                 .args = args_ftruncate64_truncate64,
+                 .arg_type = { ARG_DEC, ARG_DEC64 });
+#endif
 #ifdef TARGET_NR_gethostname
 SYSCALL_DEF(gethostname, ARG_PTR, ARG_DEC);
 #endif
@@ -292,6 +300,14 @@ SYSCALL_DEF(syncfs, ARG_DEC);
 SYSCALL_DEF(time, ARG_PTR);
 #endif
 SYSCALL_DEF(times, ARG_PTR);
+#ifdef TARGET_NR_truncate
+SYSCALL_DEF(truncate, ARG_STR, ARG_DEC);
+#endif
+#ifdef TARGET_NR_truncate64
+SYSCALL_DEF_FULL(truncate64, .impl = impl_truncate,
+                 .args = args_ftruncate64_truncate64,
+                 .arg_type = { ARG_STR, ARG_DEC64 });
+#endif
 SYSCALL_DEF(umask, ARG_OCT);
 #ifdef TARGET_NR_umount
 SYSCALL_DEF(umount, ARG_STR);
diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c
index bdf42ad437..7697cb304a 100644
--- a/linux-user/syscall-file.inc.c
+++ b/linux-user/syscall-file.inc.c
@@ -182,6 +182,25 @@ SYSCALL_IMPL(fchmodat)
     return do_fchmodat(arg1, arg2, arg3);
 }
 
+#ifdef TARGET_NR_ftruncate64
+# if TARGET_ABI_BITS == 32
+SYSCALL_ARGS(ftruncate64_truncate64)
+{
+    /* We have already assigned out[0].  */
+    int off = regpairs_aligned(cpu_env, TARGET_NR_ftruncate64);
+    out[1] = target_offset64(in[1 + off], in[2 + off]);
+    return def;
+}
+# else
+#  define args_ftruncate64_truncate64 NULL
+# endif
+#endif
+
+SYSCALL_IMPL(ftruncate)
+{
+    return get_errno(ftruncate(arg1, arg2));
+}
+
 #ifdef TARGET_NR_futimesat
 SYSCALL_IMPL(futimesat)
 {
@@ -1319,6 +1338,19 @@ SYSCALL_IMPL(syncfs)
     return get_errno(syncfs(arg1));
 }
 
+SYSCALL_IMPL(truncate)
+{
+    char *p = lock_user_string(arg1);
+    abi_long ret;
+
+    if (!p) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(truncate(p, arg2));
+    unlock_user(p, arg1, 0);
+    return ret;
+}
+
 static abi_long do_umount2(abi_ulong target_path, int flags)
 {
     char *p = lock_user_string(target_path);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 80e8b360a9..1b1d44bf32 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -3721,20 +3721,6 @@ static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
 }
 #endif
 
-#ifdef TARGET_NR_ftruncate64
-static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
-                                          abi_long arg2,
-                                          abi_long arg3,
-                                          abi_long arg4)
-{
-    if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) {
-        arg2 = arg3;
-        arg3 = arg4;
-    }
-    return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
-}
-#endif
-
 static inline abi_long target_to_host_timespec(struct timespec *host_ts,
                                                abi_ulong target_addr)
 {
@@ -4158,18 +4144,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-#ifdef TARGET_NR_truncate
-    case TARGET_NR_truncate:
-        if (!(p = lock_user_string(arg1)))
-            return -TARGET_EFAULT;
-        ret = get_errno(truncate(p, arg2));
-        unlock_user(p, arg1, 0);
-        return ret;
-#endif
-#ifdef TARGET_NR_ftruncate
-    case TARGET_NR_ftruncate:
-        return get_errno(ftruncate(arg1, arg2));
-#endif
     case TARGET_NR_getpriority:
         /* Note that negative values are valid for getpriority, so we must
            differentiate based on errno settings.  */
@@ -5371,18 +5345,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         return ret;
     }
 #endif
-#ifdef TARGET_NR_truncate64
-    case TARGET_NR_truncate64:
-        if (!(p = lock_user_string(arg1)))
-            return -TARGET_EFAULT;
-	ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
-        unlock_user(p, arg1, 0);
-        return ret;
-#endif
-#ifdef TARGET_NR_ftruncate64
-    case TARGET_NR_ftruncate64:
-        return target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
-#endif
 #ifdef TARGET_NR_stat64
     case TARGET_NR_stat64:
         if (!(p = lock_user_string(arg1))) {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 3326541f17..55b617239c 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -193,12 +193,6 @@
 #ifdef TARGET_NR_ftime
 { TARGET_NR_ftime, "ftime" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_ftruncate
-{ TARGET_NR_ftruncate, "ftruncate" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_ftruncate64
-{ TARGET_NR_ftruncate64, "ftruncate64" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_futex
 { TARGET_NR_futex, "futex" , NULL, print_futex, NULL },
 #endif
@@ -1173,12 +1167,6 @@
 #ifdef TARGET_NR_tkill
 { TARGET_NR_tkill, "tkill" , NULL, print_tkill, NULL },
 #endif
-#ifdef TARGET_NR_truncate
-{ TARGET_NR_truncate, "truncate" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_truncate64
-{ TARGET_NR_truncate64, "truncate64" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_tuxcall
 { TARGET_NR_tuxcall, "tuxcall" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [Qemu-devel] [PATCH v7 74/74] linux-user: Split out getpriority, setpriority
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (72 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 73/74] linux-user: Split out truncate, truncate64, ftruncate, ftruncate64 Richard Henderson
@ 2019-05-19 20:37 ` Richard Henderson
  2019-05-20  6:21 ` [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Laurent Vivier
                   ` (2 subsequent siblings)
  76 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-19 20:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall-defs.h     |  2 ++
 linux-user/syscall-proc.inc.c | 28 ++++++++++++++++++++++++++++
 linux-user/syscall.c          | 18 ------------------
 linux-user/strace.list        |  6 ------
 4 files changed, 30 insertions(+), 24 deletions(-)

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index 8b2d95d19e..3b45250977 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -80,6 +80,7 @@ SYSCALL_DEF(getpid);
 #ifdef TARGET_NR_getppid
 SYSCALL_DEF(getppid);
 #endif
+SYSCALL_DEF(getpriority, ARG_DEC, ARG_DEC);
 #ifdef TARGET_NR_getrlimit
 SYSCALL_DEF(getrlimit, ARG_DEC, ARG_PTR);
 #endif
@@ -238,6 +239,7 @@ SYSCALL_DEF(semget, ARG_DEC, ARG_DEC, ARG_HEX);
 #endif
 SYSCALL_DEF(sethostname, ARG_STR);
 SYSCALL_DEF(setpgid, ARG_DEC, ARG_DEC);
+SYSCALL_DEF(setpriority, ARG_DEC, ARG_DEC, ARG_DEC);
 #ifdef TARGET_NR_setrlimit
 SYSCALL_DEF(setrlimit, ARG_DEC, ARG_PTR);
 #endif
diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c
index 408e96a834..e85151cc2e 100644
--- a/linux-user/syscall-proc.inc.c
+++ b/linux-user/syscall-proc.inc.c
@@ -479,6 +479,29 @@ SYSCALL_IMPL(getppid)
 }
 #endif
 
+SYSCALL_IMPL(getpriority)
+{
+    abi_long ret;
+
+    /*
+     * Note that negative values are valid for getpriority, so we must
+     * differentiate based on errno settings.
+     */
+    errno = 0;
+    ret = getpriority(arg1, arg2);
+    if (ret == -1 && errno != 0) {
+        return -host_to_target_errno(errno);
+    }
+#ifdef TARGET_ALPHA
+    /* Return value is the unbiased priority.  Signal no error.  */
+    ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0;
+#else
+    /* Return value is a biased priority to avoid negative numbers.  */
+    ret = 20 - ret;
+#endif
+    return ret;
+}
+
 #ifdef TARGET_NR_getrlimit
 SYSCALL_IMPL(getrlimit)
 {
@@ -568,6 +591,11 @@ SYSCALL_IMPL(setpgid)
     return get_errno(setpgid(arg1, arg2));
 }
 
+SYSCALL_IMPL(setpriority)
+{
+    return get_errno(setpriority(arg1, arg2, arg3));
+}
+
 #ifdef TARGET_NR_setrlimit
 SYSCALL_IMPL(setrlimit)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 1b1d44bf32..6e7cccbdd5 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4144,24 +4144,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     switch(num) {
-    case TARGET_NR_getpriority:
-        /* Note that negative values are valid for getpriority, so we must
-           differentiate based on errno settings.  */
-        errno = 0;
-        ret = getpriority(arg1, arg2);
-        if (ret == -1 && errno != 0) {
-            return -host_to_target_errno(errno);
-        }
-#ifdef TARGET_ALPHA
-        /* Return value is the unbiased priority.  Signal no error.  */
-        ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0;
-#else
-        /* Return value is a biased priority to avoid negative numbers.  */
-        ret = 20 - ret;
-#endif
-        return ret;
-    case TARGET_NR_setpriority:
-        return get_errno(setpriority(arg1, arg2, arg3));
 #ifdef TARGET_NR_statfs
     case TARGET_NR_statfs:
         if (!(p = lock_user_string(arg1))) {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 55b617239c..a0d2b3f9c5 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -256,9 +256,6 @@
 #ifdef TARGET_NR_getpmsg
 { TARGET_NR_getpmsg, "getpmsg" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_getpriority
-{ TARGET_NR_getpriority, "getpriority", "%s(%#x,%#x)", NULL, NULL },
-#endif
 #ifdef TARGET_NR_getrandom
 { TARGET_NR_getrandom, "getrandom", NULL, NULL, NULL },
 #endif
@@ -1007,9 +1004,6 @@
 #ifdef TARGET_NR_setpgrp
 { TARGET_NR_setpgrp, "setpgrp" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_setpriority
-{ TARGET_NR_setpriority, "setpriority" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_setregid
 { TARGET_NR_setregid, "setregid" , NULL, NULL, NULL },
 #endif
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 81+ messages in thread

* Re: [Qemu-devel] [PATCH v7 62/74] linux-user: Split out rt_sigqueueinfo, rt_tgsigqueueinfo
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 62/74] linux-user: Split out rt_sigqueueinfo, rt_tgsigqueueinfo Richard Henderson
@ 2019-05-20  6:04   ` Aleksandar Markovic
  0 siblings, 0 replies; 81+ messages in thread
From: Aleksandar Markovic @ 2019-05-20  6:04 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, laurent

On May 19, 2019 11:25 PM, "Richard Henderson" <richard.henderson@linaro.org>
wrote:
>
> This does drop the (questionable) siginfo_t printing.
> But since we already do not handle more important things
> in this area like sigset_t, this does not feel a loss.
>

What is the most questionable here is the reasoning “we don't handle one
thing, therefore let's drop another”.

If you find siginfo_t printing questionable, then provide a better one, not
remove it altogether.

I find that the current printing is useful in many circumstances, there is
a lot of energy of former contributors invested into it, and should not be
deleted just like that. It does feel like a loss.

Aleksandar

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  linux-user/syscall-defs.h    |   2 +
>  linux-user/strace.c          | 138 -----------------------------------
>  linux-user/syscall-sig.inc.c |  30 ++++++++
>  linux-user/syscall.c         |  26 -------
>  linux-user/strace.list       |   6 --
>  5 files changed, 32 insertions(+), 170 deletions(-)
>
> diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
> index 24289ed413..11851535e1 100644
> --- a/linux-user/syscall-defs.h
> +++ b/linux-user/syscall-defs.h
> @@ -196,8 +196,10 @@ SYSCALL_DEF(rt_sigaction, ARG_SIGNAL, ARG_PTR,
ARG_PTR, ARG_DEC);
>  #endif
>  SYSCALL_DEF(rt_sigpending, ARG_PTR, ARG_DEC);
>  SYSCALL_DEF(rt_sigprocmask, ARG_SIGPROCMASKHOW, ARG_PTR, ARG_PTR,
ARG_DEC);
> +SYSCALL_DEF(rt_sigqueueinfo, ARG_DEC, ARG_SIGNAL, ARG_PTR);
>  SYSCALL_DEF(rt_sigsuspend, ARG_PTR, ARG_DEC);
>  SYSCALL_DEF(rt_sigtimedwait, ARG_PTR, ARG_PTR, ARG_PTR, ARG_DEC);
> +SYSCALL_DEF(rt_tgsigqueueinfo, ARG_DEC, ARG_DEC, ARG_SIGNAL, ARG_PTR);
>  #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semctl)
>  SYSCALL_DEF(semctl, ARG_DEC, ARG_DEC, ARG_DEC, ARG_HEX);
>  #endif
> diff --git a/linux-user/strace.c b/linux-user/strace.c
> index 886663af2e..2e70a3910c 100644
> --- a/linux-user/strace.c
> +++ b/linux-user/strace.c
> @@ -167,93 +167,6 @@ static void print_si_code(int arg)
>      gemu_log("%s", codename);
>  }
>
> -static void get_target_siginfo(target_siginfo_t *tinfo,
> -                                const target_siginfo_t *info)
> -{
> -    abi_ulong sival_ptr;
> -
> -    int sig;
> -    int si_errno;
> -    int si_code;
> -    int si_type;
> -
> -    __get_user(sig, &info->si_signo);
> -    __get_user(si_errno, &tinfo->si_errno);
> -    __get_user(si_code, &info->si_code);
> -
> -    tinfo->si_signo = sig;
> -    tinfo->si_errno = si_errno;
> -    tinfo->si_code = si_code;
> -
> -    /* Ensure we don't leak random junk to the guest later */
> -    memset(tinfo->_sifields._pad, 0, sizeof(tinfo->_sifields._pad));
> -
> -    /* This is awkward, because we have to use a combination of
> -     * the si_code and si_signo to figure out which of the union's
> -     * members are valid. (Within the host kernel it is always possible
> -     * to tell, but the kernel carefully avoids giving userspace the
> -     * high 16 bits of si_code, so we don't have the information to
> -     * do this the easy way...) We therefore make our best guess,
> -     * bearing in mind that a guest can spoof most of the si_codes
> -     * via rt_sigqueueinfo() if it likes.
> -     *
> -     * Once we have made our guess, we record it in the top 16 bits of
> -     * the si_code, so that print_siginfo() later can use it.
> -     * print_siginfo() will strip these top bits out before printing
> -     * the si_code.
> -     */
> -
> -    switch (si_code) {
> -    case SI_USER:
> -    case SI_TKILL:
> -    case SI_KERNEL:
> -        /* Sent via kill(), tkill() or tgkill(), or direct from the
kernel.
> -         * These are the only unspoofable si_code values.
> -         */
> -        __get_user(tinfo->_sifields._kill._pid,
&info->_sifields._kill._pid);
> -        __get_user(tinfo->_sifields._kill._uid,
&info->_sifields._kill._uid);
> -        si_type = QEMU_SI_KILL;
> -        break;
> -    default:
> -        /* Everything else is spoofable. Make best guess based on signal
*/
> -        switch (sig) {
> -        case TARGET_SIGCHLD:
> -            __get_user(tinfo->_sifields._sigchld._pid,
> -                       &info->_sifields._sigchld._pid);
> -            __get_user(tinfo->_sifields._sigchld._uid,
> -                       &info->_sifields._sigchld._uid);
> -            __get_user(tinfo->_sifields._sigchld._status,
> -                       &info->_sifields._sigchld._status);
> -            __get_user(tinfo->_sifields._sigchld._utime,
> -                       &info->_sifields._sigchld._utime);
> -            __get_user(tinfo->_sifields._sigchld._stime,
> -                       &info->_sifields._sigchld._stime);
> -            si_type = QEMU_SI_CHLD;
> -            break;
> -        case TARGET_SIGIO:
> -            __get_user(tinfo->_sifields._sigpoll._band,
> -                       &info->_sifields._sigpoll._band);
> -            __get_user(tinfo->_sifields._sigpoll._fd,
> -                       &info->_sifields._sigpoll._fd);
> -            si_type = QEMU_SI_POLL;
> -            break;
> -        default:
> -            /* Assume a sigqueue()/mq_notify()/rt_sigqueueinfo() source.
*/
> -            __get_user(tinfo->_sifields._rt._pid,
&info->_sifields._rt._pid);
> -            __get_user(tinfo->_sifields._rt._uid,
&info->_sifields._rt._uid);
> -            /* XXX: potential problem if 64 bit */
> -            __get_user(sival_ptr,
&info->_sifields._rt._sigval.sival_ptr);
> -            tinfo->_sifields._rt._sigval.sival_ptr = sival_ptr;
> -
> -            si_type = QEMU_SI_RT;
> -            break;
> -        }
> -        break;
> -    }
> -
> -    tinfo->si_code = deposit32(si_code, 16, 16, si_type);
> -}
> -
>  static void print_siginfo(const target_siginfo_t *tinfo)
>  {
>      /* Print a target_siginfo_t in the format desired for printing
> @@ -1585,57 +1498,6 @@ print_fstat(const struct syscallname *name,
>  #define print_fstat64     print_fstat
>  #endif
>
> -#ifdef TARGET_NR_rt_sigqueueinfo
> -static void
> -print_rt_sigqueueinfo(const struct syscallname *name,
> -    abi_long arg0, abi_long arg1, abi_long arg2,
> -    abi_long arg3, abi_long arg4, abi_long arg5)
> -{
> -    void *p;
> -    target_siginfo_t uinfo;
> -
> -    print_syscall_prologue(name);
> -    print_raw_param("%d", arg0, 0);
> -    print_signal(arg1, 0);
> -    p = lock_user(VERIFY_READ, arg2, sizeof(target_siginfo_t), 1);
> -    if (p) {
> -        get_target_siginfo(&uinfo, p);
> -        print_siginfo(&uinfo);
> -
> -        unlock_user(p, arg2, 0);
> -    } else {
> -        print_pointer(arg2, 1);
> -    }
> -    print_syscall_epilogue(name);
> -}
> -#endif
> -
> -#ifdef TARGET_NR_rt_tgsigqueueinfo
> -static void
> -print_rt_tgsigqueueinfo(const struct syscallname *name,
> -    abi_long arg0, abi_long arg1, abi_long arg2,
> -    abi_long arg3, abi_long arg4, abi_long arg5)
> -{
> -    void *p;
> -    target_siginfo_t uinfo;
> -
> -    print_syscall_prologue(name);
> -    print_raw_param("%d", arg0, 0);
> -    print_raw_param("%d", arg1, 0);
> -    print_signal(arg2, 0);
> -    p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
> -    if (p) {
> -        get_target_siginfo(&uinfo, p);
> -        print_siginfo(&uinfo);
> -
> -        unlock_user(p, arg3, 0);
> -    } else {
> -        print_pointer(arg3, 1);
> -    }
> -    print_syscall_epilogue(name);
> -}
> -#endif
> -
>  #ifdef TARGET_NR_syslog
>  static void
>  print_syslog_action(abi_ulong arg, int last)
> diff --git a/linux-user/syscall-sig.inc.c b/linux-user/syscall-sig.inc.c
> index 5f2c0ba499..774346838b 100644
> --- a/linux-user/syscall-sig.inc.c
> +++ b/linux-user/syscall-sig.inc.c
> @@ -191,6 +191,21 @@ SYSCALL_IMPL(rt_sigprocmask)
>      return ret;
>  }
>
> +SYSCALL_IMPL(rt_sigqueueinfo)
> +{
> +    siginfo_t uinfo;
> +    void *p;
> +
> +    p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
> +    if (!p) {
> +        return -TARGET_EFAULT;
> +    }
> +    target_to_host_siginfo(&uinfo, p);
> +    unlock_user(p, arg3, 0);
> +
> +    return get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
> +}
> +
>  SYSCALL_IMPL(rt_sigsuspend)
>  {
>      CPUState *cpu = ENV_GET_CPU(cpu_env);
> @@ -252,6 +267,21 @@ SYSCALL_IMPL(rt_sigtimedwait)
>      return ret;
>  }
>
> +SYSCALL_IMPL(rt_tgsigqueueinfo)
> +{
> +    siginfo_t uinfo;
> +    void *p;
> +
> +    p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
> +    if (!p) {
> +        return -TARGET_EFAULT;
> +    }
> +    target_to_host_siginfo(&uinfo, p);
> +    unlock_user(p, arg4, 0);
> +
> +    return get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo));
> +}
> +
>  #ifdef TARGET_NR_sigaction
>  SYSCALL_IMPL(sigaction)
>  {
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 8a05d3e32a..e489d12103 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -4240,32 +4240,6 @@ static abi_long do_syscall1(void *cpu_env, int
num, abi_long arg1,
>      void *p;
>
>      switch(num) {
> -    case TARGET_NR_rt_sigqueueinfo:
> -        {
> -            siginfo_t uinfo;
> -
> -            p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t),
1);
> -            if (!p) {
> -                return -TARGET_EFAULT;
> -            }
> -            target_to_host_siginfo(&uinfo, p);
> -            unlock_user(p, arg3, 0);
> -            ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
> -        }
> -        return ret;
> -    case TARGET_NR_rt_tgsigqueueinfo:
> -        {
> -            siginfo_t uinfo;
> -
> -            p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t),
1);
> -            if (!p) {
> -                return -TARGET_EFAULT;
> -            }
> -            target_to_host_siginfo(&uinfo, p);
> -            unlock_user(p, arg4, 0);
> -            ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3,
&uinfo));
> -        }
> -        return ret;
>  #ifdef TARGET_NR_sigreturn
>      case TARGET_NR_sigreturn:
>          if (block_signals()) {
> diff --git a/linux-user/strace.list b/linux-user/strace.list
> index 0b2c057673..57445a8d81 100644
> --- a/linux-user/strace.list
> +++ b/linux-user/strace.list
> @@ -926,15 +926,9 @@
>  #ifdef TARGET_NR_rmdir
>  { TARGET_NR_rmdir, "rmdir" , NULL, NULL, NULL },
>  #endif
> -#ifdef TARGET_NR_rt_sigqueueinfo
> -{ TARGET_NR_rt_sigqueueinfo, "rt_sigqueueinfo" , NULL,
print_rt_sigqueueinfo, NULL },
> -#endif
>  #ifdef TARGET_NR_rt_sigreturn
>  { TARGET_NR_rt_sigreturn, "rt_sigreturn" , NULL, NULL, NULL },
>  #endif
> -#ifdef TARGET_NR_rt_tgsigqueueinfo
> -{ TARGET_NR_rt_tgsigqueueinfo, "rt_tgsigqueueinfo" , NULL,
print_rt_tgsigqueueinfo, NULL },
> -#endif
>  #ifdef TARGET_NR_sched_getaffinity
>  { TARGET_NR_sched_getaffinity, "sched_getaffinity" , NULL, NULL, NULL },
>  #endif
> --
> 2.17.1
>
>

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (73 preceding siblings ...)
  2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 74/74] linux-user: Split out getpriority, setpriority Richard Henderson
@ 2019-05-20  6:21 ` Laurent Vivier
  2019-05-20  9:42 ` Peter Maydell
  2019-05-22  6:11 ` Aleksandar Markovic
  76 siblings, 0 replies; 81+ messages in thread
From: Laurent Vivier @ 2019-05-20  6:21 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

On 19/05/2019 22:36, Richard Henderson wrote:
> Based-on: <20190519201953.20161-1-richard.henderson@linaro.org>
> Aka "linux-user: path, clone, sparc, shmat fixes"
> 
> Version 6 was
> https://lists.gnu.org/archive/html/qemu-devel/2019-01/msg04794.html
> 
> Since v5, I've fixed the ioctl failure that Laurent found, and
> have done a few more syscalls.
> 
> I've tried to do more testing with LTP, but it's a really annoying
> testsuite.  There are at least 3 tests that hang forever (before
> and after this patch set), and the host kernel's OOM handler kills
> my login session, ending the test run.  This seems to be different
> behaviour than I was seeing in January, when I did have test runs
> that completed successfully.
> 
> OTOH, looking back at the v6 cover letter, I now see that I was
> testing armhf and i386 as guests, whereas this time I was trying
> aarch64 and ppc64 as guests.  32-bit guests unable to trigger the
> host OOM killer?
> 
> Laurent, is there anything special that you're doing to see these
> tests run to completion?

I'm running them in a container ('unshare chroot') and aarch64 needs a 
patch that hasn't been merged:

   "[PATCH] linux-user: check valid address in access_ok()"
   https://patchew.org/QEMU/20190208173520.15007-1-remi@remlab.net/

I have a skipfile that contains:

futex_wait03
mmap13
mmap16
msgctl10
msgctl11
ptrace01
ptrace02
ptrace03
ptrace05
remap_file_pages01
remap_file_pages02
sendmsg01
fork13
fork14
creat07
mremap03

but I didn't update it for a while.

I will test as soon as possible your series in my environment.

Thanks,
Laurent


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (74 preceding siblings ...)
  2019-05-20  6:21 ` [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Laurent Vivier
@ 2019-05-20  9:42 ` Peter Maydell
  2019-05-20 10:13   ` Aleksandar Markovic
  2019-05-22  6:11 ` Aleksandar Markovic
  76 siblings, 1 reply; 81+ messages in thread
From: Peter Maydell @ 2019-05-20  9:42 UTC (permalink / raw)
  To: Richard Henderson; +Cc: QEMU Developers, Laurent Vivier

On Sun, 19 May 2019 at 21:39, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Based-on: <20190519201953.20161-1-richard.henderson@linaro.org>
> Aka "linux-user: path, clone, sparc, shmat fixes"
>
> Version 6 was
> https://lists.gnu.org/archive/html/qemu-devel/2019-01/msg04794.html
>
> Since v5, I've fixed the ioctl failure that Laurent found, and
> have done a few more syscalls.
>
> I've tried to do more testing with LTP, but it's a really annoying
> testsuite.  There are at least 3 tests that hang forever (before
> and after this patch set), and the host kernel's OOM handler kills
> my login session, ending the test run.  This seems to be different
> behaviour than I was seeing in January, when I did have test runs
> that completed successfully.

If these are different from the ones we're already skipping
in the skiplist documented at https://wiki.qemu.org/Testing/LTP
we should update that wiki page to also skip these new
hanging-tests (and whatever it is that eats all the memory).

thanks
-- PMM


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall
  2019-05-20  9:42 ` Peter Maydell
@ 2019-05-20 10:13   ` Aleksandar Markovic
  0 siblings, 0 replies; 81+ messages in thread
From: Aleksandar Markovic @ 2019-05-20 10:13 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Richard Henderson, Laurent Vivier, QEMU Developers

On May 20, 2019 11:43 AM, "Peter Maydell" <peter.maydell@linaro.org> wrote:
>
> On Sun, 19 May 2019 at 21:39, Richard Henderson
> <richard.henderson@linaro.org> wrote:
> >
> > Based-on: <20190519201953.20161-1-richard.henderson@linaro.org>
> > Aka "linux-user: path, clone, sparc, shmat fixes"
> >
> > Version 6 was
> > https://lists.gnu.org/archive/html/qemu-devel/2019-01/msg04794.html
> >
> > Since v5, I've fixed the ioctl failure that Laurent found, and
> > have done a few more syscalls.
> >
> > I've tried to do more testing with LTP, but it's a really annoying
> > testsuite.  There are at least 3 tests that hang forever (before
> > and after this patch set), and the host kernel's OOM handler kills
> > my login session, ending the test run.  This seems to be different
> > behaviour than I was seeing in January, when I did have test runs
> > that completed successfully.
>
> If these are different from the ones we're already skipping
> in the skiplist documented at https://wiki.qemu.org/Testing/LTP
> we should update that wiki page to also skip these new
> hanging-tests (and whatever it is that eats all the memory).
>

Peter, yes, it is definitely different. It has been a moving target lately.
May I suggest that we use a stable version of QEMU, and a stable version of
LTP, and create a skiplist for such stable configuration, include it in the
docs, explicitely noting used versions? We can continue doing that for each
QEMU release and whatever the latest LTP would be at the moment of that
QEMU release (maybe even keeping the previous skiplists - which could be
useful for debugging).

Regards,
Aleksandar

> thanks
> -- PMM
>

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall
  2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
                   ` (75 preceding siblings ...)
  2019-05-20  9:42 ` Peter Maydell
@ 2019-05-22  6:11 ` Aleksandar Markovic
       [not found]   ` <CAL1e-=i_=EQ02A1DGmVgqNi1ik=h39FZTOsxkGWfMa4ZoM6rjg@mail.gmail.com>
  76 siblings, 1 reply; 81+ messages in thread
From: Aleksandar Markovic @ 2019-05-22  6:11 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, laurent

On May 19, 2019 10:38 PM, "Richard Henderson" <richard.henderson@linaro.org>
wrote:
>
> Based-on: <20190519201953.20161-1-richard.henderson@linaro.org>
> Aka "linux-user: path, clone, sparc, shmat fixes"
>
> Version 6 was
> https://lists.gnu.org/archive/html/qemu-devel/2019-01/msg04794.html
>
> Since v5, I've fixed the ioctl failure that Laurent found, and
> have done a few more syscalls.
>
> I've tried to do more testing with LTP, but it's a really annoying
> testsuite.  There are at least 3 tests that hang forever (before
> and after this patch set), and the host kernel's OOM handler kills
> my login session, ending the test run.  This seems to be different
> behaviour than I was seeing in January, when I did have test runs
> that completed successfully.
>
> OTOH, looking back at the v6 cover letter, I now see that I was
> testing armhf and i386 as guests, whereas this time I was trying
> aarch64 and ppc64 as guests.  32-bit guests unable to trigger the
> host OOM killer?
>
> Laurent, is there anything special that you're doing to see these
> tests run to completion?
>

On surface, this series looks to be a refactoring series. However, this is
not the case: burried in various patches, are removals of some features
visible to the end user. Can you please list all such cases in the cover
letter, so that they can be easier identified and evaluated by reviewers?

Thanks,
Aleksandar

>
> r~
>
>
> Richard Henderson (74):
>   linux-user: Setup split syscall infrastructure
>   linux-user: Split out open, open_at
>   linux-user: Share more code for open and openat
>   linux-user: Tidy do_openat loop over fakes
>   linux-user: Split out readlink, readlinkat
>   linux-user: Split out close
>   linux-user: Split out read, write
>   linux-user: Reduce regpairs_aligned & target_offset64 ifdefs
>   linux-user: Split out readv, writev
>   linux-user: Split out pread64, pwrite64
>   linux-user: Split out preadv, pwritev
>   linux-user: Split out name_to_handle_at, open_by_handle_at
>   linux-user: Split out ipc syscalls
>   linux-user: Split out memory syscalls
>   linux-user: Split out exit
>   linux-user: Split out brk
>   linux-user: Split out clone, fork, vfork
>   linux-user: Split out wait4, waitid, waitpid
>   linux-user: Implement rusage argument to waitid
>   linux-user: Split out creat
>   linux-user: Split out link, linkat
>   linux-user: Split out unlink, unlinkat, rmdir
>   linux-user: Split out execve
>   linux-user: Implement execveat
>   linux-user: Split out chdir
>   linux-user: Split out time
>   linux-user: Split out mknod, mknodat
>   linux-user: Split out chmod, fchmod, fchmodat
>   linux-user: Split out lseek, llseek
>   linux-user: Split out getpid, getppid, getxpid
>   linux-user: Split out mount
>   linux-user: Split out umount, umount2
>   linux-user: Split out stime
>   linux-user: Split out alarm, pause
>   linux-user: Split out utime, utimes, futimesat
>   linux-user: Split out access, faccessat
>   linux-user: Split out nice
>   linux-user: Split out sync, syncfs
>   linux-user: Split out kill
>   linux-user: Split out rename, renameat, renameat2
>   linux-user: Split out mkdir, mkdirat
>   linux-user: Split out dup, dup2, dup3
>   linux-user: Split out pipe, pipe2
>   linux-user: Split out times
>   linux-user: Split out acct
>   linux-user: Move syscall_init to the end
>   linux-user: Split out ioctl
>   linux-user: Fix types in ioctl logging
>   linux-user: Remove sentinel from ioctl_entries
>   linux-user: Split out fcntl, fcntl64
>   linux-user: Split out setpgid
>   linux-user: Split out umask
>   linux-user: Split out chroot
>   linux-user: Split out getpgid, getpgrp
>   linux-user: Split out getsid, setsid
>   linux-user: Split out sigaction, rt_sigaction
>   linux-user: Split out sgetmask, ssetmask
>   linux-user: Split out sigprocmask, rt_sigprocmask
>   linux-user: Split out sigpending, rt_sigpending
>   linux-user: Split out sigsuspend, rt_sigsuspend
>   linux-user: Split out rt_sigtimedwait
>   linux-user: Split out rt_sigqueueinfo, rt_tgsigqueueinfo
>   linux-user: Split out sigreturn, rt_sigreturn
>   linux-user: Split out gethostname, sethostname
>   linux-user: Split out getrlimit, setrlimit
>   linux-user: Split out getrusage
>   linux-user: Split out gettimeofday, settimeofday
>   linux-user: Split out select, _newselect
>   linux-user: Split out pselect6
>   linux-user: Split out symlink, symlinkat
>   linux-user: Split out swapon, swapoff
>   linux-user: Split out reboot
>   linux-user: Split out truncate, truncate64, ftruncate, ftruncate64
>   linux-user: Split out getpriority, setpriority
>
>  linux-user/syscall-defs.h      |  338 +++
>  linux-user/syscall.h           |  103 +
>  linux-user/strace.c            | 1569 +++-------
>  linux-user/syscall-fcntl.inc.c |  322 ++
>  linux-user/syscall-file.inc.c  | 1526 ++++++++++
>  linux-user/syscall-ioctl.inc.c |  873 ++++++
>  linux-user/syscall-ipc.inc.c   | 1088 +++++++
>  linux-user/syscall-mem.inc.c   |  244 ++
>  linux-user/syscall-proc.inc.c  |  758 +++++
>  linux-user/syscall-sig.inc.c   |  549 ++++
>  linux-user/syscall-time.inc.c  |   77 +
>  linux-user/syscall.c           | 5045 ++------------------------------
>  configure                      |   20 -
>  linux-user/strace.list         |  414 ---
>  14 files changed, 6512 insertions(+), 6414 deletions(-)
>  create mode 100644 linux-user/syscall-defs.h
>  create mode 100644 linux-user/syscall.h
>  create mode 100644 linux-user/syscall-fcntl.inc.c
>  create mode 100644 linux-user/syscall-file.inc.c
>  create mode 100644 linux-user/syscall-ioctl.inc.c
>  create mode 100644 linux-user/syscall-ipc.inc.c
>  create mode 100644 linux-user/syscall-mem.inc.c
>  create mode 100644 linux-user/syscall-proc.inc.c
>  create mode 100644 linux-user/syscall-sig.inc.c
>  create mode 100644 linux-user/syscall-time.inc.c
>
> --
> 2.17.1
>
>

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall
       [not found]   ` <CAL1e-=i_=EQ02A1DGmVgqNi1ik=h39FZTOsxkGWfMa4ZoM6rjg@mail.gmail.com>
@ 2019-05-22 11:29     ` Richard Henderson
  0 siblings, 0 replies; 81+ messages in thread
From: Richard Henderson @ 2019-05-22 11:29 UTC (permalink / raw)
  To: Aleksandar Markovic, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1336 bytes --]

[Adding the mailing list back in.]

On 5/22/19 2:47 AM, Aleksandar Markovic wrote:
>> > Version 6 was
>> > https://lists.gnu.org/archive/html/qemu-devel/2019-01/msg04794.html
>> >
>> > Since v5, I've fixed the ioctl failure that Laurent found, and
>> > have done a few more syscalls.
>> >
>> > I've tried to do more testing with LTP....
> 
> Running LTP is certainly a very important way of testing this series. However,
> it is not sufficient. This is because this series completely replaces internal
> QEMU strace mechanism for involved system calls,

What you missed because of the very large time lag between iterations, and
because I was lazy and only referenced v6 in this cover letter, is that in an
early revision the major objection was that I *wasn't* replacing strace, and
thus we were retaining lots of duplicate logic in multiple places.


> and any bug in such
> replacement would not be captured by LTP results. How did you test new strace
> bits and peaces? Can you provide logs of such tests (for example, before/after
> comparisons of strace output for relevant system calls, or similar)?

My strace testing is totally ad-hoc.  Run something with -strace and eyeball it.

Here are before/after logs for busybox ls (aka linux-user-test-0.3, which has
for some reason vanished from the qemu wiki?) for alpha-linux-user.

[-- Attachment #2: ls-strace-before --]
[-- Type: text/plain, Size: 2691 bytes --]

657 uname(0x40008014b8) = 0
657 brk(NULL) = 0x000000012006a000
657 access("/etc/ld.so.nohwcap",F_OK) = -1 errno=2 (No such file or directory)
657 mmap(NULL,8192,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0x000000400082e000
657 access("/etc/ld.so.preload",R_OK) = -1 errno=2 (No such file or directory)
657 open("/etc/ld.so.cache",O_RDONLY) = 3
657 fstat64(3,0x0000004000800c30) = 0
657 close(3) = 0
657 open("/lib/tls/libc.so.6.1",O_RDONLY) = -1 errno=2 (No such file or directory)
657 stat64("/lib/tls",0x0000004000800bb0) = -1 errno=2 (No such file or directory)
657 open("/lib/libc.so.6.1",O_RDONLY) = 3
657 read(3,0x800da8,640) = 640
657 fstat64(3,0x0000004000800c30) = 0
657 mmap(NULL,927824,PROT_EXEC|PROT_READ,MAP_PRIVATE|MAP_DENYWRITE,3,0) = 0x0000004000830000
657 mprotect(0x00000040008f2000,133200,PROT_NONE) = 0
657 mmap(0x0000004000902000,65536,PROT_EXEC|PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_DENYWRITE|MAP_FIXED,3,0xc2000) = 0x0000004000902000
657 mmap(0x0000004000912000,2128,PROT_EXEC|PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0) = 0x0000004000912000
657 close(3) = 0
657 mprotect(0x000000400082a000,8192,PROT_READ) = 0
657 getxuid(274886302098,4832112143,77,24,4831859744,274886356864) = 1000
657 getxgid(274886302098,4832112143,77,0,1000,274886356864) = 1000
657 setgid(1000,4832112143,77,0,1000,274886356864) = 0
657 setuid(1000,4832112143,77,0,1000,274886356864) = 0
657 ioctl(1,1074295912,274886301072,0,1000,274886356864) = 0
657 lstat64("dummyfile",0x0000004000801510) = 0
657 brk(NULL) = 0x000000012006a000
657 brk(0x000000012008c000) = 0x000000012008c000
657 open("/etc/localtime",O_RDONLY) = 3
657 fstat64(3,0x0000004000801360) = 0
657 fstat64(3,0x00000040008011f0) = 0
657 mmap(NULL,8192,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0x0000004000914000
657 read(3,0x914000,4096) = 3545
657 close(3) = 0
657 munmap(0x0000004000914000,8192) = 0
657 fstat64(1,0x0000004000800c70) = 0
657 mmap(NULL,8192,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0x0000004000916000
657 open("/etc/passwd",O_RDONLY) = 3
657 fstat64(3,0x0000004000801290) = 0
657 mmap(NULL,8192,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0x0000004000918000
657 read(3,0x918000,4096) = 2727
657 close(3) = 0
657 munmap(0x0000004000918000,8192) = 0
657 open("/etc/group",O_RDONLY) = 3
657 fstat64(3,0x0000004000801290) = 0
657 mmap(NULL,8192,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0x000000400091a000
657 read(3,0x91a000,4096) = 1043
657 close(3) = 0
657 munmap(0x000000400091a000,8192) = 0
657 gettimeofday(274886300912,0,1,0,103,1024) = 0
657 write(1,0x916000,66) = 66
657 munmap(0x0000004000916000,8192) = 0
657 exit_group(0)

[-- Attachment #3: ls-strace-after --]
[-- Type: text/plain, Size: 2899 bytes --]

17862 uname(0x40008014b8) = 0
17862 brk(NULL) = 0x000000012006a000
17862 access("/etc/ld.so.nohwcap", F_OK) = -1 errno=2 (No such file or directory)
17862 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x000000400082e000
17862 access("/etc/ld.so.preload", R_OK) = -1 errno=2 (No such file or directory)
17862 open("/etc/ld.so.cache", O_RDONLY, 01) = 3
17862 fstat64(3,0x0000004000800c30) = 0
17862 close(3) = 0
17862 open("/lib/tls/libc.so.6.1", O_RDONLY, 014) = -1 errno=2 (No such file or directory)
17862 stat64("/lib/tls",0x0000004000800bb0) = -1 errno=2 (No such file or directory)
17862 open("/lib/libc.so.6.1", O_RDONLY, 014) = 3
17862 read(3, 0x0000004000800da8, 640) = 640
17862 fstat64(3,0x0000004000800c30) = 0
17862 mmap(NULL, 927824, PROT_EXEC|PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x0000004000830000
17862 mprotect(0x00000040008f2000, 133200, PROT_NONE) = 0
17862 mmap(0x0000004000902000, 65536, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_DENYWRITE|MAP_FIXED, 3, 794624) = 0x0000004000902000
17862 mmap(0x0000004000912000, 2128, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0) = 0x0000004000912000
17862 close(3) = 0
17862 mprotect(0x000000400082a000, 8192, PROT_READ) = 0
17862 getxuid(274886302098,4832112143,77,24,4831859744,274886356864) = 1000
17862 getxgid(274886302098,4832112143,77,0,1000,274886356864) = 1000
17862 setgid(1000,4832112143,77,0,1000,274886356864) = 0
17862 setuid(1000,4832112143,77,0,1000,274886356864) = 0
17862 ioctl(1, 40087468) = 0
17862 lstat64("dummyfile",0x0000004000801510) = 0
17862 brk(NULL) = 0x000000012006a000
17862 brk(0x000000012008c000) = 0x000000012008c000
17862 open("/etc/localtime", O_RDONLY, 0666) = 3
17862 fstat64(3,0x0000004000801360) = 0
17862 fstat64(3,0x00000040008011f0) = 0
17862 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x0000004000914000
17862 read(3, 0x0000004000914000, 4096) = 3545
17862 close(3) = 0
17862 munmap(0x0000004000914000, 8192) = 0
17862 fstat64(1,0x0000004000800c70) = 0
17862 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x0000004000916000
17862 open("/etc/passwd", O_RDONLY, 0666) = 3
17862 fstat64(3,0x0000004000801290) = 0
17862 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x0000004000918000
17862 read(3, 0x0000004000918000, 4096) = 2727
17862 close(3) = 0
17862 munmap(0x0000004000918000, 8192) = 0
17862 open("/etc/group", O_RDONLY, 0666) = 3
17862 fstat64(3,0x0000004000801290) = 0
17862 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x000000400091a000
17862 read(3, 0x000000400091a000, 4096) = 1043
17862 close(3) = 0
17862 munmap(0x000000400091a000, 8192) = 0
17862 gettimeofday(0x00000040008014f0) = 0
17862 write(1, 0x0000004000916000, 66) = 66
17862 munmap(0x0000004000916000, 8192) = 0
17862 exit_group(0)

^ permalink raw reply	[flat|nested] 81+ messages in thread

end of thread, other threads:[~2019-05-22 11:30 UTC | newest]

Thread overview: 81+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-19 20:36 [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 01/74] linux-user: Setup split syscall infrastructure Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 02/74] linux-user: Split out open, open_at Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 03/74] linux-user: Share more code for open and openat Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 04/74] linux-user: Tidy do_openat loop over fakes Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 05/74] linux-user: Split out readlink, readlinkat Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 06/74] linux-user: Split out close Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 07/74] linux-user: Split out read, write Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 08/74] linux-user: Reduce regpairs_aligned & target_offset64 ifdefs Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 09/74] linux-user: Split out readv, writev Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 10/74] linux-user: Split out pread64, pwrite64 Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 11/74] linux-user: Split out preadv, pwritev Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 12/74] linux-user: Split out name_to_handle_at, open_by_handle_at Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 13/74] linux-user: Split out ipc syscalls Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 14/74] linux-user: Split out memory syscalls Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 15/74] linux-user: Split out exit Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 16/74] linux-user: Split out brk Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 17/74] linux-user: Split out clone, fork, vfork Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 18/74] linux-user: Split out wait4, waitid, waitpid Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 19/74] linux-user: Implement rusage argument to waitid Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 20/74] linux-user: Split out creat Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 21/74] linux-user: Split out link, linkat Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 22/74] linux-user: Split out unlink, unlinkat, rmdir Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 23/74] linux-user: Split out execve Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 24/74] linux-user: Implement execveat Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 25/74] linux-user: Split out chdir Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 26/74] linux-user: Split out time Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 27/74] linux-user: Split out mknod, mknodat Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 28/74] linux-user: Split out chmod, fchmod, fchmodat Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 29/74] linux-user: Split out lseek, llseek Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 30/74] linux-user: Split out getpid, getppid, getxpid Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 31/74] linux-user: Split out mount Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 32/74] linux-user: Split out umount, umount2 Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 33/74] linux-user: Split out stime Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 34/74] linux-user: Split out alarm, pause Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 35/74] linux-user: Split out utime, utimes, futimesat Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 36/74] linux-user: Split out access, faccessat Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 37/74] linux-user: Split out nice Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 38/74] linux-user: Split out sync, syncfs Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 39/74] linux-user: Split out kill Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 40/74] linux-user: Split out rename, renameat, renameat2 Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 41/74] linux-user: Split out mkdir, mkdirat Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 42/74] linux-user: Split out dup, dup2, dup3 Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 43/74] linux-user: Split out pipe, pipe2 Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 44/74] linux-user: Split out times Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 45/74] linux-user: Split out acct Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 46/74] linux-user: Move syscall_init to the end Richard Henderson
2019-05-19 20:36 ` [Qemu-devel] [PATCH v7 47/74] linux-user: Split out ioctl Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 48/74] linux-user: Fix types in ioctl logging Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 49/74] linux-user: Remove sentinel from ioctl_entries Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 50/74] linux-user: Split out fcntl, fcntl64 Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 51/74] linux-user: Split out setpgid Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 52/74] linux-user: Split out umask Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 53/74] linux-user: Split out chroot Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 54/74] linux-user: Split out getpgid, getpgrp Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 55/74] linux-user: Split out getsid, setsid Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 56/74] linux-user: Split out sigaction, rt_sigaction Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 57/74] linux-user: Split out sgetmask, ssetmask Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 58/74] linux-user: Split out sigprocmask, rt_sigprocmask Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 59/74] linux-user: Split out sigpending, rt_sigpending Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 60/74] linux-user: Split out sigsuspend, rt_sigsuspend Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 61/74] linux-user: Split out rt_sigtimedwait Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 62/74] linux-user: Split out rt_sigqueueinfo, rt_tgsigqueueinfo Richard Henderson
2019-05-20  6:04   ` Aleksandar Markovic
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 63/74] linux-user: Split out sigreturn, rt_sigreturn Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 64/74] linux-user: Split out gethostname, sethostname Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 65/74] linux-user: Split out getrlimit, setrlimit Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 66/74] linux-user: Split out getrusage Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 67/74] linux-user: Split out gettimeofday, settimeofday Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 68/74] linux-user: Split out select, _newselect Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 69/74] linux-user: Split out pselect6 Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 70/74] linux-user: Split out symlink, symlinkat Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 71/74] linux-user: Split out swapon, swapoff Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 72/74] linux-user: Split out reboot Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 73/74] linux-user: Split out truncate, truncate64, ftruncate, ftruncate64 Richard Henderson
2019-05-19 20:37 ` [Qemu-devel] [PATCH v7 74/74] linux-user: Split out getpriority, setpriority Richard Henderson
2019-05-20  6:21 ` [Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall Laurent Vivier
2019-05-20  9:42 ` Peter Maydell
2019-05-20 10:13   ` Aleksandar Markovic
2019-05-22  6:11 ` Aleksandar Markovic
     [not found]   ` <CAL1e-=i_=EQ02A1DGmVgqNi1ik=h39FZTOsxkGWfMa4ZoM6rjg@mail.gmail.com>
2019-05-22 11:29     ` Richard Henderson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.