All of lore.kernel.org
 help / color / mirror / Atom feed
* [PULL 00/10] Linux user for 7.0 patches
@ 2022-03-24  8:20 Laurent Vivier
  2022-03-24  8:20 ` [PULL 01/10] linux-user: Fix syscall parameter handling for MIPS n32 Laurent Vivier
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Laurent Vivier @ 2022-03-24  8:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier

The following changes since commit 48fb0a826eea2e7b0135f49e7fa63e7efe2b7677:

  Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging (2022-03-21 21:27:14 +0000)

are available in the Git repository at:

  https://gitlab.com/laurent_vivier/qemu.git tags/linux-user-for-7.0-pull-request

for you to fetch changes up to 330ea9d1d819680ac7501457220b8cd1c29f9d2f:

  linux-user/arm: Implement __kernel_cmpxchg64 with host atomics (2022-03-23 16:53:17 +0100)

----------------------------------------------------------------
linux-user pull request 20220324

Fix MIPS n32
Fix ppoll, epoll_wait, pselect
Fix error message in elfload.c
Implement ARM __kernel_memory_barrier/__kernel_cmpxchg/__kernel_cmpxchg64

----------------------------------------------------------------

Fergus Henderson (1):
  linux-user: Fix missing space in error message

Richard Henderson (8):
  linux-user/alpha: Fix sigsuspend for big-endian hosts
  linux-user: Split out helpers for sigsuspend
  linux-user: Properly handle sigset arg to pselect
  linux-user: Properly handle sigset arg to epoll_pwait
  linux-user: Properly handle sigset arg to ppoll
  linux-user/arm: Implement __kernel_memory_barrier
  linux-user/arm: Implement __kernel_cmpxchg with host atomics
  linux-user/arm: Implement __kernel_cmpxchg64 with host atomics

WANG Xuerui (1):
  linux-user: Fix syscall parameter handling for MIPS n32

 linux-user/arm/cpu_loop.c   | 164 ++++++++++++++++++++++--------------
 linux-user/elfload.c        |   2 +-
 linux-user/signal-common.h  |  26 ++++++
 linux-user/signal.c         |  23 +++++
 linux-user/syscall.c        | 119 ++++++++++----------------
 linux-user/user-internals.h |   6 +-
 6 files changed, 195 insertions(+), 145 deletions(-)

-- 
2.35.1



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

* [PULL 01/10] linux-user: Fix syscall parameter handling for MIPS n32
  2022-03-24  8:20 [PULL 00/10] Linux user for 7.0 patches Laurent Vivier
@ 2022-03-24  8:20 ` Laurent Vivier
  2022-03-24  8:20 ` [PULL 02/10] linux-user/alpha: Fix sigsuspend for big-endian hosts Laurent Vivier
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Laurent Vivier @ 2022-03-24  8:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: Andreas K . Hüttel, Richard Henderson, Laurent Vivier,
	Philippe Mathieu-Daudé,
	WANG Xuerui

From: WANG Xuerui <xen0n@gentoo.org>

The MIPS n32 ABI is basically n64 with the address space (i.e. pointer
width) shrinked to 32 bits. Meanwhile the current code treats it as
o32-like based on TARGET_ABI_BITS, which causes problems with n32
syscalls utilizing 64-bit offsets, like pread64, affecting most (if not
all) recently built n32 binaries.

This partially solves issue #909 ("qemu-mipsn32(el) user mode emulator
fails to execute any recently built n32 binaries"); with this change
applied, the built qemu-mipsn32el is able to progress beyond the
pread64, and finish _dl_start_user for the "getting ld.so load libc.so"
case. The program later dies with SIGBUS, though, due to _dl_start_user
not maintaining stack alignment after removing ld.so itself from argv,
and qemu-user starting to enforce alignment recently, but that is
orthogonal to the issue here; the more common case of chrooting is
working, verified with my own-built Gentoo n32 sysroot. (Depending on
the exact ISA used, one may have to explicitly specify QEMU_CPU, which
is the case for my chroot.)

Buglink: https://gitlab.com/qemu-project/qemu/-/issues/909
Signed-off-by: WANG Xuerui <xen0n@gentoo.org>
Cc: Laurent Vivier <laurent@vivier.eu>
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
Cc: Andreas K. Hüttel <dilfridge@gentoo.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20220320052259.1610883-1-xen0n@gentoo.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/user-internals.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h
index a8fdd6933b23..ee152ccfaa8f 100644
--- a/linux-user/user-internals.h
+++ b/linux-user/user-internals.h
@@ -112,7 +112,7 @@ static inline int is_error(abi_long ret)
     return (abi_ulong)ret >= (abi_ulong)(-4096);
 }
 
-#if TARGET_ABI_BITS == 32
+#if (TARGET_ABI_BITS == 32) && !defined(TARGET_ABI_MIPSN32)
 static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
 {
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -121,7 +121,7 @@ static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
     return ((uint64_t)word1 << 32) | word0;
 #endif
 }
-#else /* TARGET_ABI_BITS == 32 */
+#else /* TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32) */
 static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
 {
     return word0;
@@ -136,7 +136,7 @@ static inline int regpairs_aligned(void *cpu_env, int num)
 {
     return ((((CPUARMState *)cpu_env)->eabi) == 1) ;
 }
-#elif defined(TARGET_MIPS) && (TARGET_ABI_BITS == 32)
+#elif defined(TARGET_MIPS) && defined(TARGET_ABI_MIPSO32)
 static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
 #elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
 /*
-- 
2.35.1



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

* [PULL 02/10] linux-user/alpha: Fix sigsuspend for big-endian hosts
  2022-03-24  8:20 [PULL 00/10] Linux user for 7.0 patches Laurent Vivier
  2022-03-24  8:20 ` [PULL 01/10] linux-user: Fix syscall parameter handling for MIPS n32 Laurent Vivier
