[Qemu-devel] [PATCH v5 6/6] linux-user: Add support for statx() syscall

2019-05-19 Thread Aleksandar Markovic
From: Aleksandar Rikalo 

Implement support for translation of system call statx(). The
implementation includes invoking other (more mature) system calls
(from the same 'stat' family) on the host side. This way, the
problems of potential lack of statx() availability of on the host
side are avoided.

Support for statx() in kernel and glibc was unfortunately introduced
in different points of time (the difference is more than a year):

  - kernel: Linux 4.11 (30 April 2017)
  - glibc: glibc 2.28 (1 Aug 2018)

In this patch, the availability of statx() support is established
via __NR_statx (if it is defined, statx() is considered available).
This coincedes with statx() introduction in kernel.

However, the structure statx may not be available for hosts with
glibc older than 2.28, even though the statx() functionality may
be supported in kernel, if the kernel is not older than 4.11. Hence,
a structure "target_statx" is defined in this patch, to remove that
dependency on glibc headers. It is used for both target and host
structures statx (of course, endian conversion is done in all
needed cases).

Signed-off-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 linux-user/syscall.c  | 135 +-
 linux-user/syscall_defs.h |  37 +
 2 files changed, 171 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index d8f95c5..aea2000 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -6429,6 +6430,48 @@ static inline abi_long host_to_target_stat64(void 
*cpu_env,
 }
 #endif
 
+#if defined(TARGET_NR_statx) && defined(__NR_statx)
+static inline abi_long host_to_target_statx(struct target_statx *host_stx,
+abi_ulong target_addr)
+{
+struct target_statx *target_stx;
+
+if (!lock_user_struct(VERIFY_WRITE, target_stx, target_addr,  0)) {
+return -TARGET_EFAULT;
+}
+memset(target_stx, 0, sizeof(*target_stx));
+
+__put_user(host_stx->stx_mask, _stx->stx_mask);
+__put_user(host_stx->stx_blksize, _stx->stx_blksize);
+__put_user(host_stx->stx_attributes, _stx->stx_attributes);
+__put_user(host_stx->stx_nlink, _stx->stx_nlink);
+__put_user(host_stx->stx_uid, _stx->stx_uid);
+__put_user(host_stx->stx_gid, _stx->stx_gid);
+__put_user(host_stx->stx_mode, _stx->stx_mode);
+__put_user(host_stx->stx_ino, _stx->stx_ino);
+__put_user(host_stx->stx_size, _stx->stx_size);
+__put_user(host_stx->stx_blocks, _stx->stx_blocks);
+__put_user(host_stx->stx_attributes_mask, 
_stx->stx_attributes_mask);
+__put_user(host_stx->stx_atime.tv_sec, _stx->stx_atime.tv_sec);
+__put_user(host_stx->stx_atime.tv_nsec, _stx->stx_atime.tv_nsec);
+__put_user(host_stx->stx_btime.tv_sec, _stx->stx_atime.tv_sec);
+__put_user(host_stx->stx_btime.tv_nsec, _stx->stx_atime.tv_nsec);
+__put_user(host_stx->stx_ctime.tv_sec, _stx->stx_atime.tv_sec);
+__put_user(host_stx->stx_ctime.tv_nsec, _stx->stx_atime.tv_nsec);
+__put_user(host_stx->stx_mtime.tv_sec, _stx->stx_atime.tv_sec);
+__put_user(host_stx->stx_mtime.tv_nsec, _stx->stx_atime.tv_nsec);
+__put_user(host_stx->stx_rdev_major, _stx->stx_rdev_major);
+__put_user(host_stx->stx_rdev_minor, _stx->stx_rdev_minor);
+__put_user(host_stx->stx_dev_major, _stx->stx_dev_major);
+__put_user(host_stx->stx_dev_minor, _stx->stx_dev_minor);
+
+unlock_user_struct(target_stx, target_addr, 1);
+
+return 0;
+}
+#endif
+
+
 /* ??? Using host futex calls even when target atomic operations
are not really atomic probably breaks things.  However implementing
futexes locally would make futexes shared between multiple processes
@@ -6982,7 +7025,8 @@ static abi_long do_syscall1(void *cpu_env, int num, 
abi_long arg1,
 abi_long ret;
 #if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) \
 || defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) \
-|| defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64)
+|| defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) \
+|| defined(TARGET_NR_statx)
 struct stat st;
 #endif
 #if defined(TARGET_NR_statfs) || defined(TARGET_NR_statfs64) \
@@ -10031,6 +10075,95 @@ static abi_long do_syscall1(void *cpu_env, int num, 
abi_long arg1,
 ret = host_to_target_stat64(cpu_env, arg3, );
 return ret;
 #endif
+#if defined(TARGET_NR_statx)
+case TARGET_NR_statx:
+{
+struct target_statx *target_stx;
+int dirfd = arg1;
+int flags = arg3;
+
+p = lock_user_string(arg2);
+if (p == NULL) {
+return -TARGET_EFAULT;
+}
+#if defined(__NR_statx)
+{
+/*
+ * It is assumed that struct statx is arhitecture independent
+ */
+struct 

[Qemu-devel] [PATCH v5 4/6] linux-user: Add support for setsockopt() options IPV6__MEMBERSHIP

2019-05-19 Thread Aleksandar Markovic
From: Neng Chen 

Add support for options IPV6_ADD_MEMBERSHIP and IPV6_DROP_MEMPEMBERSHIP
of the syscall setsockopt(). These options control membership in
multicast groups. Their argument is a pointer to a struct ipv6_mreq,
which is in turn defined in IP v6 headers as:

struct ipv6_mreq {
/* IPv6 multicast address of group */
struct  in6_addr  ipv6mr_multiaddr;
/* local IPv6 address of interface */
int ipv6mr_interface;
};

...whereas its definition in kernel (include/uapi/linux/in6.h) is:

struct ipv6_mreq {
/* IPv6 multicast address of group */
struct  in6_addr ipv6mr_multiaddr;
/* local IPv6 address of interface */
int ipv6mr_ifindex;
};

The first field of ipv6_mreq has the same name ("ipv6mr_multiaddr")
and type ("in6_addr") in both cases. Moreover, the in6_addr structure
consists of fields that are always big-endian (on host of any endian),
therefore the ipv6_mreq's field ipv6mr_multiaddr doesn't need any
endian conversion.

The second field of ipv6_mreq may, however, depending on the build
environment, have different names. This is the reason why the line
"#if __UAPI_DEF_IPV6_MREQ" is used in this patch - to establish the
right choice for the field name. Also, endian conversion is needed
fot this field, since it is of type "int".

Signed-off-by: Neng Chen 
Signed-off-by: Aleksandar Markovic 
---
 linux-user/syscall.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 96cd4bf..d8f95c5 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1892,6 +1892,31 @@ static abi_long do_setsockopt(int sockfd, int level, int 
optname,
, sizeof(pki)));
 break;
 }
+case IPV6_ADD_MEMBERSHIP:
+case IPV6_DROP_MEMBERSHIP:
+{
+struct ipv6_mreq ipv6mreq;
+
+if (optlen < sizeof(ipv6mreq)) {
+return -TARGET_EINVAL;
+}
+
+if (copy_from_user(, optval_addr, sizeof(ipv6mreq))) {
+return -TARGET_EFAULT;
+}
+
+#if __UAPI_DEF_IPV6_MREQ
+ipv6mreq.ipv6mr_ifindex = tswap32(ipv6mreq.ipv6mr_ifindex);
+#else
+ipv6mreq.ipv6mr_interface = tswap32(ipv6mreq.ipv6mr_interface);
+#endif /* __UAPI_DEF_IVP6_MREQ */
+
+ipv6mreq.ipv6mr_interface = tswap32(ipv6mreq.ipv6mr_interface);
+
+ret = get_errno(setsockopt(sockfd, level, optname,
+   , sizeof(ipv6mreq)));
+break;
+}
 default:
 goto unimplemented;
 }
-- 
2.7.4




Re: [Qemu-devel] [PULL 00/10] MIPS queue for May 19th, 2019

2019-05-19 Thread Jakub Jermar
On 5/19/19 5:16 PM, Aleksandar Markovic wrote:
>> From: Jakub Jermar 
>>
>> On 5/19/19 2:00 PM, Aleksandar Markovic wrote:
>
>   * A fix for HelenOS boot hang (related to the flag PAGE_EXEC)

 This was rather a problem with failing non-executable page tests in
 L4Re, not HelenOS. Even though I tested HelenOS for regressions.
>>>
>>> OK, Jakub, what would be your suggestion for a high-level description
>>> of this message for end users (it is definitely a change that affects end
>>> user)? Something like" Improved PAGE_EXEC flag handling"?
>>
>> It makes sure that referenced pages are not automatically marked
>> executable by QEMU (despite the XI bit).
>>
>> As a user-visible change, this might unbreak some tests that attempt to
>> execute data. Note that this fix does not affect pages that are not
>> referenced prior to being executed - those have worked fine.
>>
>> Otherwise for normal code that does not attempt to execute data, things
>> should not change at all.
>>
> 
> I changed the first item in MIPS section of 4.1 release notes (change log)
> to be:
> 
> * Marking referenced memory pages as executable is improved (it is restricted 
> to necessary cases only).

Sounds good.

> Thanks for your engaging in this issue!

You are welcome.

Thanks to all for reviewing and testing this.

Jakub

> 
> Aleksandar
> 
> 
>> Cheers,
>> Jakub
>>
>>> Thanks,
>>> Aleksandar
>>>
>>
>> --
>> Kernkonzept GmbH at Dresden, Germany, HRB 31129, CEO Dr.-Ing. Michael
>> Hohmuth

-- 
Kernkonzept GmbH at Dresden, Germany, HRB 31129, CEO Dr.-Ing. Michael
Hohmuth



[Qemu-devel] [PATCH v6 5/6] linux-user: Sanitize interp_info and, for mips only, init field fp_abi

2019-05-19 Thread Aleksandar Markovic
From: Daniel Santos 

Sanitize interp_info structure in load_elf_binary() and, for MIPS only,
init its field fp_abi to MIPS_ABI_FP_UNKNOWN. This fixes appearances of
"Unexpected FPU mode" message in some MIPS use cases. Currently, this
bug is a complete stopper for some MIPS binaries.

In load_elf_binary(), struct image_info interp_info is used without
being properly initialized. One result is that when the ELF's program
header doesn't contain an entry for the ABI flags, then the value of
the struct image_info's fp_abi field is set to whatever happened to
be in stack memory at the time.

Backporting to 4.0 and, if possible, to 3.1 is recommended.

Fixes: https://bugs.launchpad.net/qemu/+bug/1825002

Signed-off-by: Daniel Santos 
Signed-off-by: Aleksandar Markovic 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
---
 linux-user/elfload.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index c1a2602..7f09d57 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2698,6 +2698,11 @@ int load_elf_binary(struct linux_binprm *bprm, struct 
image_info *info)
 char *elf_interpreter = NULL;
 char *scratch;
 