@ 2022-03-24  8:20 ` Laurent Vivier
  2022-03-24  8:20 ` [PULL 03/10] linux-user: Split out helpers for sigsuspend Laurent Vivier
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Laurent Vivier @ 2022-03-24  8:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Richard Henderson, Laurent Vivier

From: Richard Henderson <richard.henderson@linaro.org>

On alpha, the sigset argument for sigsuspend is in a register.
When we drop that into memory that happens in host-endianness,
but target_to_host_old_sigset will treat it as target-endianness.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20220315084308.433109-2-richard.henderson@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/syscall.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 75ed71eb461d..77cd88b53785 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -9559,7 +9559,8 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         {
             TaskState *ts = cpu->opaque;
 #if defined(TARGET_ALPHA)
-            abi_ulong mask = arg1;
+            /* target_to_host_old_sigset will bswap back */
+            abi_ulong mask = tswapal(arg1);
             target_to_host_old_sigset(&ts->sigsuspend_mask, &mask);
 #else
             if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
-- 
2.35.1



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

* [PULL 03/10] linux-user: Split out helpers for sigsuspend
  2022-03-24  8:20 [PULL 00/10] Linux user for 7.0 patches Laurent Vivier
  2022-03-24  8:20 ` [PULL 01/10] linux-user: Fix syscall parameter handling for MIPS n32 Laurent Vivier
  2022-03-24  8:20 ` [PULL 02/10] linux-user/alpha: Fix sigsuspend for big-endian hosts Laurent Vivier
@ 2022-03-24  8:20 ` Laurent Vivier
  2022-03-24  8:20 ` [PULL 04/10] linux-user: Properly handle sigset arg to pselect Laurent Vivier
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Laurent Vivier @ 2022-03-24  8:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Richard Henderson, Laurent Vivier

From: Richard Henderson <richard.henderson@linaro.org>

Two new functions: process_sigsuspend_mask and finish_sigsuspend_mask.
Move the size check and copy-from-user code.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20220315084308.433109-3-richard.henderson@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/signal-common.h | 26 +++++++++++++++++++++++++
 linux-user/signal.c        | 23 ++++++++++++++++++++++
 linux-user/syscall.c       | 40 ++++++++++++++++----------------------
 3 files changed, 66 insertions(+), 23 deletions(-)

diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h
index 2113165a7583..6a7e4a93fc13 100644
--- a/linux-user/signal-common.h
+++ b/linux-user/signal-common.h
@@ -92,4 +92,30 @@ abi_long do_swapcontext(CPUArchState *env, abi_ulong uold_ctx,
  */
 int block_signals(void); /* Returns non zero if signal pending */
 
+/**
+ * process_sigsuspend_mask: read and apply syscall-local signal mask
+ *
+ * Read the guest signal mask from @sigset, length @sigsize.
+ * Convert that to a host signal mask and save it to sigpending_mask.
+ *
+ * Return value: negative target errno, or zero;
+ *               store &sigpending_mask into *pset on success.
+ */
+int process_sigsuspend_mask(sigset_t **pset, target_ulong sigset,
+                            target_ulong sigsize);
+
+/**
+ * finish_sigsuspend_mask: finish a sigsuspend-like syscall
+ *
+ * Set in_sigsuspend if we need to use the modified sigset
+ * during process_pending_signals.
+ */
+static inline void finish_sigsuspend_mask(int ret)
+{
+    if (ret != -QEMU_ERESTARTSYS) {
+        TaskState *ts = (TaskState *)thread_cpu->opaque;
+        ts->in_sigsuspend = 1;
+    }
+}
+
 #endif
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 2a3f3cc23f92..092e70b80c6f 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1199,3 +1199,26 @@ void process_pending_signals(CPUArchState *cpu_env)
     }
     ts->in_sigsuspend = 0;
 }
+
+int process_sigsuspend_mask(sigset_t **pset, target_ulong sigset,
+                            target_ulong sigsize)
+{
+    TaskState *ts = (TaskState *)thread_cpu->opaque;
+    sigset_t *host_set = &ts->sigsuspend_mask;
+    target_sigset_t *target_sigset;
+
+    if (sigsize != sizeof(*target_sigset)) {
+        /* Like the kernel, we enforce correct size sigsets */
+        return -TARGET_EINVAL;
+    }
+
+    target_sigset = lock_user(VERIFY_READ, sigset, sigsize, 1);
+    if (!target_sigset) {
+        return -TARGET_EFAULT;
+    }
+    target_to_host_sigset(host_set, target_sigset);
+    unlock_user(target_sigset, sigset, 0);
+
+    *pset = host_set;
+    return 0;
+}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 77cd88b53785..d9b5662ff820 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -9557,41 +9557,35 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
 #ifdef TARGET_NR_sigsuspend
     case TARGET_NR_sigsuspend:
         {
-            TaskState *ts = cpu->opaque;
+            sigset_t *set;
+
 #if defined(TARGET_ALPHA)
+            TaskState *ts = cpu->opaque;
             /* target_to_host_old_sigset will bswap back */
             abi_ulong mask = tswapal(arg1);
-            target_to_host_old_sigset(&ts->sigsuspend_mask, &mask);
+            set = &ts->sigsuspend_mask;
+            target_to_host_old_sigset(set, &mask);
 #else
-            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
-                return -TARGET_EFAULT;
-            target_to_host_old_sigset(&ts->sigsuspend_mask, p);
-            unlock_user(p, arg1, 0);
-#endif
-            ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
-                                               SIGSET_T_SIZE));
-            if (ret != -QEMU_ERESTARTSYS) {
-                ts->in_sigsuspend = 1;
+            ret = process_sigsuspend_mask(&set, arg1, sizeof(target_sigset_t));
+            if (ret != 0) {
+                return ret;
             }
+#endif
+            ret = get_errno(safe_rt_sigsuspend(set, SIGSET_T_SIZE));
+            finish_sigsuspend_mask(ret);
         }
         return ret;
 #endif
     case TARGET_NR_rt_sigsuspend:
         {
-            TaskState *ts = cpu->opaque;
+            sigset_t *set;
 
-            if (arg2 != sizeof(target_sigset_t)) {
-                return -TARGET_EINVAL;
-            }
-            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
-                return -TARGET_EFAULT;
-            target_to_host_sigset(&ts->sigsuspend_mask, p);
-            unlock_user(p, arg1, 0);
-            ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
-                                               SIGSET_T_SIZE));
-            if (ret != -QEMU_ERESTARTSYS) {
-                ts->in_sigsuspend = 1;
+            ret = process_sigsuspend_mask(&set, arg1, arg2);
+            if (ret != 0) {
+                return ret;
             }
+            ret = get_errno(safe_rt_sigsuspend(set, SIGSET_T_SIZE));
+            finish_sigsuspend_mask(ret);
         }
         return ret;
 #ifdef TARGET_NR_rt_sigtimedwait
-- 
2.35.1



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

* [PULL 04/10] linux-user: Properly handle sigset arg to pselect
  2022-03-24  8:20 [PULL 00/10] Linux user for 7.0 patches Laurent Vivier
                   ` (2 preceding siblings ...)
  2022-03-24  8:20 ` [PULL 03/10] linux-user: Split out helpers for sigsuspend Laurent Vivier
@ 2022-03-24  8:20 ` Laurent Vivier
  2022-03-24  8:20 ` [PULL 05/10] linux-user: Properly handle sigset arg to epoll_pwait Laurent Vivier
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Laurent Vivier @ 2022-03-24  8:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Richard Henderson, Laurent Vivier

From: Richard Henderson <richard.henderson@linaro.org>