+memset(_info, 0, sizeof(interp_info));
+#ifdef TARGET_MIPS
+interp_info.fp_abi = MIPS_ABI_FP_UNKNOWN;
+#endif
+
 info->start_mmap = (abi_ulong)ELF_START_MMAP;
 
 load_elf_image(bprm->filename, bprm->fd, info,
-- 
2.7.4




[Qemu-devel] [PATCH 10/13] scripts/qemu-binfmt-conf: Update for sparc64

2019-05-19 Thread Richard Henderson
Also note that we were missing the qemu_target_list entry
for plain sparc; fix that at the same time.

Signed-off-by: Richard Henderson 
---
 scripts/qemu-binfmt-conf.sh | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
index b5a16742a1..9f1580a91c 100755
--- a/scripts/qemu-binfmt-conf.sh
+++ b/scripts/qemu-binfmt-conf.sh
@@ -1,8 +1,8 @@
 #!/bin/sh
 # Enable automatic program execution by the kernel.
 
-qemu_target_list="i386 i486 alpha arm armeb sparc32plus ppc ppc64 ppc64le m68k 
\
-mips mipsel mipsn32 mipsn32el mips64 mips64el \
+qemu_target_list="i386 i486 alpha arm armeb sparc sparc32plus sparc64 \
+ppc ppc64 ppc64le m68k mips mipsel mipsn32 mipsn32el mips64 mips64el \
 sh4 sh4eb s390x aarch64 aarch64_be hppa riscv32 riscv64 xtensa xtensaeb \
 microblaze microblazeel or1k x86_64"
 
@@ -38,6 +38,10 @@ 
sparc32plus_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x
 
sparc32plus_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
 sparc32plus_family=sparc
 
+sparc64_magic='\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2b'
+sparc64_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+sparc64_family=sparc
+
 
ppc_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14'
 
ppc_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
 ppc_family=ppc
-- 
2.17.1




[Qemu-devel] [PATCH 13/13] linux-user: Align mmap_find_vma to host page size

2019-05-19 Thread Richard Henderson
This can avoid stack allocation failures for i386 guest
on ppc64 (64k page) host.

Suggested-by: Laurent Vivier 
Signed-off-by: Richard Henderson 
---
 linux-user/mmap.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 10796b37ac..af41339d57 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -262,6 +262,8 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, 
abi_ulong align)
 abi_ulong addr;
 int wrapped, repeat;
 
+align = MAX(align, qemu_host_page_size);
+
 /* If 'start' == 0, then a default start address is used. */
 if (start == 0) {
 start = mmap_next_start;
-- 
2.17.1




[Qemu-devel] [PATCH v7 04/74] linux-user: Tidy do_openat loop over fakes

2019-05-19 Thread Richard Henderson
Cleaner to use ARRAY_SIZE to loop over elements instead of
using a sentinel within the data structure.

Signed-off-by: Richard Henderson 
---
 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 = [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




[Qemu-devel] [PATCH v7 05/74] linux-user: Split out readlink, readlinkat

2019-05-19 Thread Richard Henderson
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 
---
 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_newfstatatprint_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 0x0caf
 #define TIMER_MAGIC_MASK 0x
 
@@ -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 

[Qemu-devel] [PATCH v7 14/74] linux-user: Split out memory syscalls

2019-05-19 Thread Richard Henderson
This includes mmap, mmap2, munmap, mlock, mlockall, munlock,
munlockall, mprotect, mremap, msync.

Signed-off-by: Richard Henderson 
---
 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 = 

[Qemu-devel] [PATCH v7 08/74] linux-user: Reduce regpairs_aligned & target_offset64 ifdefs

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 11/74] linux-user: Split out preadv, pwritev

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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(, , 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(, , 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, , );
-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 

[Qemu-devel] [PATCH v7 16/74] linux-user: Split out brk

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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 .
  */
 
+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, 

[Qemu-devel] [PATCH v7 38/74] linux-user: Split out sync, syncfs

2019-05-19 Thread Richard Henderson
Note that syncfs is universally available.
If !CONFIG_SYNCFS, provide our own syscall replacement.

Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 31/74] linux-user: Split out mount

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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;
-   

[Qemu-devel] [PATCH v7 25/74] linux-user: Split out chdir

2019-05-19 Thread Richard Henderson
Note that chdir is universally provided.

Signed-off-by: Richard Henderson 
---
 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 .
  */
 
+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




[Qemu-devel] [PATCH v7 46/74] linux-user: Move syscall_init to the end

2019-05-19 Thread Richard Henderson
No functional change.  This will aid moving everything
related to ioctls to a separate file.

Signed-off-by: Richard Henderson 
---
 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, _ ## 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, \
+ _ ## 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




[Qemu-devel] [PATCH v7 36/74] linux-user: Split out access, faccessat

2019-05-19 Thread Richard Henderson
Note that faccessat is unconditionally available.

Signed-off-by: Richard Henderson 
---
 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 .
  */
 
+#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 .
  */
 
+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);
-

[Qemu-devel] [PATCH v7 69/74] linux-user: Split out pselect6

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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(, _ptr, rfd_addr, n);
+if (ret) {
+return ret;
+}
+ret = copy_from_user_fdset_ptr(, _ptr, wfd_addr, n);
+if (ret) {
+return ret;
+}
+ret = copy_from_user_fdset_ptr(, _ptr, efd_addr, n);
+if (ret) {
+return ret;
+}
+
+if (ts_addr) {
+if (target_to_host_timespec(, ts_addr)) {
+return -TARGET_EFAULT;
+}
+ts_ptr = 
+}
+
+/* Extract the two packed args for the sigset */
+if (arg6) {
+sig_ptr = 
+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 = 
+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(, 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, , n)) {
+return -TARGET_EFAULT;
+}
+if (wfd_addr && copy_to_user_fdset(wfd_addr, , n)) {
+return -TARGET_EFAULT;
+}
+if (efd_addr && copy_to_user_fdset(efd_addr, , n)) {
+return -TARGET_EFAULT;
+}
+if (ts_addr && host_to_target_timespec(ts_addr, )) {
+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 

[Qemu-devel] [PATCH v7 68/74] linux-user: Split out select, _newselect

2019-05-19 Thread Richard Henderson
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 
---
 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 = 

[Qemu-devel] [PATCH v6 2/6] linux-user: Add support for SIOCSPGRP ioctl for all targets

2019-05-19 Thread Aleksandar Markovic
From: Aleksandar Markovic 

Add support for setting the process (or process group) to receive SIGIO
or SIGURG signals when I/O becomes possible or urgent data is available,
using SIOCSPGRP ioctl.

The ioctl numeric values for SIOCSPGRP are platform-dependent and are
determined by following files in Linux kernel source tree:

arch/ia64/include/uapi/asm/sockios.h:#define SIOCSPGRP0x8902
arch/mips/include/uapi/asm/sockios.h:#define SIOCSPGRP_IOW('s', 8, pid_t)
arch/parisc/include/uapi/asm/sockios.h:#define SIOCSPGRP  0x8902
arch/sh/include/uapi/asm/sockios.h:#define SIOCSPGRP  _IOW('s', 8, pid_t)
arch/xtensa/include/uapi/asm/sockios.h:#define SIOCSPGRP  _IOW('s', 8, pid_t)
arch/alpha/include/uapi/asm/sockios.h:#define SIOCSPGRP   _IOW('s', 8, pid_t)
arch/sparc/include/uapi/asm/sockios.h:#define SIOCSPGRP   0x8902
include/uapi/asm-generic/sockios.h:#define SIOCSPGRP  0x8902

Hence the different definition for alpha, mips, sh4, and xtensa.

Signed-off-by: Aleksandar Markovic 
Reviewed-by: Max Filippov 
Reviewed-by: Laurent Vivier 
---
 linux-user/ioctls.h   | 1 +
 linux-user/syscall_defs.h | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index ae89516..c37adc5 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -218,6 +218,7 @@
   IOCTL(SIOCSRARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
   IOCTL(SIOCGRARP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
   IOCTL(SIOCGIWNAME, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_char_ifreq)))
+  IOCTL(SIOCSPGRP, IOC_W, MK_PTR(TYPE_INT)) /* pid_t */
   IOCTL(SIOCGPGRP, IOC_R, MK_PTR(TYPE_INT)) /* pid_t */
   IOCTL(SIOCGSTAMP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_timeval)))
   IOCTL(SIOCGSTAMPNS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_timespec)))
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 1e86fb9..2941231 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -739,11 +739,14 @@ struct target_pollfd {
 #if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SH4) ||
\
defined(TARGET_XTENSA)
 #define TARGET_SIOCATMARK  TARGET_IOR('s', 7, int)
+#define TARGET_SIOCSPGRP   TARGET_IOW('s', 8, pid_t)
 #define TARGET_SIOCGPGRP   TARGET_IOR('s', 9, pid_t)
 #else
 #define TARGET_SIOCATMARK  0x8905
+#define TARGET_SIOCSPGRP   0x8902
 #define TARGET_SIOCGPGRP   0x8904
 #endif
+
 #define TARGET_SIOCGSTAMP  0x8906  /* Get stamp (timeval) */
 #define TARGET_SIOCGSTAMPNS0x8907  /* Get stamp (timespec) */
 
-- 
2.7.4




[Qemu-devel] [PATCH v6 1/6] linux-user: Fix support for SIOCATMARK and SIOCGPGRP ioctls for xtensa

2019-05-19 Thread Aleksandar Markovic
From: Aleksandar Markovic 

Fix support for the SIOCATMARK and SIOCGPGRP ioctls for xtensa by
correcting corresponding macro definition.

Values for TARGET_SIOCATMARK and TARGET_SIOCGPGRP are determined by
Linux kernel. Following relevant lines (obtained by grep) are from
the kernel source tree:

arch/ia64/include/uapi/asm/sockios.h:#define SIOCATMARK0x8905
arch/mips/include/uapi/asm/sockios.h:#define SIOCATMARK_IOR('s', 7, int)
arch/parisc/include/uapi/asm/sockios.h:#define SIOCATMARK  0x8905
arch/sh/include/uapi/asm/sockios.h:#define SIOCATMARK  _IOR('s', 7, int)
arch/xtensa/include/uapi/asm/sockios.h:#define SIOCATMARK  _IOR('s', 7, int)
arch/alpha/include/uapi/asm/sockios.h:#define SIOCATMARK   _IOR('s', 7, int)
arch/sparc/include/uapi/asm/sockios.h:#define SIOCATMARK   0x8905
include/uapi/asm-generic/sockios.h:#define SIOCATMARK  0x8905

arch/ia64/include/uapi/asm/sockios.h:#define SIOCGPGRP 0x8904
arch/mips/include/uapi/asm/sockios.h:#define SIOCGPGRP _IOR('s', 9, pid_t)
arch/parisc/include/uapi/asm/sockios.h:#define SIOCGPGRP   0x8904
arch/sh/include/uapi/asm/sockios.h:#define SIOCGPGRP   _IOR('s', 9, pid_t)
arch/xtensa/include/uapi/asm/sockios.h:#define SIOCGPGRP   _IOR('s', 9, pid_t)
arch/alpha/include/uapi/asm/sockios.h:#define SIOCGPGRP_IOR('s', 9, pid_t)
arch/sparc/include/uapi/asm/sockios.h:#define SIOCGPGRP0x8904
include/uapi/asm-generic/sockios.h:#define SIOCGPGRP   0x8904

It is visible from above that xtensa should have the same definitions
as alpha, mips and sh4 already do. This patch brings QEMU to the accurate
state wrt these two ioctls.

Acked-by: Max Filippov 
Signed-off-by: Aleksandar Markovic 
Reviewed-by: Laurent Vivier 
---
 linux-user/syscall_defs.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 12c8407..1e86fb9 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -736,7 +736,8 @@ struct target_pollfd {
 #define TARGET_KDSETLED0x4B32  /* set led state [lights, not flags] */
 #define TARGET_KDSIGACCEPT 0x4B4E
 
-#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SH4)
+#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SH4) ||
\
+   defined(TARGET_XTENSA)
 #define TARGET_SIOCATMARK  TARGET_IOR('s', 7, int)
 #define TARGET_SIOCGPGRP   TARGET_IOR('s', 9, pid_t)
 #else
-- 
2.7.4




[Qemu-devel] [PATCH v6 0/6] linux-user: A set of miscellaneous patches

2019-05-19 Thread Aleksandar Markovic
From: Aleksandar Markovic 

This is a collection of misc patches for Linux user that I recently
accumulated from variuous sources. All of them originate from problems
observed on mips target. However, these changes actually affect and fix
problems on multiple targets.

v5->v6:

  - fixed a mistake in patch #4
  - improved commit messages in patches #4 and #6

v4->v5:

  - added the patch on statx() support
  - improved the patch on IPV6__MEMBERSHIP to take into
account the possibility of different names for a field
  - minor corrections in commit messages

v3->v4:

  - improved commit messages (fixed some typos, improved relevance)

v2->v3:

  - updated and improved commit messages
  - added IPV6_DROP_MEMBERSHIP support to the patch on setsockopt()'s
option

v1->v2:

  - added the patch on setsockopt()'s option IPV6_ADD_MEMBERSHIP
  - improved the commit message of interp_info sanitizing patch


Aleksandar Markovic (2):
  linux-user: Fix support for SIOCATMARK and SIOCGPGRP ioctls for xtensa
  linux-user: Add support for SIOCSPGRP ioctl for all targets

Aleksandar Rikalo (1):
  linux-user: Add support for statx() syscall

Daniel Santos (1):
  linux-user: Sanitize interp_info and, for mips only, init field fp_abi

Neng Chen (2):
  linux-user: Add support for SIOCIFPFLAGS ioctls for all targets
  linux-user: Add support for setsockopt() options
IPV6__MEMBERSHIP

 linux-user/elfload.c  |   5 ++
 linux-user/ioctls.h   |   3 +
 linux-user/syscall.c  | 158 +-
 linux-user/syscall_defs.h |  45 -
 4 files changed, 209 insertions(+), 2 deletions(-)

-- 
2.7.4




[Qemu-devel] [PATCH 07/13] linux-user/sparc: Use WREG constants in sparc/signal.c

2019-05-19 Thread Richard Henderson
Remove the incorrectly defined UREG constants.

Maddeningly, in some cases we used the correct constant getting
the env register wrong, and in other cases we used the incorrect
constant getting the env register right.

In the case of getcontext/setcontext, we are aided by the fact
that the "other" constant, e.g. SPARC_MC_O0, is correct.  So we
can easily guess that the WREG_* constant on the other side
should also be O0.

Signed-off-by: Richard Henderson 
---
 linux-user/sparc/signal.c | 96 +--
 1 file changed, 32 insertions(+), 64 deletions(-)

diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c
index ead169fbaa..243f237528 100644
--- a/linux-user/sparc/signal.c
+++ b/linux-user/sparc/signal.c
@@ -104,20 +104,6 @@ struct target_rt_signal_frame {
 qemu_siginfo_fpu_t  fpu_state;
 };
 
-#define UREG_O016
-#define UREG_O622
-#define UREG_I00
-#define UREG_I11
-#define UREG_I22
-#define UREG_I33
-#define UREG_I44
-#define UREG_I55
-#define UREG_I66
-#define UREG_I77
-#define UREG_L08
-#define UREG_FPUREG_I6
-#define UREG_SPUREG_O6
-
 static inline abi_ulong get_sigframe(struct target_sigaction *sa, 
  CPUSPARCState *env,
  unsigned long framesize)
@@ -159,30 +145,12 @@ setup___siginfo(__siginfo_t *si, CPUSPARCState *env, 
abi_ulong mask)
 __put_user(env->gregs[i], >si_regs.u_regs[i]);
 }
 for (i=0; i < 8; i++) {
-__put_user(env->regwptr[UREG_I0 + i], >si_regs.u_regs[i+8]);
+__put_user(env->regwptr[WREG_O0 + i], >si_regs.u_regs[i+8]);
 }
 __put_user(mask, >si_mask);
 return err;
 }
 
-#if 0
-static int
-setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
- CPUSPARCState *env, unsigned long mask)
-{
-int err = 0;
-
-__put_user(mask, >sigc_mask);
-__put_user(env->regwptr[UREG_SP], >sigc_sp);
-__put_user(env->pc, >sigc_pc);
-__put_user(env->npc, >sigc_npc);
-__put_user(env->psr, >sigc_psr);
-__put_user(env->gregs[1], >sigc_g1);
-__put_user(env->regwptr[UREG_O0], >sigc_o0);
-
-return err;
-}
-#endif
 #define NF_ALIGNEDSZ  (((sizeof(struct target_signal_frame) + 7) & (~7)))
 
 void setup_frame(int sig, struct target_sigaction *ka,
@@ -221,20 +189,20 @@ void setup_frame(int sig, struct target_sigaction *ka,
 }
 
 for (i = 0; i < 8; i++) {
-__put_user(env->regwptr[i + UREG_L0], >ss.locals[i]);
+__put_user(env->regwptr[i + WREG_L0], >ss.locals[i]);
 }
 for (i = 0; i < 8; i++) {
-__put_user(env->regwptr[i + UREG_I0], >ss.ins[i]);
+__put_user(env->regwptr[i + WREG_I0], >ss.ins[i]);
 }
 if (err)
 goto sigsegv;
 
 /* 3. signal handler back-trampoline and parameters */
-env->regwptr[UREG_FP] = sf_addr;
-env->regwptr[UREG_I0] = sig;
-env->regwptr[UREG_I1] = sf_addr +
+env->regwptr[WREG_FP] = sf_addr;
+env->regwptr[WREG_I0] = sig;
+env->regwptr[WREG_I1] = sf_addr +
 offsetof(struct target_signal_frame, info);
-env->regwptr[UREG_I2] = sf_addr +
+env->regwptr[WREG_I2] = sf_addr +
 offsetof(struct target_signal_frame, info);
 
 /* 4. signal handler */
@@ -242,11 +210,11 @@ void setup_frame(int sig, struct target_sigaction *ka,
 env->npc = (env->pc + 4);
 /* 5. return to kernel instructions */
 if (ka->ka_restorer) {
-env->regwptr[UREG_I7] = ka->ka_restorer;
+env->regwptr[WREG_I7] = ka->ka_restorer;
 } else {
 uint32_t val32;
 
-env->regwptr[UREG_I7] = sf_addr +
+env->regwptr[WREG_I7] = sf_addr +
 offsetof(struct target_signal_frame, insns) - 2 * 4;
 
 /* mov __NR_sigreturn, %g1 */
@@ -284,7 +252,7 @@ long do_sigreturn(CPUSPARCState *env)
 sigset_t host_set;
 int i;
 
-sf_addr = env->regwptr[UREG_FP];
+sf_addr = env->regwptr[WREG_SP];
 trace_user_do_sigreturn(env, sf_addr);
 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
 goto segv_and_exit;
@@ -316,7 +284,7 @@ long do_sigreturn(CPUSPARCState *env)
 __get_user(env->gregs[i], >info.si_regs.u_regs[i]);
 }
 for (i=0; i < 8; i++) {
-__get_user(env->regwptr[i + UREG_I0], >info.si_regs.u_regs[i+8]);
+__get_user(env->regwptr[i + WREG_O0], >info.si_regs.u_regs[i+8]);
 }
 
 /* FIXME: implement FPU save/restore:
@@ -433,7 +401,7 @@ void sparc64_set_context(CPUSPARCState *env)
 abi_ulong fp, i7, w_addr;
 unsigned int i;
 
-ucp_addr = env->regwptr[UREG_I0];
+ucp_addr = env->regwptr[WREG_O0];
 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
 goto do_sigsegv;
 }
@@ -443,7 +411,7 @@ void sparc64_set_context(CPUSPARCState *env)
 if ((pc | npc) & 3) {
 goto do_sigsegv;
 }
-if (env->regwptr[UREG_I1]) {
+if 

[Qemu-devel] [PATCH 11/13] tests/tcg/multiarch/linux-test: Fix error check for shmat

2019-05-19 Thread Richard Henderson
The error indicator for this syscall is -1, not 0.

Signed-off-by: Richard Henderson 
---
 tests/tcg/multiarch/linux-test.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/tcg/multiarch/linux-test.c b/tests/tcg/multiarch/linux-test.c
index fa4243fc04..673d7c8a1c 100644
--- a/tests/tcg/multiarch/linux-test.c
+++ b/tests/tcg/multiarch/linux-test.c
@@ -503,8 +503,9 @@ static void test_shm(void)
 
 shmid = chk_error(shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0777));
 ptr = shmat(shmid, NULL, 0);
-if (!ptr)
+if (ptr == (void *)-1) {
 error("shmat");
+}
 
 memset(ptr, 0, SHM_SIZE);
 
-- 
2.17.1




[Qemu-devel] [PATCH v7 15/74] linux-user: Split out exit

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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 00..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 .
+ */
+
+
+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(, 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(, 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




[Qemu-devel] [PATCH v7 07/74] linux-user: Split out read, write

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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
 

[Qemu-devel] [PATCH v7 50/74] linux-user: Split out fcntl, fcntl64

2019-05-19 Thread Richard Henderson
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 
---
 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 00..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 

[Qemu-devel] [PATCH v7 52/74] linux-user: Split out umask

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 45/74] linux-user: Split out acct

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 29/74] linux-user: Split out lseek, llseek

2019-05-19 Thread Richard Henderson
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 
---
 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 

[Qemu-devel] [PATCH v7 49/74] linux-user: Remove sentinel from ioctl_entries

2019-05-19 Thread Richard Henderson
Iterate based on the size of the array instead.

Signed-off-by: Richard Henderson 
---
 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 = _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




[Qemu-devel] [PATCH v7 33/74] linux-user: Split out stime

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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 .
  */
 
+#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(_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(_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




[Qemu-devel] [PATCH v7 55/74] linux-user: Split out getsid, setsid

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 64/74] linux-user: Split out gethostname, sethostname

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 58/74] linux-user: Split out sigprocmask, rt_sigprocmask

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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(, p);
+unlock_user(p, arg2, 0);
+set_ptr = 
+}
+
+ret = do_sigprocmask(how, set_ptr, );
+
+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, );
+unlock_user(p, arg3, 

[Qemu-devel] [PATCH v7 73/74] linux-user: Split out truncate, truncate64, ftruncate, ftruncate64

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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 

[Qemu-devel] [PATCH v7 63/74] linux-user: Split out sigreturn, rt_sigreturn

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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, ));
 }
 
+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




[Qemu-devel] [PATCH v7 51/74] linux-user: Split out setpgid

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 71/74] linux-user: Split out swapon, swapoff

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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 & 0x, 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




[Qemu-devel] [Bug 1829576] Re: QEMU-SYSTEM-PPC64 Regression QEMU-4.0.0

2019-05-19 Thread Ivan Warren via Qemu-devel
Same thing here using https://github.com/dgibson/qemu/commits/ppc-
for-4.1 ... It might be a completely different problem (athough it looks
like a MMU problem).

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1829576

Title:
  QEMU-SYSTEM-PPC64 Regression QEMU-4.0.0

Status in QEMU:
  New

Bug description:
  I have been using QEMU-SYSTEM-PPC64 v3.1.0 to run CentOS7 PPC emulated
  system. It stopped working when I upgraded to QEMU-4.0.0 . I
  downgraded back to QEMU-3.1.0 and it started working again. The
  problem is that my CentOS7 image will not boot up udner QEMU-4.0.0,
  but works fine under QEMU-3.1.0.

  I have an QCOW2 image available at
  https://www.mediafire.com/file/d8dda05ro85whn1/linux-
  centos7-ppc64.qcow2/file . NOTE: It is 15GB. Kind of large.

  I run it as follows:

 qemu-system-ppc64 \