Unblocked signals are never delivered, because we
didn't record the new mask for process_pending_signals.
Handle this with the same mechanism as sigsuspend.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/834
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20220315084308.433109-4-richard.henderson@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/syscall.c | 30 ++++++++++--------------------
 1 file changed, 10 insertions(+), 20 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index d9b5662ff820..ffd4cefc8b7a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1391,14 +1391,12 @@ static abi_long do_pselect6(abi_long arg1, abi_long arg2, abi_long arg3,
      * 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;
@@ -1439,10 +1437,8 @@ static abi_long do_pselect6(abi_long arg1, abi_long arg2, abi_long arg3,
     }
 
     /* Extract the two packed args for the sigset */
+    sig_ptr = NULL;
     if (arg6) {
-        sig_ptr = &sig;
-        sig.size = SIGSET_T_SIZE;
-
         arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
         if (!arg7) {
             return -TARGET_EFAULT;
@@ -1452,28 +1448,22 @@ static abi_long do_pselect6(abi_long arg1, abi_long arg2, abi_long arg3,
         unlock_user(arg7, arg6, 0);
 
         if (arg_sigset) {
-            sig.set = &set;
-            if (arg_sigsize != sizeof(*target_sigset)) {
-                /* Like the kernel, we enforce correct size sigsets */
-                return -TARGET_EINVAL;
-            }
-            target_sigset = lock_user(VERIFY_READ, arg_sigset,
-                                      sizeof(*target_sigset), 1);
-            if (!target_sigset) {
-                return -TARGET_EFAULT;
+            ret = process_sigsuspend_mask(&sig.set, arg_sigset, arg_sigsize);
+            if (ret != 0) {
+                return ret;
             }
-            target_to_host_sigset(&set, target_sigset);
-            unlock_user(target_sigset, arg_sigset, 0);
-        } else {
-            sig.set = NULL;
+            sig_ptr = &sig;
+            sig.size = SIGSET_T_SIZE;
         }
-    } else {
-        sig_ptr = NULL;
     }
 
     ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
                                   ts_ptr, sig_ptr));
 
+    if (sig_ptr) {
+        finish_sigsuspend_mask(ret);
+    }
+
     if (!is_error(ret)) {
         if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) {
             return -TARGET_EFAULT;
-- 
2.35.1



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

* [PULL 05/10] linux-user: Properly handle sigset arg to epoll_pwait
  2022-03-24  8:20 [PULL 00/10] Linux user for 7.0 patches Laurent Vivier
                   ` (3 preceding siblings ...)
  2022-03-24  8:20 ` [PULL 04/10] linux-user: Properly handle sigset arg to pselect Laurent Vivier
@ 2022-03-24  8:20 ` Laurent Vivier
  2022-03-24  8:20 ` [PULL 06/10] linux-user: Properly handle sigset arg to ppoll Laurent Vivier
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Laurent Vivier @ 2022-03-24  8:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Richard Henderson, Laurent Vivier

From: Richard Henderson <richard.henderson@linaro.org>

Unblocked signals are never delivered, because we
didn't record the new mask for process_pending_signals.
Handle this with the same mechanism as sigsuspend.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20220315084308.433109-5-richard.henderson@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/syscall.c | 22 +++++++---------------
 1 file changed, 7 insertions(+), 15 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ffd4cefc8b7a..67af40deac07 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -12694,29 +12694,21 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
 #if defined(TARGET_NR_epoll_pwait)
         case TARGET_NR_epoll_pwait:
         {
-            target_sigset_t *target_set;
-            sigset_t _set, *set = &_set;
+            sigset_t *set = NULL;
 
             if (arg5) {
-                if (arg6 != sizeof(target_sigset_t)) {
-                    ret = -TARGET_EINVAL;
-                    break;
-                }
-
-                target_set = lock_user(VERIFY_READ, arg5,
-                                       sizeof(target_sigset_t), 1);
-                if (!target_set) {
-                    ret = -TARGET_EFAULT;
+                ret = process_sigsuspend_mask(&set, arg5, arg6);
+                if (ret != 0) {
                     break;
                 }
-                target_to_host_sigset(set, target_set);
-                unlock_user(target_set, arg5, 0);
-            } else {
-                set = NULL;
             }
 
             ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
                                              set, SIGSET_T_SIZE));
+
+            if (set) {
+                finish_sigsuspend_mask(ret);
+            }
             break;
         }
 #endif
-- 
2.35.1



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

* [PULL 06/10] linux-user: Properly handle sigset arg to ppoll
  2022-03-24  8:20 [PULL 00/10] Linux user for 7.0 patches Laurent Vivier
                   ` (4 preceding siblings ...)
  2022-03-24  8:20 ` [PULL 05/10] linux-user: Properly handle sigset arg to epoll_pwait Laurent Vivier
@ 2022-03-24  8:20 ` Laurent Vivier
  2022-03-24  8:20 ` [PULL 07/10] linux-user: Fix missing space in error message Laurent Vivier
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Laurent Vivier @ 2022-03-24  8:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Richard Henderson, Laurent Vivier

From: Richard Henderson <richard.henderson@linaro.org>

Unblocked signals are never delivered, because we
didn't record the new mask for process_pending_signals.
Handle this with the same mechanism as sigsuspend.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20220315084308.433109-6-richard.henderson@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/syscall.c | 24 +++++++-----------------
 1 file changed, 7 insertions(+), 17 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 67af40deac07..f65045efe6a2 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1519,8 +1519,7 @@ static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3,
     }
     if (ppoll) {
         struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
-        target_sigset_t *target_set;
-        sigset_t _set, *set = &_set;
+        sigset_t *set = NULL;
 
         if (arg3) {
             if (time64) {
@@ -1539,25 +1538,19 @@ static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3,
         }
 
         if (arg4) {
-            if (arg5 != sizeof(target_sigset_t)) {
-                unlock_user(target_pfd, arg1, 0);
-                return -TARGET_EINVAL;
-            }
-
-            target_set = lock_user(VERIFY_READ, arg4,
-                                   sizeof(target_sigset_t), 1);
-            if (!target_set) {
+            ret = process_sigsuspend_mask(&set, arg4, arg5);
+            if (ret != 0) {
                 unlock_user(target_pfd, arg1, 0);
-                return -TARGET_EFAULT;
+                return ret;
             }
-            target_to_host_sigset(set, target_set);
-        } else {
-            set = NULL;
         }
 
         ret = get_errno(safe_ppoll(pfd, nfds, timeout_ts,
                                    set, SIGSET_T_SIZE));
 
+        if (set) {
+            finish_sigsuspend_mask(ret);
+        }
         if (!is_error(ret) && arg3) {
             if (time64) {
                 if (host_to_target_timespec64(arg3, timeout_ts)) {
@@ -1569,9 +1562,6 @@ static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3,
                 }
             }
         }
-        if (arg4) {
-            unlock_user(target_set, arg4, 0);
-        }
     } else {
           struct timespec ts, *pts;
 
-- 
2.35.1



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

* [PULL 07/10] linux-user: Fix missing space in error message
  2022-03-24  8:20 [PULL 00/10] Linux user for 7.0 patches Laurent Vivier
                   ` (5 preceding siblings ...)
  2022-03-24  8:20 ` [PULL 06/10] linux-user: Properly handle sigset arg to ppoll Laurent Vivier
@ 2022-03-24  8:20 ` Laurent Vivier
  2022-03-24  8:20 ` [PULL 08/10] linux-user/arm: Implement __kernel_memory_barrier Laurent Vivier
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Laurent Vivier @ 2022-03-24  8:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: Patrick Venture, Fergus Henderson, Laurent Vivier,
	Philippe Mathieu-Daudé,
	Peter Maydell

From: Fergus Henderson <fergus@google.com>

Signed-off-by: Fergus Henderson <fergus@google.com>
Signed-off-by: Patrick Venture <venture@google.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20220310192148.1696486-1-venture@google.com>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/elfload.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 9628a38361cb..c45da4d63375 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2504,7 +2504,7 @@ static void pgb_reserved_va(const char *image_name, abi_ulong guest_loaddr,
     addr = mmap(test, reserved_va, PROT_NONE, flags, -1, 0);
     if (addr == MAP_FAILED || addr != test) {
         error_report("Unable to reserve 0x%lx bytes of virtual address "
-                     "space at %p (%s) for use as guest address space (check your"
+                     "space at %p (%s) for use as guest address space (check your "
                      "virtual memory ulimit setting, min_mmap_addr or reserve less "
                      "using -R option)", reserved_va, test, strerror(errno));
         exit(EXIT_FAILURE);
-- 
2.35.1



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

* [PULL 08/10] linux-user/arm: Implement __kernel_memory_barrier
  2022-03-24  8:20 [PULL 00/10] Linux user for 7.0 patches Laurent Vivier
                   ` (6 preceding siblings ...)
  2022-03-24  8:20 ` [PULL 07/10] linux-user: Fix missing space in error message Laurent Vivier
@ 2022-03-24  8:20 ` Laurent Vivier
  2022-03-24  8:20 ` [PULL 09/10] linux-user/arm: Implement __kernel_cmpxchg with host atomics Laurent Vivier
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Laurent Vivier @ 2022-03-24  8:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Richard Henderson, Laurent Vivier

From: Richard Henderson <richard.henderson@linaro.org>

This fallback syscall was stubbed out.
It would only matter for emulating pre-armv6.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20220323005839.94327-2-richard.henderson@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/arm/cpu_loop.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
index 032e1ffddfbd..a0e43b261c7b 100644
--- a/linux-user/arm/cpu_loop.c
+++ b/linux-user/arm/cpu_loop.c
@@ -158,7 +158,7 @@ do_kernel_trap(CPUARMState *env)
 
     switch (env->regs[15]) {
     case 0xffff0fa0: /* __kernel_memory_barrier */
-        /* ??? No-op. Will need to do better for SMP.  */
+        smp_mb();
         break;
     case 0xffff0fc0: /* __kernel_cmpxchg */
          /* XXX: This only works between threads, not between processes.
-- 
2.35.1



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

* [PULL 09/10] linux-user/arm: Implement __kernel_cmpxchg with host atomics
  2022-03-24  8:20 [PULL 00/10] Linux user for 7.0 patches Laurent Vivier
                   ` (7 preceding siblings ...)
  2022-03-24  8:20 ` [PULL 08/10] linux-user/arm: Implement __kernel_memory_barrier Laurent Vivier
@ 2022-03-24  8:20 ` Laurent Vivier
  2022-03-24  8:20 ` [PULL 10/10] linux-user/arm: Implement __kernel_cmpxchg64 " Laurent Vivier
  2022-03-24 20:08 ` [PULL 00/10] Linux user for 7.0 patches Peter Maydell
  10 siblings, 0 replies; 12+ messages in thread
From: Laurent Vivier @ 2022-03-24  8:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Richard Henderson, Laurent Vivier

From: Richard Henderson <richard.henderson@linaro.org>

The existing implementation using start/end_exclusive
does not provide atomicity across processes.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20220323005839.94327-3-richard.henderson@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/arm/cpu_loop.c | 87 ++++++++++++++++++++++++++++-----------
 1 file changed, 62 insertions(+), 25 deletions(-)

diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
index a0e43b261c7b..aa2d777bf449 100644
--- a/linux-user/arm/cpu_loop.c
+++ b/linux-user/arm/cpu_loop.c
@@ -75,7 +75,67 @@
         put_user_u16(__x, (gaddr));                     \
     })
 
-/* Commpage handling -- there is no commpage for AArch64 */
+/*
+ * Similar to code in accel/tcg/user-exec.c, but outside the execution loop.
+ * Must be called with mmap_lock.
+ * We get the PC of the entry address - which is as good as anything,
+ * on a real kernel what you get depends on which mode it uses.
+ */
+static void *atomic_mmu_lookup(CPUArchState *env, uint32_t addr, int size)
+{
+    int need_flags = PAGE_READ | PAGE_WRITE_ORG | PAGE_VALID;
+    int page_flags;
+
+    /* Enforce guest required alignment.  */
+    if (unlikely(addr & (size - 1))) {
+        force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN, addr);
+        return NULL;
+    }
+
+    page_flags = page_get_flags(addr);
+    if (unlikely((page_flags & need_flags) != need_flags)) {
+        force_sig_fault(TARGET_SIGSEGV,
+                        page_flags & PAGE_VALID ?
+                        TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR, addr);
+        return NULL;
+    }
+
+    return g2h(env_cpu(env), addr);
+}
+
+/*
+ * See the Linux kernel's Documentation/arm/kernel_user_helpers.rst
+ * Input:
+ * r0 = oldval
+ * r1 = newval
+ * r2 = pointer to target value
+ *
+ * Output:
+ * r0 = 0 if *ptr was changed, non-0 if no exchange happened
+ * C set if *ptr was changed, clear if no exchange happened
+ */
+static void arm_kernel_cmpxchg32_helper(CPUARMState *env)
+{
+    uint32_t oldval, newval, val, addr, cpsr, *host_addr;
+
+    oldval = env->regs[0];
+    newval = env->regs[1];
+    addr = env->regs[2];
+
+    mmap_lock();
+    host_addr = atomic_mmu_lookup(env, addr, 4);
+    if (!host_addr) {
+        mmap_unlock();
+        return;
+    }
+
+    val = qatomic_cmpxchg__nocheck(host_addr, oldval, newval);
+    mmap_unlock();
+
+    cpsr = (val == oldval) * CPSR_C;
+    cpsr_write(env, cpsr, CPSR_C, CPSRWriteByInstr);
+    env->regs[0] = cpsr ? 0 : -1;
+}
 
 /*
  * See the Linux kernel's Documentation/arm/kernel_user_helpers.txt
@@ -153,36 +213,13 @@ static int
 do_kernel_trap(CPUARMState *env)
 {
     uint32_t addr;
-    uint32_t cpsr;
-    uint32_t val;
 
     switch (env->regs[15]) {
     case 0xffff0fa0: /* __kernel_memory_barrier */
         smp_mb();
         break;
     case 0xffff0fc0: /* __kernel_cmpxchg */
-         /* XXX: This only works between threads, not between processes.
-            It's probably possible to implement this with native host
-            operations. However things like ldrex/strex are much harder so
-            there's not much point trying.  */
-        start_exclusive();
-        cpsr = cpsr_read(env);
-        addr = env->regs[2];
-        /* FIXME: This should SEGV if the access fails.  */
-        if (get_user_u32(val, addr))
-            val = ~env->regs[0];
-        if (val == env->regs[0]) {
-            val = env->regs[1];
-            /* FIXME: Check for segfaults.  */
-            put_user_u32(val, addr);
-            env->regs[0] = 0;
-            cpsr |= CPSR_C;
-        } else {
-            env->regs[0] = -1;
-            cpsr &= ~CPSR_C;
-        }
-        cpsr_write(env, cpsr, CPSR_C, CPSRWriteByInstr);
-        end_exclusive();
+        arm_kernel_cmpxchg32_helper(env);
         break;
     case 0xffff0fe0: /* __kernel_get_tls */
         env->regs[0] = cpu_get_tls(env);
-- 
2.35.1



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

* [PULL 10/10] linux-user/arm: Implement __kernel_cmpxchg64 with host atomics
  2022-03-24  8:20 [PULL 00/10] Linux user for 7.0 patches Laurent Vivier
                   ` (8 preceding siblings ...)
  2022-03-24  8:20 ` [PULL 09/10] linux-user/arm: Implement __kernel_cmpxchg with host atomics Laurent Vivier
@ 2022-03-24  8:20 ` Laurent Vivier
  2022-03-24 20:08 ` [PULL 00/10] Linux user for 7.0 patches Peter Maydell
  10 siblings, 0 replies; 12+ messages in thread
From: Laurent Vivier @ 2022-03-24  8:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Richard Henderson, Laurent Vivier

From: Richard Henderson <richard.henderson@linaro.org>

If CONFIG_ATOMIC64, we can use a host cmpxchg and provide
atomicity across processes; otherwise we have no choice but
to continue using start/end_exclusive.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20220323005839.94327-4-richard.henderson@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/arm/cpu_loop.c | 75 +++++++++++++++++++--------------------
 1 file changed, 36 insertions(+), 39 deletions(-)

diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
index aa2d777bf449..aae375d61792 100644
--- a/linux-user/arm/cpu_loop.c
+++ b/linux-user/arm/cpu_loop.c
@@ -138,7 +138,7 @@ static void arm_kernel_cmpxchg32_helper(CPUARMState *env)
 }
 
 /*
- * See the Linux kernel's Documentation/arm/kernel_user_helpers.txt
+ * See the Linux kernel's Documentation/arm/kernel_user_helpers.rst
  * Input:
  * r0 = pointer to oldval
  * r1 = pointer to newval
@@ -155,57 +155,54 @@ static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
 {
     uint64_t oldval, newval, val;
     uint32_t addr, cpsr;
+    uint64_t *host_addr;
 
-    /* Based on the 32 bit code in do_kernel_trap */
-
-    /* XXX: This only works between threads, not between processes.
-       It's probably possible to implement this with native host
-       operations. However things like ldrex/strex are much harder so
-       there's not much point trying.  */
-    start_exclusive();
-    cpsr = cpsr_read(env);
-    addr = env->regs[2];
-
-    if (get_user_u64(oldval, env->regs[0])) {
-        env->exception.vaddress = env->regs[0];
+    addr = env->regs[0];
+    if (get_user_u64(oldval, addr)) {
         goto segv;
-    };
+    }
 
-    if (get_user_u64(newval, env->regs[1])) {
-        env->exception.vaddress = env->regs[1];
+    addr = env->regs[1];
+    if (get_user_u64(newval, addr)) {
         goto segv;
-    };
+    }
 
-    if (get_user_u64(val, addr)) {
-        env->exception.vaddress = addr;
-        goto segv;
+    mmap_lock();
+    addr = env->regs[2];
+    host_addr = atomic_mmu_lookup(env, addr, 8);
+    if (!host_addr) {
+        mmap_unlock();
+        return;
     }
 
+#ifdef CONFIG_ATOMIC64
+    val = qatomic_cmpxchg__nocheck(host_addr, oldval, newval);
+    cpsr = (val == oldval) * CPSR_C;
+#else
+    /*
+     * This only works between threads, not between processes, but since
+     * the host has no 64-bit cmpxchg, it is the best that we can do.
+     */
+    start_exclusive();
+    val = *host_addr;
     if (val == oldval) {
-        val = newval;
-
-        if (put_user_u64(val, addr)) {
-            env->exception.vaddress = addr;
-            goto segv;
-        };
-
-        env->regs[0] = 0;
-        cpsr |= CPSR_C;
+        *host_addr = newval;
+        cpsr = CPSR_C;
     } else {
-        env->regs[0] = -1;
-        cpsr &= ~CPSR_C;
+        cpsr = 0;
     }
-    cpsr_write(env, cpsr, CPSR_C, CPSRWriteByInstr);
     end_exclusive();
+#endif
+    mmap_unlock();
+
+    cpsr_write(env, cpsr, CPSR_C, CPSRWriteByInstr);
+    env->regs[0] = cpsr ? 0 : -1;
     return;
 
-segv:
-    end_exclusive();
-    /* We get the PC of the entry address - which is as good as anything,
-       on a real kernel what you get depends on which mode it uses. */
-    /* XXX: check env->error_code */
-    force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR,
-                    env->exception.vaddress);
+ segv:
+    force_sig_fault(TARGET_SIGSEGV,
+                    page_get_flags(addr) & PAGE_VALID ?
+                    TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR, addr);
 }
 
 /* Handle a jump to the kernel code page.  */
-- 
2.35.1



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

* Re: [PULL 00/10] Linux user for 7.0 patches
  2022-03-24  8:20 [PULL 00/10] Linux user for 7.0 patches Laurent Vivier
                   ` (9 preceding siblings ...)
  2022-03-24  8:20 ` [PULL 10/10] linux-user/arm: Implement __kernel_cmpxchg64 " Laurent Vivier
@ 2022-03-24 20:08 ` Peter Maydell
  10 siblings, 0 replies; 12+ messages in thread
From: Peter Maydell @ 2022-03-24 20:08 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: qemu-devel

On Thu, 24 Mar 2022 at 08:29, Laurent Vivier <laurent@vivier.eu> wrote:
>
> The following changes since commit 48fb0a826eea2e7b0135f49e7fa63e7efe2b7677:
>
>   Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging (2022-03-21 21:27:14 +0000)
>
> are available in the Git repository at:
>
>   https://gitlab.com/laurent_vivier/qemu.git tags/linux-user-for-7.0-pull-request
>
> for you to fetch changes up to 330ea9d1d819680ac7501457220b8cd1c29f9d2f:
>
>   linux-user/arm: Implement __kernel_cmpxchg64 with host atomics (2022-03-23 16:53:17 +0100)
>
> ----------------------------------------------------------------
> linux-user pull request 20220324
>
> Fix MIPS n32
> Fix ppoll, epoll_wait, pselect
> Fix error message in elfload.c
> Implement ARM __kernel_memory_barrier/__kernel_cmpxchg/__kernel_cmpxchg64
>


Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/7.0
for any user-visible changes.

-- PMM


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

end of thread, other threads:[~2022-03-24 20:09 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-24  8:20 [PULL 00/10] Linux user for 7.0 patches Laurent Vivier
2022-03-24  8:20 ` [PULL 01/10] linux-user: Fix syscall parameter handling for MIPS n32 Laurent Vivier
2022-03-24  8:20 ` [PULL 02/10] linux-user/alpha: Fix sigsuspend for big-endian hosts Laurent Vivier
2022-03-24  8:20 ` [PULL 03/10] linux-user: Split out helpers for sigsuspend Laurent Vivier
2022-03-24  8:20 ` [PULL 04/10] linux-user: Properly handle sigset arg to pselect Laurent Vivier
2022-03-24  8:20 ` [PULL 05/10] linux-user: Properly handle sigset arg to epoll_pwait Laurent Vivier
2022-03-24  8:20 ` [PULL 06/10] linux-user: Properly handle sigset arg to ppoll Laurent Vivier
2022-03-24  8:20 ` [PULL 07/10] linux-user: Fix missing space in error message Laurent Vivier
2022-03-24  8:20 ` [PULL 08/10] linux-user/arm: Implement __kernel_memory_barrier Laurent Vivier
2022-03-24  8:20 ` [PULL 09/10] linux-user/arm: Implement __kernel_cmpxchg with host atomics Laurent Vivier
2022-03-24  8:20 ` [PULL 10/10] linux-user/arm: Implement __kernel_cmpxchg64 " Laurent Vivier
2022-03-24 20:08 ` [PULL 00/10] Linux user for 7.0 patches Peter Maydell

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