-name "CENTOS7-PPC64" \
-cpu POWER7 -machine pseries \
-m 4096 \
-netdev bridge,id=netbr0,br=br0 \
-device e1000,netdev=netbr0,mac=52:54:3c:13:21:33 \
-hda "./linux-centos7-ppc64.qcow2" \
-monitor stdio

  HOST: I am using Manjaro Linux on an Intel i7 machine with the QEMU
  packages installed via the package manager of the distribution.

  [jsantiago@jlsws0 ~]$ uname -a
  Linux jlsws0.haivision.com 4.19.42-1-MANJARO #1 SMP PREEMPT Fri May 10 
20:52:43 UTC 2019 x86_64 GNU/Linux

  jsantiago@jlsws0 ~]$ cpuinfo 
  Intel(R) processor family information utility, Version 2019 Update 3 Build 
20190214 (id: b645a4a54)
  Copyright (C) 2005-2019 Intel Corporation.  All rights reserved.

  =  Processor composition  =
  Processor name: Intel(R) Core(TM) i7-6700K  
  Packages(sockets) : 1
  Cores : 4
  Processors(CPUs)  : 8
  Cores per package : 4
  Threads per core  : 2

  =  Processor identification  =
  Processor Thread Id.  Core Id.Package Id.
  0 0   0   0   
  1 0   1   0   
  2 0   2   0   
  3 0   3   0   
  4 1   0   0   
  5 1   1   0   
  6 1   2   0   
  7 1   3   0   
  =  Placement on packages  =
  Package Id.   Core Id.Processors
  0 0,1,2,3 (0,4)(1,5)(2,6)(3,7)

  =  Cache sharing  =
  Cache SizeProcessors
  L132  KB  (0,4)(1,5)(2,6)(3,7)
  L2256 KB  (0,4)(1,5)(2,6)(3,7)
  L38   MB  (0,1,2,3,4,5,6,7)

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1829576/+subscriptions



[Qemu-devel] [PATCH 05/13] target/sparc: Define an enumeration for accessing env->regwptr

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/sparc/cpu.h | 33 +
 1 file changed, 33 insertions(+)

diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index f31e8535df..f0ac3ac086 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -31,6 +31,39 @@
 
 /*#define EXCP_INTERRUPT 0x100*/
 
+/* Windowed register indexes.  */
+enum {
+WREG_O0,
+WREG_O1,
+WREG_O2,
+WREG_O3,
+WREG_O4,
+WREG_O5,
+WREG_O6,
+WREG_O7,
+
+WREG_L0,
+WREG_L1,
+WREG_L2,
+WREG_L3,
+WREG_L4,
+WREG_L5,
+WREG_L6,
+WREG_L7,
+
+WREG_I0,
+WREG_I1,
+WREG_I2,
+WREG_I3,
+WREG_I4,
+WREG_I5,
+WREG_I6,
+WREG_I7,
+
+WREG_SP = WREG_O6,
+WREG_FP = WREG_I6,
+};
+
 /* trap definitions */
 #ifndef TARGET_SPARC64
 #define TT_TFAULT   0x01
-- 
2.17.1




[Qemu-devel] [PATCH v7 35/74] linux-user: Split out utime, utimes, futimesat

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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([0], target_tv)
+|| copy_from_user_timeval([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 = 
+} 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, 

[Qemu-devel] [PATCH v7 30/74] linux-user: Split out getpid, getppid, getxpid

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 21/74] linux-user: Split out link, linkat

2019-05-19 Thread Richard Henderson
Note that linkat is universally provided.

Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 44/74] linux-user: Split out times

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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());
+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());
-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




[Qemu-devel] [PATCH v7 41/74] linux-user: Split out mkdir, mkdirat

2019-05-19 Thread Richard Henderson
Note that mkdirat is universally available.

Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 26/74] linux-user: Split out time

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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 00..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 .
+ */
+
+#ifdef TARGET_NR_time
+SYSCALL_IMPL(time)
+{
+time_t host_time;
+abi_long ret = get_errno(time(_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(_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




[Qemu-devel] [PATCH v7 37/74] linux-user: Split out nice

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 34/74] linux-user: Split out alarm, pause

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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 .
  */
 
+#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 00..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 .
+ */
+
+#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(>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




[Qemu-devel] [PATCH v7 48/74] linux-user: Fix types in ioctl logging

2019-05-19 Thread Richard Henderson
There is no need to cast "int" to "long"; just use the
correct format in the first place.

Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 67/74] linux-user: Split out gettimeofday, settimeofday

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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 .
  */
 
+SYSCALL_IMPL(gettimeofday)
+{
+struct timeval tv;
+abi_long ret = get_errno(gettimeofday(, NULL));
+
+if (!is_error(ret) && copy_to_user_timeval(arg1, )) {
+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(, arg1)) {
+return -TARGET_EFAULT;
+}
+ptv = 
+}
+
+if (arg2) {
+if (copy_from_user_timezone(, arg2)) {
+return -TARGET_EFAULT;
+}
+ptz = 
+}
+
+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(, NULL));
-if (!is_error(ret)) {
-if (copy_to_user_timeval(arg1, ))
-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(, arg1)) {
-return -TARGET_EFAULT;
-}
-ptv = 
-}
-
-if (arg2) {
-if (copy_from_user_timezone(, arg2)) {
-return -TARGET_EFAULT;
-}
-ptz = 
-}
-
-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




[Qemu-devel] [PATCH v7 70/74] linux-user: Split out symlink, symlinkat

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 62/74] linux-user: Split out rt_sigqueueinfo, rt_tgsigqueueinfo

2019-05-19 Thread Richard Henderson
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 
---
 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, >si_signo);
-__get_user(si_errno, >si_errno);
-__get_user(si_code, >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, >_sifields._kill._pid);
-__get_user(tinfo->_sifields._kill._uid, >_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,
-   >_sifields._sigchld._pid);
-__get_user(tinfo->_sifields._sigchld._uid,
-   >_sifields._sigchld._uid);
-__get_user(tinfo->_sifields._sigchld._status,
-   >_sifields._sigchld._status);
-__get_user(tinfo->_sifields._sigchld._utime,
-   >_sifields._sigchld._utime);
-__get_user(tinfo->_sifields._sigchld._stime,
-   >_sifields._sigchld._stime);
-si_type = QEMU_SI_CHLD;
-break;
-case TARGET_SIGIO:
-__get_user(tinfo->_sifields._sigpoll._band,
-   >_sifields._sigpoll._band);
-__get_user(tinfo->_sifields._sigpoll._fd,
-   >_sifields._sigpoll._fd);
-si_type = QEMU_SI_POLL;
-break;
-default:
-/* Assume a sigqueue()/mq_notify()/rt_sigqueueinfo() source. */
-__get_user(tinfo->_sifields._rt._pid, >_sifields._rt._pid);
-__get_user(tinfo->_sifields._rt._uid, >_sifields._rt._uid);
-/* XXX: potential problem if 64 bit */
-__get_user(sival_ptr, >_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 

[Qemu-devel] [PATCH 02/13] linux-user: Rename cpu_clone_regs to cpu_clone_regs_child

2019-05-19 Thread Richard Henderson
We will need a target-specific hook for adjusting registers
in the parent during clone.  To avoid confusion, rename the
one we have to make it clear it affects the child.

Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/target_cpu.h| 2 +-
 linux-user/alpha/target_cpu.h  | 2 +-
 linux-user/arm/target_cpu.h| 2 +-
 linux-user/cris/target_cpu.h   | 2 +-
 linux-user/hppa/target_cpu.h   | 2 +-
 linux-user/i386/target_cpu.h   | 2 +-
 linux-user/m68k/target_cpu.h   | 2 +-
 linux-user/microblaze/target_cpu.h | 2 +-
 linux-user/mips/target_cpu.h   | 2 +-
 linux-user/nios2/target_cpu.h  | 2 +-
 linux-user/openrisc/target_cpu.h   | 3 ++-
 linux-user/ppc/target_cpu.h| 2 +-
 linux-user/riscv/target_cpu.h  | 2 +-
 linux-user/s390x/target_cpu.h  | 2 +-
 linux-user/sh4/target_cpu.h| 2 +-
 linux-user/sparc/target_cpu.h  | 2 +-
 linux-user/tilegx/target_cpu.h | 2 +-
 linux-user/xtensa/target_cpu.h | 3 ++-
 linux-user/syscall.c   | 4 ++--
 19 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/linux-user/aarch64/target_cpu.h b/linux-user/aarch64/target_cpu.h
index a021c95fa4..abde35b104 100644
--- a/linux-user/aarch64/target_cpu.h
+++ b/linux-user/aarch64/target_cpu.h
@@ -19,7 +19,7 @@
 #ifndef AARCH64_TARGET_CPU_H
 #define AARCH64_TARGET_CPU_H
 
-static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
+static inline void cpu_clone_regs_child(CPUARMState *env, target_ulong newsp)
 {
 if (newsp) {
 env->xregs[31] = newsp;
diff --git a/linux-user/alpha/target_cpu.h b/linux-user/alpha/target_cpu.h
index ac4d255ae7..dc02f2234c 100644
--- a/linux-user/alpha/target_cpu.h
+++ b/linux-user/alpha/target_cpu.h
@@ -19,7 +19,7 @@
 #ifndef ALPHA_TARGET_CPU_H
 #define ALPHA_TARGET_CPU_H
 
-static inline void cpu_clone_regs(CPUAlphaState *env, target_ulong newsp)
+static inline void cpu_clone_regs_child(CPUAlphaState *env, target_ulong newsp)
 {
 if (newsp) {
 env->ir[IR_SP] = newsp;
diff --git a/linux-user/arm/target_cpu.h b/linux-user/arm/target_cpu.h
index 8a3764919a..d35c997287 100644
--- a/linux-user/arm/target_cpu.h
+++ b/linux-user/arm/target_cpu.h
@@ -23,7 +23,7 @@
See validate_guest_space in linux-user/elfload.c.  */
 #define MAX_RESERVED_VA  0xul
 
-static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
+static inline void cpu_clone_regs_child(CPUARMState *env, target_ulong newsp)
 {
 if (newsp) {
 env->regs[13] = newsp;
diff --git a/linux-user/cris/target_cpu.h b/linux-user/cris/target_cpu.h
index 2309343979..9c847caaef 100644
--- a/linux-user/cris/target_cpu.h
+++ b/linux-user/cris/target_cpu.h
@@ -20,7 +20,7 @@
 #ifndef CRIS_TARGET_CPU_H
 #define CRIS_TARGET_CPU_H
 
-static inline void cpu_clone_regs(CPUCRISState *env, target_ulong newsp)
+static inline void cpu_clone_regs_child(CPUCRISState *env, target_ulong newsp)
 {
 if (newsp) {
 env->regs[14] = newsp;
diff --git a/linux-user/hppa/target_cpu.h b/linux-user/hppa/target_cpu.h
index 1c539bdbd6..b98e5a1cfe 100644
--- a/linux-user/hppa/target_cpu.h
+++ b/linux-user/hppa/target_cpu.h
@@ -19,7 +19,7 @@
 #ifndef HPPA_TARGET_CPU_H
 #define HPPA_TARGET_CPU_H
 
-static inline void cpu_clone_regs(CPUHPPAState *env, target_ulong newsp)
+static inline void cpu_clone_regs_child(CPUHPPAState *env, target_ulong newsp)
 {
 if (newsp) {
 env->gr[30] = newsp;
diff --git a/linux-user/i386/target_cpu.h b/linux-user/i386/target_cpu.h
index ece04d0966..e1c9e03490 100644
--- a/linux-user/i386/target_cpu.h
+++ b/linux-user/i386/target_cpu.h
@@ -20,7 +20,7 @@
 #ifndef I386_TARGET_CPU_H
 #define I386_TARGET_CPU_H
 
-static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp)
+static inline void cpu_clone_regs_child(CPUX86State *env, target_ulong newsp)
 {
 if (newsp) {
 env->regs[R_ESP] = newsp;
diff --git a/linux-user/m68k/target_cpu.h b/linux-user/m68k/target_cpu.h
index 7a26f3c3fc..7637a98cab 100644
--- a/linux-user/m68k/target_cpu.h
+++ b/linux-user/m68k/target_cpu.h
@@ -21,7 +21,7 @@
 #ifndef M68K_TARGET_CPU_H
 #define M68K_TARGET_CPU_H
 
-static inline void cpu_clone_regs(CPUM68KState *env, target_ulong newsp)
+static inline void cpu_clone_regs_child(CPUM68KState *env, target_ulong newsp)
 {
 if (newsp) {
 env->aregs[7] = newsp;
diff --git a/linux-user/microblaze/target_cpu.h 
b/linux-user/microblaze/target_cpu.h
index 73e139938c..526b80d54d 100644
--- a/linux-user/microblaze/target_cpu.h
+++ b/linux-user/microblaze/target_cpu.h
@@ -19,7 +19,7 @@
 #ifndef MICROBLAZE_TARGET_CPU_H
 #define MICROBLAZE_TARGET_CPU_H
 
-static inline void cpu_clone_regs(CPUMBState *env, target_ulong newsp)
+static inline void cpu_clone_regs_child(CPUMBState *env, target_ulong newsp)
 {
 if (newsp) {
 env->regs[R_SP] = newsp;
diff --git a/linux-user/mips/target_cpu.h b/linux-user/mips/target_cpu.h
index 02cf5eeff7..c42660b047 100644
--- 

[Qemu-devel] [PATCH 09/13] linux-user/sparc: Flush register windows before clone/fork/vfork

2019-05-19 Thread Richard Henderson
As seen as the very first instruction of sys_clone in the kernel.

Ideally this would be done in or before cpu_copy, and not with a
separate explicit test vs the syscall number, but this is a more
minimal solution.

Signed-off-by: Richard Henderson 
---
 linux-user/sparc/cpu_loop.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c
index 9e357229c0..0816da6fa1 100644
--- a/linux-user/sparc/cpu_loop.c
+++ b/linux-user/sparc/cpu_loop.c
@@ -169,6 +169,18 @@ void cpu_loop (CPUSPARCState *env)
 case 0x110:
 case 0x16d:
 #endif
+/*
+ * Before copying/adjusting registers for parent/child,
+ * flush the register windows to the stack.
+ */
+switch (env->gregs[1]) {
+case TARGET_NR_fork:
+case TARGET_NR_vfork:
+case TARGET_NR_clone:
+flush_windows(env);
+break;
+}
+
 ret = do_syscall (env, env->gregs[1],
   env->regwptr[0], env->regwptr[1],
   env->regwptr[2], env->regwptr[3],
-- 
2.17.1




[Qemu-devel] [PATCH 12/13] linux-user: Fix shmat emulation by honoring host SHMLBA

2019-05-19 Thread Richard Henderson
For those hosts with SHMLBA > getpagesize, we don't automatically
select a guest address that is compatible with the host.  We can
achieve this by boosting the alignment of guest_base and by adding
an extra alignment argument to mmap_find_vma.

Signed-off-by: Richard Henderson 
---
 linux-user/qemu.h|  2 +-
 linux-user/elfload.c | 17 +-
 linux-user/mmap.c| 74 +++-
 linux-user/syscall.c |  3 +-
 4 files changed, 52 insertions(+), 44 deletions(-)

diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index ef400cb78a..82d33d7e93 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -443,7 +443,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong 
old_size,
abi_ulong new_addr);
 extern unsigned long last_brk;
 extern abi_ulong mmap_next_start;
-abi_ulong mmap_find_vma(abi_ulong, abi_ulong);
+abi_ulong mmap_find_vma(abi_ulong, abi_ulong, abi_ulong);
 void mmap_fork_start(void);
 void mmap_fork_end(int child);
 
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index ef42e02d82..fe9f07843e 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -3,6 +3,7 @@
 #include 
 
 #include 
+#include 
 
 #include "qemu.h"
 #include "disas/disas.h"
@@ -2012,6 +2013,8 @@ unsigned long init_guest_space(unsigned long host_start,
unsigned long guest_start,
bool fixed)
 {
+/* In order to use host shmat, we must be able to honor SHMLBA.  */
+unsigned long align = MAX(SHMLBA, qemu_host_page_size);
 unsigned long current_start, aligned_start;
 int flags;
 
@@ -2029,7 +2032,7 @@ unsigned long init_guest_space(unsigned long host_start,
 }
 
 /* Setup the initial flags and start address.  */
-current_start = host_start & qemu_host_page_mask;
+current_start = host_start & -align;
 flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
 if (fixed) {
 flags |= MAP_FIXED;
@@ -2065,8 +2068,8 @@ unsigned long init_guest_space(unsigned long host_start,
 return (unsigned long)-1;
 }
 munmap((void *)real_start, host_full_size);
-if (real_start & ~qemu_host_page_mask) {
-/* The same thing again, but with an extra qemu_host_page_size
+if (real_start & (align - 1)) {
+/* The same thing again, but with extra
  * so that we can shift around alignment.
  */
 unsigned long real_size = host_full_size + qemu_host_page_size;
@@ -2079,7 +2082,7 @@ unsigned long init_guest_space(unsigned long host_start,
 return (unsigned long)-1;
 }
 munmap((void *)real_start, real_size);
-real_start = HOST_PAGE_ALIGN(real_start);
+real_start = ROUND_UP(real_start, align);
 }
 current_start = real_start;
 }
@@ -2106,7 +2109,7 @@ unsigned long init_guest_space(unsigned long host_start,
 }
 
 /* Ensure the address is properly aligned.  */
-if (real_start & ~qemu_host_page_mask) {
+if (real_start & (align - 1)) {
 /* Ideally, we adjust like
  *
  *pages: [  ][  ][  ][  ][  ]
@@ -2134,7 +2137,7 @@ unsigned long init_guest_space(unsigned long host_start,
 if (real_start == (unsigned long)-1) {
 return (unsigned long)-1;
 }
-aligned_start = HOST_PAGE_ALIGN(real_start);
+aligned_start = ROUND_UP(real_start, align);
 } else {
 aligned_start = real_start;
 }
@@ -2171,7 +2174,7 @@ unsigned long init_guest_space(unsigned long host_start,
  * because of trouble with ARM commpage setup.
  */
 munmap((void *)real_start, real_size);
-current_start += qemu_host_page_size;
+current_start += align;
 if (host_start == current_start) {
 /* Theoretically possible if host doesn't have any suitably
  * aligned areas.  Normally the first mmap will fail.
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index e0249efe4f..10796b37ac 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -202,49 +202,52 @@ unsigned long last_brk;
 
 /* Subroutine of mmap_find_vma, used when we have pre-allocated a chunk
of guest address space.  */
-static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size)
+static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size,
+abi_ulong align)
 {
-abi_ulong addr;
-abi_ulong end_addr;
+abi_ulong addr, end_addr, incr = qemu_host_page_size;
 int prot;
-int looped = 0;
+bool looped = false;
 
 if (size > reserved_va) {
 return (abi_ulong)-1;
 }
 
-size = HOST_PAGE_ALIGN(size);
-end_addr = start + size;
-if (end_addr > reserved_va) {
-end_addr = reserved_va;
-}
-addr = end_addr - qemu_host_page_size;
+/* Note 

[Qemu-devel] [PATCH v7 00/74] linux-user: Split do_syscall

2019-05-19 Thread Richard Henderson
Based-on: <20190519201953.20161-1-richard.hender...@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 

[Qemu-devel] [PATCH v7 17/74] linux-user: Split out clone, fork, vfork

2019-05-19 Thread Richard Henderson
Rename do_fork to do_clone, since that is what it does.

Signed-off-by: Richard Henderson 
---
 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 .
  */
 
+#ifndef CLONE_IO
+#define CLONE_IO0x8000  /* 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:
+ * 

[Qemu-devel] [PATCH v7 09/74] linux-user: Split out readv, writev

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 13/74] linux-user: Split out ipc syscalls

2019-05-19 Thread Richard Henderson
Because of the ipc multiplex syscall, these must be done all at once.

Signed-off-by: Richard Henderson 
---
 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 
-#include 
-#include 
-#include 
 #include 
 #include 
 #include 
@@ -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 

[Qemu-devel] [PATCH v7 32/74] linux-user: Split out umount, umount2

2019-05-19 Thread Richard Henderson
Note that umount2 is unconditionally available.

Signed-off-by: Richard Henderson 
---
 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

[Qemu-devel] [PATCH v7 39/74] linux-user: Split out kill

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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, 

[Qemu-devel] [PATCH v7 57/74] linux-user: Split out sgetmask, ssetmask

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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, _set);
+
+if (!ret) {
+host_to_target_old_sigset(_set, _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);
+ret = do_sigprocmask(SIG_SETMASK, , );
+if (!ret) {
+host_to_target_old_sigset(_set, );
+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, _set);
-if (!ret) {
-host_to_target_old_sigset(_set, _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);
-ret = do_sigprocmask(SIG_SETMASK, , );
-if (!ret) {
-host_to_target_old_sigset(_set, );
-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




[Qemu-devel] [PATCH v7 59/74] linux-user: Split out sigpending, rt_sigpending

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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());
+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, );
+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());
+
+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, );
+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());
-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, );
-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());
-if (!is_error(ret)) {
-if (!(p = lock_user(VERIFY_WRITE, arg1, 
sizeof(target_sigset_t), 0)))
-return -TARGET_EFAULT;
-host_to_target_sigset(p, );
-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

[Qemu-devel] [PATCH v7 56/74] linux-user: Split out sigaction, rt_sigaction

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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 = 
+}
+ret = get_errno(do_sigaction(arg1, pact, ));
+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 = 
+}
+
+ret = get_errno(do_sigaction(arg1, pact, ));
+
+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 

[Qemu-devel] [PATCH v7 74/74] linux-user: Split out getpriority, setpriority

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v6 6/6] linux-user: Add support for statx() syscall

2019-05-19 Thread Aleksandar Markovic
From: Aleksandar Rikalo 

Implement support for translation of system call statx(). The
implementation includes invoking other (more mature) system calls
(from the same 'stat' family) on the host side. This way, the
problems of potential lack of statx() availability of on the host
side are avoided.

Support for statx() in kernel and glibc was unfortunately introduced
in different points of time (the difference is more than a year):

  - kernel: Linux 4.11 (30 April 2017)
  - glibc: glibc 2.28 (1 Aug 2018)

In this patch, the availability of statx() support is established
via __NR_statx (if it is defined, statx() is considered available).
This coincedes with statx() introduction in kernel.

However, the structure statx definition may not be available for hosts
with glibc older than 2.28 (it is, by design, to be defined in one of
glibc headers), even though the full statx() functionality may be
supported in kernel, if the kernel is not older than 4.11. Hence,
a structure "target_statx" is defined in this patch, to remove that
dependency on glibc headers, and to use statx() functionality as soon
as the host kernel is capable of supporting it. Such structure statx
definition is used for both target and host structures statx (of
course, this doesn't mean the endian arrangement is the same on
target and host, and endian conversion is done in all necessary
cases).

Signed-off-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 linux-user/syscall.c  | 135 +-
 linux-user/syscall_defs.h |  37 +
 2 files changed, 171 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index acff14d..e892a29 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -6427,6 +6428,48 @@ static inline abi_long host_to_target_stat64(void 
*cpu_env,
 }
 #endif
 
+#if defined(TARGET_NR_statx) && defined(__NR_statx)
+static inline abi_long host_to_target_statx(struct target_statx *host_stx,
+abi_ulong target_addr)
+{
+struct target_statx *target_stx;
+
+if (!lock_user_struct(VERIFY_WRITE, target_stx, target_addr,  0)) {
+return -TARGET_EFAULT;
+}
+memset(target_stx, 0, sizeof(*target_stx));
+
+__put_user(host_stx->stx_mask, _stx->stx_mask);
+__put_user(host_stx->stx_blksize, _stx->stx_blksize);
+__put_user(host_stx->stx_attributes, _stx->stx_attributes);
+__put_user(host_stx->stx_nlink, _stx->stx_nlink);
+__put_user(host_stx->stx_uid, _stx->stx_uid);
+__put_user(host_stx->stx_gid, _stx->stx_gid);
+__put_user(host_stx->stx_mode, _stx->stx_mode);
+__put_user(host_stx->stx_ino, _stx->stx_ino);
+__put_user(host_stx->stx_size, _stx->stx_size);
+__put_user(host_stx->stx_blocks, _stx->stx_blocks);
+__put_user(host_stx->stx_attributes_mask, 
_stx->stx_attributes_mask);
+__put_user(host_stx->stx_atime.tv_sec, _stx->stx_atime.tv_sec);
+__put_user(host_stx->stx_atime.tv_nsec, _stx->stx_atime.tv_nsec);
+__put_user(host_stx->stx_btime.tv_sec, _stx->stx_atime.tv_sec);
+__put_user(host_stx->stx_btime.tv_nsec, _stx->stx_atime.tv_nsec);
+__put_user(host_stx->stx_ctime.tv_sec, _stx->stx_atime.tv_sec);
+__put_user(host_stx->stx_ctime.tv_nsec, _stx->stx_atime.tv_nsec);
+__put_user(host_stx->stx_mtime.tv_sec, _stx->stx_atime.tv_sec);
+__put_user(host_stx->stx_mtime.tv_nsec, _stx->stx_atime.tv_nsec);
+__put_user(host_stx->stx_rdev_major, _stx->stx_rdev_major);
+__put_user(host_stx->stx_rdev_minor, _stx->stx_rdev_minor);
+__put_user(host_stx->stx_dev_major, _stx->stx_dev_major);
+__put_user(host_stx->stx_dev_minor, _stx->stx_dev_minor);
+
+unlock_user_struct(target_stx, target_addr, 1);
+
+return 0;
+}
+#endif
+
+
 /* ??? Using host futex calls even when target atomic operations
are not really atomic probably breaks things.  However implementing
futexes locally would make futexes shared between multiple processes
@@ -6980,7 +7023,8 @@ static abi_long do_syscall1(void *cpu_env, int num, 
abi_long arg1,
 abi_long ret;
 #if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) \
 || defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) \
-|| defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64)
+|| defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) \
+|| defined(TARGET_NR_statx)
 struct stat st;
 #endif
 #if defined(TARGET_NR_statfs) || defined(TARGET_NR_statfs64) \
@@ -10029,6 +10073,95 @@ static abi_long do_syscall1(void *cpu_env, int num, 
abi_long arg1,
 ret = host_to_target_stat64(cpu_env, arg3, );
 return ret;
 #endif
+#if defined(TARGET_NR_statx)
+case TARGET_NR_statx:
+{
+struct target_statx *target_stx;
+int dirfd = arg1;
+int flags = arg3;
+
+p = lock_user_string(arg2);
+  

[Qemu-devel] [PATCH 03/13] linux-user: Introduce cpu_clone_regs_parent

2019-05-19 Thread Richard Henderson
Add an empty inline function for each target, and invoke it
from the proper places.

Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/target_cpu.h| 4 
 linux-user/alpha/target_cpu.h  | 4 
 linux-user/arm/target_cpu.h| 4 
 linux-user/cris/target_cpu.h   | 4 
 linux-user/hppa/target_cpu.h   | 4 
 linux-user/i386/target_cpu.h   | 4 
 linux-user/m68k/target_cpu.h   | 4 
 linux-user/microblaze/target_cpu.h | 4 
 linux-user/mips/target_cpu.h   | 4 
 linux-user/nios2/target_cpu.h  | 4 
 linux-user/openrisc/target_cpu.h   | 4 
 linux-user/ppc/target_cpu.h| 4 
 linux-user/riscv/target_cpu.h  | 4 
 linux-user/s390x/target_cpu.h  | 4 
 linux-user/sh4/target_cpu.h| 4 
 linux-user/sparc/target_cpu.h  | 4 
 linux-user/tilegx/target_cpu.h | 4 
 linux-user/xtensa/target_cpu.h | 4 
 linux-user/syscall.c   | 2 ++
 19 files changed, 74 insertions(+)

diff --git a/linux-user/aarch64/target_cpu.h b/linux-user/aarch64/target_cpu.h
index abde35b104..0182bfca07 100644
--- a/linux-user/aarch64/target_cpu.h
+++ b/linux-user/aarch64/target_cpu.h
@@ -27,6 +27,10 @@ static inline void cpu_clone_regs_child(CPUARMState *env, 
target_ulong newsp)
 env->xregs[0] = 0;
 }
 
+static inline void cpu_clone_regs_parent(CPUARMState *env)
+{
+}
+
 static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
 {
 /* Note that AArch64 Linux keeps the TLS pointer in TPIDR; this is
diff --git a/linux-user/alpha/target_cpu.h b/linux-user/alpha/target_cpu.h
index dc02f2234c..140a459f73 100644
--- a/linux-user/alpha/target_cpu.h
+++ b/linux-user/alpha/target_cpu.h
@@ -28,6 +28,10 @@ static inline void cpu_clone_regs_child(CPUAlphaState *env, 
target_ulong newsp)
 env->ir[IR_A3] = 0;
 }
 
+static inline void cpu_clone_regs_parent(CPUAlphaState *env)
+{
+}
+
 static inline void cpu_set_tls(CPUAlphaState *env, target_ulong newtls)
 {
 env->unique = newtls;
diff --git a/linux-user/arm/target_cpu.h b/linux-user/arm/target_cpu.h
index d35c997287..3e66d5b106 100644
--- a/linux-user/arm/target_cpu.h
+++ b/linux-user/arm/target_cpu.h
@@ -31,6 +31,10 @@ static inline void cpu_clone_regs_child(CPUARMState *env, 
target_ulong newsp)
 env->regs[0] = 0;
 }
 
+static inline void cpu_clone_regs_parent(CPUARMState *env)
+{
+}
+
 static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
 {
 if (access_secure_reg(env)) {
diff --git a/linux-user/cris/target_cpu.h b/linux-user/cris/target_cpu.h
index 9c847caaef..4da074b4fd 100644
--- a/linux-user/cris/target_cpu.h
+++ b/linux-user/cris/target_cpu.h
@@ -28,6 +28,10 @@ static inline void cpu_clone_regs_child(CPUCRISState *env, 
target_ulong newsp)
 env->regs[10] = 0;
 }
 
+static inline void cpu_clone_regs_parent(CPUCRISState *env)
+{
+}
+
 static inline void cpu_set_tls(CPUCRISState *env, target_ulong newtls)
 {
 env->pregs[PR_PID] = (env->pregs[PR_PID] & 0xff) | newtls;
diff --git a/linux-user/hppa/target_cpu.h b/linux-user/hppa/target_cpu.h
index b98e5a1cfe..6b323297af 100644
--- a/linux-user/hppa/target_cpu.h
+++ b/linux-user/hppa/target_cpu.h
@@ -31,6 +31,10 @@ static inline void cpu_clone_regs_child(CPUHPPAState *env, 
target_ulong newsp)
 env->iaoq_b = env->gr[31] + 4;
 }
 
+static inline void cpu_clone_regs_parent(CPUHPPAState *env)
+{
+}
+
 static inline void cpu_set_tls(CPUHPPAState *env, target_ulong newtls)
 {
 env->cr[27] = newtls;
diff --git a/linux-user/i386/target_cpu.h b/linux-user/i386/target_cpu.h
index e1c9e03490..6dbb856c52 100644
--- a/linux-user/i386/target_cpu.h
+++ b/linux-user/i386/target_cpu.h
@@ -28,6 +28,10 @@ static inline void cpu_clone_regs_child(CPUX86State *env, 
target_ulong newsp)
 env->regs[R_EAX] = 0;
 }
 
+static inline void cpu_clone_regs_parent(CPUX86State *env)
+{
+}
+
 #if defined(TARGET_ABI32)
 abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr);
 
diff --git a/linux-user/m68k/target_cpu.h b/linux-user/m68k/target_cpu.h
index 7637a98cab..f1a53cdee5 100644
--- a/linux-user/m68k/target_cpu.h
+++ b/linux-user/m68k/target_cpu.h
@@ -29,6 +29,10 @@ static inline void cpu_clone_regs_child(CPUM68KState *env, 
target_ulong newsp)
 env->dregs[0] = 0;
 }
 
+static inline void cpu_clone_regs_parent(CPUM68KState *env)
+{
+}
+
 static inline void cpu_set_tls(CPUM68KState *env, target_ulong newtls)
 {
 CPUState *cs = CPU(m68k_env_get_cpu(env));
diff --git a/linux-user/microblaze/target_cpu.h 
b/linux-user/microblaze/target_cpu.h
index 526b80d54d..5e285e9211 100644
--- a/linux-user/microblaze/target_cpu.h
+++ b/linux-user/microblaze/target_cpu.h
@@ -27,6 +27,10 @@ static inline void cpu_clone_regs_child(CPUMBState *env, 
target_ulong newsp)
 env->regs[3] = 0;
 }
 
+static inline void cpu_clone_regs_parent(CPUMBState *env)
+{
+}
+
 static inline void cpu_set_tls(CPUMBState *env, target_ulong newtls)
 {
 env->regs[21] = newtls;
diff --git 

[Qemu-devel] [PATCH 08/13] linux-user/sparc: Fix cpu_clone_regs

2019-05-19 Thread Richard Henderson
We failed to set the secondary return value in %o1
we failed to advance the PC past the syscall,
we failed to adjust regwptr into the new structure,
we stored the stack pointer into the wrong register.

Signed-off-by: Richard Henderson 
---
 linux-user/sparc/target_cpu.h | 29 +++--
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/linux-user/sparc/target_cpu.h b/linux-user/sparc/target_cpu.h
index 2c80db4889..a81f8216b7 100644
--- a/linux-user/sparc/target_cpu.h
+++ b/linux-user/sparc/target_cpu.h
@@ -22,22 +22,39 @@
 
 static inline void cpu_clone_regs_child(CPUSPARCState *env, target_ulong newsp)
 {
-if (newsp) {
-env->regwptr[22] = newsp;
-}
-/* syscall return for clone child: 0, and clear CF since
- * this counts as a success return value.
+/*
+ * After cpu_copy, env->regwptr is pointing into old_env.
+ * Update the new cpu to use its own register window.
  */
-env->regwptr[0] = 0;
+env->regwptr = env->regbase + (env->cwp * 16);
+
+/* Set a new stack, if requested.  */
+if (newsp) {
+/* ??? The kernel appears to copy one stack frame to the new stack. */
+/* ??? The kernel force aligns the stack. */
+env->regwptr[WREG_SP] = newsp;
+}
+
+/*
+ * Syscall return for clone child: %o0 = 0 and clear CF since
+ * this counts as a success return value.  %o1 = 1 to indicate
+ * this is the child.  Advance the PC past the syscall.
+ */
+env->regwptr[WREG_O0] = 0;
 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
 env->xcc &= ~PSR_CARRY;
 #else
 env->psr &= ~PSR_CARRY;
 #endif
+env->regwptr[WREG_O1] = 1;
+env->pc = env->npc;
+env->npc = env->npc + 4;
 }
 
 static inline void cpu_clone_regs_parent(CPUSPARCState *env)
 {
+/* Set the second return value for the parent: %o1 = 0.  */
+env->regwptr[WREG_O1] = 0;
 }
 
 static inline void cpu_set_tls(CPUSPARCState *env, target_ulong newtls)
-- 
2.17.1




[Qemu-devel] [PATCH 06/13] linux-user/sparc: Use WREG constants in sparc/target_cpu.h

2019-05-19 Thread Richard Henderson
This fixes a naming bug wherein we used "UREG_FP" to access the
stack pointer.  OTOH, the "UREG_FP" constant was also defined
incorrectly such that it *did* reference the stack pointer.

Note that the kernel legitimately uses the name "FP", because it
utilizes the rolled stack window in processing the system call.

Signed-off-by: Richard Henderson 
---
 linux-user/sparc/target_cpu.h | 10 ++
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/linux-user/sparc/target_cpu.h b/linux-user/sparc/target_cpu.h
index 52c9d8c7db..2c80db4889 100644
--- a/linux-user/sparc/target_cpu.h
+++ b/linux-user/sparc/target_cpu.h
@@ -45,15 +45,9 @@ static inline void cpu_set_tls(CPUSPARCState *env, 
target_ulong newtls)
 env->gregs[7] = newtls;
 }
 
-#ifndef UREG_I6
-#define UREG_I66
-#endif
-#ifndef UREG_FP
-#define UREG_FPUREG_I6
-#endif
-
 static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
 {
-return state->regwptr[UREG_FP];
+return state->regwptr[WREG_SP];
 }
+
 #endif
-- 
2.17.1




[Qemu-devel] [PATCH v7 10/74] linux-user: Split out pread64, pwrite64

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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
@@ 

[Qemu-devel] [PATCH v7 02/74] linux-user: Split out open, open_at

2019-05-19 Thread Richard Henderson
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 
---
 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 .
  */
+
+#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 00..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 .
+ */
+
+/*
+ * 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(, , 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", , , _r, _w, _x,
+_p, , _maj, _min, , 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 

[Qemu-devel] [PATCH v7 03/74] linux-user: Share more code for open and openat

2019-05-19 Thread Richard Henderson
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 
---
 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.XX", 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




[Qemu-devel] [PATCH v7 19/74] linux-user: Implement rusage argument to waitid

2019-05-19 Thread Richard Henderson
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 
---
 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 ?  : NULL;
+struct rusage rusage;
+struct rusage *rusage_ptr = target_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, );
+unlock_user(p, target_info, sizeof(target_siginfo_t));
+}
+if (target_rusage) {
+abi_long err = host_to_target_rusage(target_rusage, );
+if (err) {
+ret = err;
+}
 }
-host_to_target_siginfo(p, );
-unlock_user(p, target_info, sizeof(target_siginfo_t));
 }
 return ret;
 }
-- 
2.17.1




[Qemu-devel] [PATCH v7 28/74] linux-user: Split out chmod, fchmod, fchmodat

2019-05-19 Thread Richard Henderson
Note that fchmodat is universally provided.

Signed-off-by: Richard Henderson 
---
 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 

[Qemu-devel] [PATCH v7 18/74] linux-user: Split out wait4, waitid, waitpid

2019-05-19 Thread Richard Henderson
Note that waitid is universally provided and need not be conditional.

Signed-off-by: Richard Henderson 
---
 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 ?  : NULL;
+abi_long ret;
+
+ret = get_errno(safe_wait4(pid, , 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, );
+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 ?  : 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, );
+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, , 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 0x0caf
 #define TIMER_MAGIC_MASK 0x
 
@@ -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, , 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;
-  

[Qemu-devel] [PATCH v7 12/74] linux-user: Split out name_to_handle_at, open_by_handle_at

2019-05-19 Thread Richard Henderson
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 
---
 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, , 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 

[Qemu-devel] [PATCH v7 20/74] linux-user: Split out creat

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 22/74] linux-user: Split out unlink, unlinkat, rmdir

2019-05-19 Thread Richard Henderson
Note that unlinkat is universally provided.
Implement rmdir in terms of unlinkat.

Signed-off-by: Richard Henderson 
---
 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;
 
 

[Qemu-devel] [PATCH v7 40/74] linux-user: Split out rename, renameat, renameat2

2019-05-19 Thread Richard Henderson
Note that renameat2 is universally available for guests.
Merge sys_renameat2 into the new do_renameat2 helper.

Signed-off-by: Richard Henderson 
---
 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 
 #include 
 #include 
+#include 
 #include 
 #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_newfstatatprint_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

[Qemu-devel] [PATCH v7 27/74] linux-user: Split out mknod, mknodat

2019-05-19 Thread Richard Henderson
Note that mknodat is universally provided.

Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 47/74] linux-user: Split out ioctl

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
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 00..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 .
+ */
+
+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 

[Qemu-devel] [PATCH v7 53/74] linux-user: Split out chroot

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 54/74] linux-user: Split out getpgid, getpgrp

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 42/74] linux-user: Split out dup, dup2, dup3

2019-05-19 Thread Richard Henderson
Note that dup3 is universally available for guests.
Implement host support with syscall when !CONFIG_DUP3.

Signed-off-by: Richard Henderson 
---
 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..062a75 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




[Qemu-devel] [PATCH v7 72/74] linux-user: Split out reboot

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v6 3/6] linux-user: Add support for SIOCIFPFLAGS ioctls for all targets

2019-05-19 Thread Aleksandar Markovic
From: Neng Chen 

Add support for getting and setting extended private flags of a
network device via SIOCSIFPFLAGS and SIOCGIFPFLAGS ioctls.

The ioctl numeric values are platform-independent and determined by
the file include/uapi/linux/sockios.h in Linux kernel source code:

  #define SIOCSIFPFLAGS 0x8934
  #define SIOCGIFPFLAGS 0x8935

These ioctls get (or set) the field ifr_flags of type short in the
structure ifreq. Such functionality is achieved in QEMU by using
MK_STRUCT() and MK_PTR() macros with an appropriate argument, as
it was done for existing similar cases.

Signed-off-by: Neng Chen 
Signed-off-by: Aleksandar Markovic 
Reviewed-by: Laurent Vivier 
Message-Id: <1554839486-3527-1-git-send-email-aleksandar.marko...@rt-rk.com>
---
 linux-user/ioctls.h   | 2 ++
 linux-user/syscall_defs.h | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index c37adc5..76375df 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -206,6 +206,8 @@
   IOCTL(SIOCADDMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
   IOCTL(SIOCDELMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
   IOCTL(SIOCGIFINDEX, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_int_ifreq)))
+  IOCTL(SIOCSIFPFLAGS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
+  IOCTL(SIOCGIFPFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
   IOCTL(SIOCSIFLINK, 0, TYPE_NULL)
   IOCTL_SPECIAL(SIOCGIFCONF, IOC_W | IOC_R, do_ioctl_ifconf,
 MK_PTR(MK_STRUCT(STRUCT_ifconf)))
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 2941231..8904d35 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -781,6 +781,8 @@ struct target_pollfd {
 #define TARGET_SIOCADDMULTI0x8931  /* Multicast address lists  
*/
 #define TARGET_SIOCDELMULTI0x8932
 #define TARGET_SIOCGIFINDEX0x8933
+#define TARGET_SIOCSIFPFLAGS   0x8934  /* set extended flags  
*/
+#define TARGET_SIOCGIFPFLAGS   0x8935  /* get extended flags  
*/
 
 /* Bridging control calls */
 #define TARGET_SIOCGIFBR   0x8940  /* Bridging support 
*/
-- 
2.7.4




[Qemu-devel] [PATCH v6 4/6] linux-user: Add support for setsockopt() options IPV6__MEMBERSHIP

2019-05-19 Thread Aleksandar Markovic
From: Neng Chen 

Add support for options IPV6_ADD_MEMBERSHIP and IPV6_DROP_MEMPEMBERSHIP
of the syscall setsockopt(). These options control membership in
multicast groups. Their argument is a pointer to a struct ipv6_mreq,
which is in turn defined in IP v6 header netinet/in.h as:

 struct ipv6_mreq {
 /* IPv6 multicast address of group */
 struct  in6_addr  ipv6mr_multiaddr;
 /* local IPv6 address of interface */
 int ipv6mr_interface;
 };

...whereas its definition in kernel's include/uapi/linux/in6.h is:

 #if __UAPI_DEF_IPV6_MREQ
 struct ipv6_mreq {
 /* IPv6 multicast address of group */
 struct  in6_addr ipv6mr_multiaddr;
 /* local IPv6 address of interface */
 int ipv6mr_ifindex;
 };
 #endif

The first field of ipv6_mreq has the same name ("ipv6mr_multiaddr")
and type ("in6_addr") in both cases. Moreover, the in6_addr structure
consists of fields that are always big-endian (on host of any endian),
therefore the ipv6_mreq's field ipv6mr_multiaddr doesn't need any
endian conversion.

The second field of ipv6_mreq may, however, depending on the build
environment, have different names. This is the reason why the line
"#if __UAPI_DEF_IPV6_MREQ" is used in this patch - to establish the
right choice for the field name. Also, endian conversion is needed
for this field, since it is of type "int".

Signed-off-by: Neng Chen 
Signed-off-by: Aleksandar Markovic 
---
 linux-user/syscall.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 96cd4bf..acff14d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1892,6 +1892,29 @@ static abi_long do_setsockopt(int sockfd, int level, int 
optname,
, sizeof(pki)));
 break;
 }
+case IPV6_ADD_MEMBERSHIP:
+case IPV6_DROP_MEMBERSHIP:
+{
+struct ipv6_mreq ipv6mreq;
+
+if (optlen < sizeof(ipv6mreq)) {
+return -TARGET_EINVAL;
+}
+
+if (copy_from_user(, optval_addr, sizeof(ipv6mreq))) {
+return -TARGET_EFAULT;
+}
+
+#if __UAPI_DEF_IPV6_MREQ
+ipv6mreq.ipv6mr_ifindex = tswap32(ipv6mreq.ipv6mr_ifindex);
+#else
+ipv6mreq.ipv6mr_interface = tswap32(ipv6mreq.ipv6mr_interface);
+#endif /* __UAPI_DEF_IVP6_MREQ */
+
+ret = get_errno(setsockopt(sockfd, level, optname,
+   , sizeof(ipv6mreq)));
+break;
+}
 default:
 goto unimplemented;
 }
-- 
2.7.4




[Qemu-devel] [PATCH 01/13] util/path: Do not cache all filenames at startup

2019-05-19 Thread Richard Henderson
If one uses -L $PATH to point to a full chroot, the startup time
is significant.  In addition, the existing probing algorithm fails
to handle symlink loops.

Instead, probe individual paths on demand.  Cache both positive
and negative results within $PATH, so that any one filename is
probed only once.

Use glib filename functions for clarity.

Signed-off-by: Richard Henderson 
---
 util/path.c | 201 
 1 file changed, 47 insertions(+), 154 deletions(-)

diff --git a/util/path.c b/util/path.c
index 7f9fc272fb..8e174eb436 100644
--- a/util/path.c
+++ b/util/path.c
@@ -8,170 +8,63 @@
 #include 
 #include "qemu/cutils.h"
 #include "qemu/path.h"
+#include "qemu/thread.h"
 
-struct pathelem
-{
-/* Name of this, eg. lib */
-char *name;
-/* Full path name, eg. /usr/gnemul/x86-linux/lib. */
-char *pathname;
-struct pathelem *parent;
-/* Children */
-unsigned int num_entries;
-struct pathelem *entries[0];
-};
-
-static struct pathelem *base;
-
-/* First N chars of S1 match S2, and S2 is N chars long. */
-static int strneq(const char *s1, unsigned int n, const char *s2)
-{
-unsigned int i;
-
-for (i = 0; i < n; i++)
-if (s1[i] != s2[i])
-return 0;
-return s2[i] == 0;
-}
-
-static struct pathelem *add_entry(struct pathelem *root, const char *name,
-  unsigned type);
-
-static struct pathelem *new_entry(const char *root,
-  struct pathelem *parent,
-  const char *name)
-{
-struct pathelem *new = g_malloc(sizeof(*new));
-new->name = g_strdup(name);
-new->pathname = g_strdup_printf("%s/%s", root, name);
-new->num_entries = 0;
-return new;
-}
-
-#define streq(a,b) (strcmp((a), (b)) == 0)
-
-/* Not all systems provide this feature */
-#if defined(DT_DIR) && defined(DT_UNKNOWN) && defined(DT_LNK)
-# define dirent_type(dirent) ((dirent)->d_type)
-# define is_dir_maybe(type) \
-((type) == DT_DIR || (type) == DT_UNKNOWN || (type) == DT_LNK)
-#else
-# define dirent_type(dirent) (1)
-# define is_dir_maybe(type)  (type)
-#endif
-
-static struct pathelem *add_dir_maybe(struct pathelem *path)
-{
-DIR *dir;
-
-if ((dir = opendir(path->pathname)) != NULL) {
-struct dirent *dirent;
-
-while ((dirent = readdir(dir)) != NULL) {
-if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){
-path = add_entry(path, dirent->d_name, dirent_type(dirent));
-}
-}
-closedir(dir);
-}
-return path;
-}
-
-static struct pathelem *add_entry(struct pathelem *root, const char *name,
-  unsigned type)
-{
-struct pathelem **e;
-
-root->num_entries++;
-
-root = g_realloc(root, sizeof(*root)
-   + sizeof(root->entries[0])*root->num_entries);
-e = >entries[root->num_entries-1];
-
-*e = new_entry(root->pathname, root, name);
-if (is_dir_maybe(type)) {
-*e = add_dir_maybe(*e);
-}
-
-return root;
-}
-
-/* This needs to be done after tree is stabilized (ie. no more reallocs!). */
-static void set_parents(struct pathelem *child, struct pathelem *parent)
-{
-unsigned int i;
-
-child->parent = parent;
-for (i = 0; i < child->num_entries; i++)
-set_parents(child->entries[i], child);
-}
-
-/* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */
-static const char *
-follow_path(const struct pathelem *cursor, const char *name)
-{
-unsigned int i, namelen;
-
-name += strspn(name, "/");
-namelen = strcspn(name, "/");
-
-if (namelen == 0)
-return cursor->pathname;
-
-if (strneq(name, namelen, ".."))
-return follow_path(cursor->parent, name + namelen);
-
-if (strneq(name, namelen, "."))
-return follow_path(cursor, name + namelen);
-
-for (i = 0; i < cursor->num_entries; i++)
-if (strneq(name, namelen, cursor->entries[i]->name))
-return follow_path(cursor->entries[i], name + namelen);
-
-/* Not found */
-return NULL;
-}
+static const char *base;
+static GHashTable *hash;
+static QemuMutex lock;
 
 void init_paths(const char *prefix)
 {
-char pref_buf[PATH_MAX];
-
-if (prefix[0] == '\0' ||
-!strcmp(prefix, "/"))
+if (prefix[0] == '\0' || !strcmp(prefix, "/")) {
 return;
-
-if (prefix[0] != '/') {
-char *cwd = getcwd(NULL, 0);
-size_t pref_buf_len = sizeof(pref_buf);
-
-if (!cwd)
-abort();
-pstrcpy(pref_buf, sizeof(pref_buf), cwd);
-pstrcat(pref_buf, pref_buf_len, "/");
-pstrcat(pref_buf, pref_buf_len, prefix);
-free(cwd);
-} else
-pstrcpy(pref_buf, sizeof(pref_buf), prefix + 1);
-
-base = new_entry("", NULL, pref_buf);
-base = add_dir_maybe(base);
-if (base->num_entries == 0) {
-g_free(base->pathname);
-

[Qemu-devel] [PATCH 00/13] linux-user: path, clone, sparc, shmat fixes

2019-05-19 Thread Richard Henderson
This is an omnibus patchset of:

  v2: util/path: Do not cache all filenames at startup
  https://lists.gnu.org/archive/html/qemu-devel/2019-04/msg04149.html

  v1: linux-user: Fix shmat emulation by honoring host SHMLBA
  https://lists.gnu.org/archive/html/qemu-devel/2018-10/msg03430.html

And a v3 update of

  v2: linux-user sparc fixes
  https://lists.gnu.org/archive/html/qemu-devel/2019-05/msg02273.html


r~


Richard Henderson (13):
  util/path: Do not cache all filenames at startup
  linux-user: Rename cpu_clone_regs to cpu_clone_regs_child
  linux-user: Introduce cpu_clone_regs_parent
  linux-user/alpha: Set r20 secondary return value
  target/sparc: Define an enumeration for accessing env->regwptr
  linux-user/sparc: Use WREG constants in sparc/target_cpu.h
  linux-user/sparc: Use WREG constants in sparc/signal.c
  linux-user/sparc: Fix cpu_clone_regs
  linux-user/sparc: Flush register windows before clone/fork/vfork
  scripts/qemu-binfmt-conf: Update for sparc64
  tests/tcg/multiarch/linux-test: Fix error check for shmat
  linux-user: Fix shmat emulation by honoring host SHMLBA
  linux-user: Align mmap_find_vma to host page size

 linux-user/aarch64/target_cpu.h|   6 +-
 linux-user/alpha/target_cpu.h  |   8 +-
 linux-user/arm/target_cpu.h|   6 +-
 linux-user/cris/target_cpu.h   |   6 +-
 linux-user/hppa/target_cpu.h   |   6 +-
 linux-user/i386/target_cpu.h   |   6 +-
 linux-user/m68k/target_cpu.h   |   6 +-
 linux-user/microblaze/target_cpu.h |   6 +-
 linux-user/mips/target_cpu.h   |   6 +-
 linux-user/nios2/target_cpu.h  |   6 +-
 linux-user/openrisc/target_cpu.h   |   7 +-
 linux-user/ppc/target_cpu.h|   6 +-
 linux-user/qemu.h  |   2 +-
 linux-user/riscv/target_cpu.h  |   6 +-
 linux-user/s390x/target_cpu.h  |   6 +-
 linux-user/sh4/target_cpu.h|   6 +-
 linux-user/sparc/target_cpu.h  |  45 ---
 linux-user/tilegx/target_cpu.h |   6 +-
 linux-user/xtensa/target_cpu.h |   7 +-
 target/sparc/cpu.h |  33 +
 linux-user/elfload.c   |  17 ++-
 linux-user/mmap.c  |  76 ++-
 linux-user/sparc/cpu_loop.c|  12 ++
 linux-user/sparc/signal.c  |  96 +-
 linux-user/syscall.c   |   9 +-
 tests/tcg/multiarch/linux-test.c   |   3 +-
 util/path.c| 201 +++--
 scripts/qemu-binfmt-conf.sh|   8 +-
 28 files changed, 309 insertions(+), 299 deletions(-)

-- 
2.17.1




[Qemu-devel] [PATCH 04/13] linux-user/alpha: Set r20 secondary return value

2019-05-19 Thread Richard Henderson
This value is not, as far as I know, used by any linux software,
but it is set by the kernel and is part of the ABI.

Signed-off-by: Richard Henderson 
---
 linux-user/alpha/target_cpu.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/linux-user/alpha/target_cpu.h b/linux-user/alpha/target_cpu.h
index 140a459f73..caadb54372 100644
--- a/linux-user/alpha/target_cpu.h
+++ b/linux-user/alpha/target_cpu.h
@@ -26,10 +26,12 @@ static inline void cpu_clone_regs_child(CPUAlphaState *env, 
target_ulong newsp)
 }
 env->ir[IR_V0] = 0;
 env->ir[IR_A3] = 0;
+env->ir[IR_A4] = 1;  /* OSF/1 secondary return: child */
 }
 
 static inline void cpu_clone_regs_parent(CPUAlphaState *env)
 {
+env->ir[IR_A4] = 0;  /* OSF/1 secondary return: parent */
 }
 
 static inline void cpu_set_tls(CPUAlphaState *env, target_ulong newtls)
-- 
2.17.1




[Qemu-devel] [PATCH v7 01/74] linux-user: Setup split syscall infrastructure

2019-05-19 Thread Richard Henderson
Defines a unified structure for implementation and strace.

Signed-off-by: Richard Henderson 
---
 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 00..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 .
+ */
diff --git a/linux-user/syscall.h b/linux-user/syscall.h
new file mode 100644
index 00..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 .
+ */
+
+#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 
 #include 
 #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),

[Qemu-devel] [PATCH v7 06/74] linux-user: Split out close

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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 .
  */
 
+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 .
  */
 
+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




[Qemu-devel] [PATCH v7 23/74] linux-user: Split out execve

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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;
+}
+

[Qemu-devel] [PATCH v7 24/74] linux-user: Implement execveat

2019-05-19 Thread Richard Henderson
A trivial extension to our current execve implementation
to support the new(ish) syscall.

Signed-off-by: Richard Henderson 
---
 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




[Qemu-devel] [PATCH v7 61/74] linux-user: Split out rt_sigtimedwait

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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(, p);
+unlock_user(p, arg1, 0);
+if (arg3) {
+puts = 
+target_to_host_timespec(puts, arg3);
+}
+
+ret = get_errno(safe_rt_sigtimedwait(, , 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, );
+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(, p);
-unlock_user(p, arg1, 0);
-if (arg3) {
-puts = 
-target_to_host_timespec(puts, arg3);
-} else {
-puts = NULL;
-}
-ret = get_errno(safe_rt_sigtimedwait(, , 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, );
-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




[Qemu-devel] [PATCH v7 60/74] linux-user: Split out sigsuspend, rt_sigsuspend

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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(>sigsuspend_mask, p);
+unlock_user(p, arg1, 0);
+
+ret = get_errno(safe_rt_sigsuspend(>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(>sigsuspend_mask, );
+#else
+void *p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
+if (!p) {
+return -TARGET_EFAULT;
+}
+target_to_host_old_sigset(>sigsuspend_mask, p);
+unlock_user(p, arg1, 0);
+#endif
+
+ret = get_errno(safe_rt_sigsuspend(>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(>sigsuspend_mask, );
-#else
-if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 
1)))
-return -TARGET_EFAULT;
-target_to_host_old_sigset(>sigsuspend_mask, p);
-unlock_user(p, arg1, 0);
-#endif
-ret = get_errno(safe_rt_sigsuspend(>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(>sigsuspend_mask, p);
-unlock_user(p, arg1, 0);
-ret = get_errno(safe_rt_sigsuspend(>sigsuspend_mask,
-   SIGSET_T_SIZE));
-if (ret != -TARGET_ERESTARTSYS) {
-ts->in_sigsuspend 

[Qemu-devel] [PATCH v7 43/74] linux-user: Split out pipe, pipe2

2019-05-19 Thread Richard Henderson
Note that pipe2 is universally available for guests.
Implement host support with syscall when !CONFIG_PIPE2.

Signed-off-by: Richard Henderson 
---
 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 062a75..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)
-|| 

[Qemu-devel] [PATCH v7 65/74] linux-user: Split out getrlimit, setrlimit

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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, ));
+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, ));
+} 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, ));
-} 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 = 

[Qemu-devel] [PATCH v7 66/74] linux-user: Split out getrusage

2019-05-19 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 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, ));
+
+if (!is_error(ret)) {
+ret = host_to_target_rusage(arg2, );
+}
+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, ));
-if (!is_error(ret)) {
-ret = host_to_target_rusage(arg2, );
-}
-}
-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




  1   2   >