qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [4616] NPTL host detection and futex syscall passthrough.
@ 2008-05-29 14:34 Paul Brook
  2008-05-29 15:00 ` Stuart Anderson
  2008-05-30  9:39 ` Kirill A. Shutemov
  0 siblings, 2 replies; 5+ messages in thread
From: Paul Brook @ 2008-05-29 14:34 UTC (permalink / raw)
  To: qemu-devel

Revision: 4616
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4616
Author:   pbrook
Date:     2008-05-29 14:34:11 +0000 (Thu, 29 May 2008)

Log Message:
-----------
NPTL host detection and futex syscall passthrough.

Modified Paths:
--------------
    trunk/configure
    trunk/linux-user/syscall.c

Modified: trunk/configure
===================================================================
--- trunk/configure	2008-05-29 13:56:10 UTC (rev 4615)
+++ trunk/configure	2008-05-29 14:34:11 UTC (rev 4616)
@@ -112,6 +112,7 @@
 build_docs="no"
 uname_release=""
 curses="yes"
+nptl="yes"
 
 # OS specific
 targetos=`uname -s`
@@ -331,6 +332,8 @@
   ;;
   --disable-curses) curses="no"
   ;;
+  --disable-nptl) nptl="no"
+  ;;
   *) echo "ERROR: unknown option $opt"; show_help="yes"
   ;;
   esac
@@ -424,6 +427,7 @@
 echo "  --disable-brlapi         disable BrlAPI"
 echo "  --disable-vnc-tls        disable TLS encryption for VNC server"
 echo "  --disable-curses         disable curses output"
+echo "  --disable-nptl           disable usermode NPTL support"
 echo "  --enable-system          enable all system emulation targets"
 echo "  --disable-system         disable all system emulation targets"
 echo "  --enable-linux-user      enable all linux usermode emulation targets"
@@ -641,6 +645,24 @@
 }
 EOF
 
+# Check host NPTL support
+cat > $TMPC <<EOF
+#include <sched.h>
+#include <sys/futex.h>
+void foo()
+{
+#if !defined(CLONE_SETTLS) || !defined(FUTEX_WAIT)
+#error bork
+#endif
+}
+EOF
+
+if $cc $ARCH_CFLAGS -c -o $TMPO $TMPC 2> /dev/null ; then
+  :
+else
+   nptl="no"
+fi
+
 ##########################################
 # SDL probe
 
@@ -839,6 +861,7 @@
 echo "Documentation     $build_docs"
 [ ! -z "$uname_release" ] && \
 echo "uname -r          $uname_release"
+echo "NPTL support      $nptl"
 
 if test $sdl_too_old = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -1190,6 +1213,7 @@
 
 bflt="no"
 elfload32="no"
+target_nptl="no"
 interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"`
 echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h
 
@@ -1232,6 +1256,7 @@
     echo "#define TARGET_ARCH \"arm\"" >> $config_h
     echo "#define TARGET_ARM 1" >> $config_h
     bflt="yes"
+    target_nptl="yes"
   ;;
   cris)
     echo "TARGET_ARCH=cris" >> $config_mak
@@ -1379,6 +1404,10 @@
   echo "TARGET_HAS_BFLT=yes" >> $config_mak
   echo "#define TARGET_HAS_BFLT 1" >> $config_h
 fi
+if test "$target_user_only" = "yes" \
+        -a "$nptl" = "yes" -a "$target_nptl" = "yes"; then
+  echo "#define USE_NPTL 1" >> $config_h
+fi
 # 32 bit ELF loader in addition to native 64 bit loader?
 if test "$target_user_only" = "yes" -a "$elfload32" = "yes"; then
   echo "TARGET_HAS_ELFLOAD32=yes" >> $config_mak

Modified: trunk/linux-user/syscall.c
===================================================================
--- trunk/linux-user/syscall.c	2008-05-29 13:56:10 UTC (rev 4615)
+++ trunk/linux-user/syscall.c	2008-05-29 14:34:11 UTC (rev 4616)
@@ -52,6 +52,9 @@
 //#include <sys/user.h>
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
+#if defined(USE_NPTL)
+#include <sys/futex.h>
+#endif
 
 #define termios host_termios
 #define winsize host_winsize
@@ -160,6 +163,7 @@
 #define __NR_sys_tkill __NR_tkill
 #define __NR_sys_unlinkat __NR_unlinkat
 #define __NR_sys_utimensat __NR_utimensat
+#define __NR_sys_futex __NR_futex
 
 #if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
 #define __NR__llseek __NR_lseek
@@ -241,6 +245,11 @@
 _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
           const struct timespec *,tsp,int,flags)
 #endif
+#if defined(TARGET_NR_futex) && defined(__NR_futex)
+_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
+          const struct timespec *,timeout,int *,uaddr2,int,val3)
+          
+#endif
 
 extern int personality(int);
 extern int flock(int, int);
@@ -2718,6 +2727,14 @@
     CPUState *new_env;
 
     if (flags & CLONE_VM) {
+#if defined(USE_NPTL)
+        /* qemu is not threadsafe.  Bail out immediately if application
+           tries to create a thread.  */
+        if (!(flags & CLONE_VFORK)) {
+            gemu_log ("clone(CLONE_VM) not supported\n");
+            return -EINVAL;
+        }
+#endif
         ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE);
         memset(ts, 0, sizeof(TaskState));
         new_stack = ts->stack;
@@ -3056,6 +3073,45 @@
     return 0;
 }
 
+#if defined(USE_NPTL)
+/* ??? 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
+   tricky.  However they're probably useless because guest atomic
+   operations won't work either.  */
+int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
+             target_ulong uaddr2, int val3)
+{
+    struct timespec ts, *pts;
+
+    /* ??? We assume FUTEX_* constants are the same on both host
+       and target.  */
+    switch (op) {
+    case FUTEX_WAIT:
+        if (timeout) {
+            pts = &ts;
+            target_to_host_timespec(pts, timeout);
+        } else {
+            pts = NULL;
+        }
+        return get_errno(sys_futex(g2h(uaddr), FUTEX_WAIT, tswap32(val),
+                         pts, NULL, 0));
+    case FUTEX_WAKE:
+        return get_errno(sys_futex(g2h(uaddr), FUTEX_WAKE, val, NULL, NULL, 0));
+    case FUTEX_FD:
+        return get_errno(sys_futex(g2h(uaddr), FUTEX_FD, val, NULL, NULL, 0));
+    case FUTEX_REQUEUE:
+        return get_errno(sys_futex(g2h(uaddr), FUTEX_REQUEUE, val,
+                         NULL, g2h(uaddr2), 0));
+    case FUTEX_CMP_REQUEUE:
+        return get_errno(sys_futex(g2h(uaddr), FUTEX_CMP_REQUEUE, val,
+                         NULL, g2h(uaddr2), tswap32(val3)));
+    default:
+        return -TARGET_ENOSYS;
+    }
+}
+#endif
+
 int get_osversion(void)
 {
     static int osversion;
@@ -5614,6 +5670,11 @@
         }
 	break;
 #endif
+#if defined(USE_NPTL)
+    case TARGET_NR_futex:
+        ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
+        break;
+#endif
 
     default:
     unimplemented:

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

* Re: [Qemu-devel] [4616] NPTL host detection and futex syscall passthrough.
  2008-05-29 14:34 [Qemu-devel] [4616] NPTL host detection and futex syscall passthrough Paul Brook
@ 2008-05-29 15:00 ` Stuart Anderson
  2008-05-29 15:14   ` Paul Brook
  2008-05-30  9:39 ` Kirill A. Shutemov
  1 sibling, 1 reply; 5+ messages in thread
From: Stuart Anderson @ 2008-05-29 15:00 UTC (permalink / raw)
  To: qemu-devel

On Thu, 29 May 2008, Paul Brook wrote:

> Revision: 4616
>          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4616
> Author:   pbrook
> Date:     2008-05-29 14:34:11 +0000 (Thu, 29 May 2008)
>
> Log Message:
> -----------
> NPTL host detection and futex syscall passthrough.


I'm glad to see this (and the recent TLS) patches make it in finally!

This patch however doesn't handle private futexes which we're now seeing
in the field, nor does it handle byte swaping as is needed for certain
host/target combinations.

Here is the patch that we've been using for a while now. I'll eventually
be able to resync w/ current svn, and send an updated patch to the list,
but it may be awhile so I'm just sending what I've got in case someone
else can get to it before I do.


Author: Stuart R. Anderson <anderson@netsweng.com>

     This patch provides an implementation for the futex() syscall.

Index: olmec-qemu/linux-user/syscall.c
===================================================================
--- olmec-qemu.orig/linux-user/syscall.c
+++ olmec-qemu/linux-user/syscall.c
@@ -17,6 +17,8 @@
   *  along with this program; if not, write to the Free Software
   *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   */
+
+#define __user
  #include <stddef.h>
  #include <stdlib.h>
  #include <stdio.h>
@@ -61,6 +63,7 @@
  #define tchars host_tchars /* same as target */
  #define ltchars host_ltchars /* same as target */

+#include <linux/futex.h>
  #include <linux/termios.h>
  #include <linux/unistd.h>
  #include <linux/utsname.h>
@@ -3310,6 +3313,114 @@
      return 0;
  }

+#if defined(TARGET_NR_futex)
+#ifdef BSWAP_NEEDED
+static int futex_op(int oldval, int op, int oparg)
+{
+    int retval = oparg;
+    switch(op) {
+        case FUTEX_OP_SET: break;
+        case FUTEX_OP_ADD: retval += oparg; break;
+        case FUTEX_OP_OR: retval |= oparg; break;
+        case FUTEX_OP_ANDN: retval &= oparg; break;
+        case FUTEX_OP_XOR: retval ^= oparg; break;
+    }
+    return retval;
+}
+
+static int futex_cmp(int oldval, int cmp, int cmparg)
+{
+    switch(cmp) {
+        case FUTEX_OP_CMP_EQ: return oldval == cmparg;
+        case FUTEX_OP_CMP_NE: return oldval != cmparg;
+        case FUTEX_OP_CMP_LT: return oldval <  cmparg;
+        case FUTEX_OP_CMP_LE: return oldval <= cmparg;
+        case FUTEX_OP_CMP_GT: return oldval >  cmparg;
+        case FUTEX_OP_CMP_GE: return oldval >= cmparg;
+    }
+    return -1;
+}
+#endif
+
+#if !defined(FUTEX_PRIVATE_FLAG)
+#define FUTEX_PRIVATE_FLAG      128
+#define FUTEX_CMD_MASK          ~FUTEX_PRIVATE_FLAG
+
+#define FUTEX_WAIT_PRIVATE      (FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAKE_PRIVATE      (FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
+#define FUTEX_REQUEUE_PRIVATE   (FUTEX_REQUEUE | FUTEX_PRIVATE_FLAG)
+#define FUTEX_CMP_REQUEUE_PRIVATE (FUTEX_CMP_REQUEUE | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAKE_OP_PRIVATE   (FUTEX_WAKE_OP | FUTEX_PRIVATE_FLAG)
+#define FUTEX_LOCK_PI_PRIVATE   (FUTEX_LOCK_PI | FUTEX_PRIVATE_FLAG)
+#define FUTEX_UNLOCK_PI_PRIVATE (FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG)
+#define FUTEX_TRYLOCK_PI_PRIVATE (FUTEX_TRYLOCK_PI | FUTEX_PRIVATE_FLAG)
+#endif
+
+static abi_long do_futex(abi_ulong uaddr, int op, uint32_t val,
+                         abi_ulong utime, abi_ulong uaddr2,
+                         uint32_t val3)
+{
+    struct timespec host_utime;
+    unsigned long val2 = utime;
+    long retval;
+
+    if (utime && ((op&FUTEX_CMD_MASK) == FUTEX_WAIT || (op&FUTEX_CMD_MASK) == FUTEX_LOCK_PI)) {
+        if (target_to_host_timespec(&host_utime, utime))
+            return -TARGET_EFAULT;
+        val2 = (unsigned long)&host_utime;
+    }
+
+#ifdef BSWAP_NEEDED
+    switch(op&FUTEX_CMD_MASK) {
+    case FUTEX_CMP_REQUEUE:
+        val3 = tswap32(val3);
+    case FUTEX_REQUEUE:
+        val2 = tswap32(val2);
+    case FUTEX_WAIT:
+    case FUTEX_WAKE:
+    case FUTEX_WAKE_OP:
+        val = tswap32(val);
+    case FUTEX_LOCK_PI: /* This one's icky, but comes out OK */
+    case FUTEX_UNLOCK_PI:
+        break;
+    default:
+        gemu_log("qemu: Unsupported futex op %d\n", op);
+        return -ENOSYS;
+    }
+    if ((op&FUTEX_CMD_MASK) == FUTEX_WAKE_OP) {
+        /* Need to munge the secondary operation (val3) */
+        gemu_log("qemu: Tricky FUTEX_WAKE_OP - trying to emulate it\n");
+        val3 = tswap32(val3);
+        int op2 = (val3 >> 28) & 0xf;
+        int cmp = (val3 >> 24) & 0xf;
+        int oparg = (val3 >> 12) & 0xfff;
+        int cmparg = val3 & 0xfff;
+        int shift = val3 & (FUTEX_OP_OPARG_SHIFT << 28);
+        int oldval;
+
+        if (get_user_s32(oldval, uaddr2))
+            return -TARGET_EFAULT;
+
+        if (shift)
+            oparg = 1 << oparg;
+
+        if (put_user_s32(futex_op(oldval, op2, oparg), uaddr2))
+            return -TARGET_EFAULT;
+
+        retval = syscall(__NR_futex, g2h(uaddr), op, val, 0, 0, 0);
+        if(futex_cmp(oldval, cmp, cmparg)) {
+            retval = syscall(__NR_futex, g2h(uaddr2), op, val2, 0, 0, 0);
+        }
+    } else {
+        retval = syscall(__NR_futex, g2h(uaddr), op, val, val2, g2h(uaddr2), val3);
+    }
+#else
+    retval = syscall(__NR_futex, g2h(uaddr), op, val, val2, g2h(uaddr2), val3);
+#endif
+    return retval;
+}
+#endif /* defined(TARGET_NR_futex) */
+
  /* do_syscall() should always have a single exit point at the end so
     that actions, such as logging of syscall results, can be performed.
     All errnos that do_syscall() returns must be -TARGET_<errcode>. */
@@ -5792,6 +5903,11 @@
      }
  #endif

+#ifdef TARGET_NR_futex
+    case TARGET_NR_futex:
+        ret = get_errno(do_futex(arg1, arg2, arg3, arg4, arg5, arg6));
+        break;
+#endif
  #if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
      case TARGET_NR_set_tid_address:
          ret = get_errno(set_tid_address((int *)g2h(arg1)));


                                 Stuart

Stuart R. Anderson                               anderson@netsweng.com
Network & Software Engineering                   http://www.netsweng.com/
1024D/37A79149:                                  0791 D3B8 9A4C 2CDC A31F
                                                  BD03 0A62 E534 37A7 9149

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

* Re: [Qemu-devel] [4616] NPTL host detection and futex syscall passthrough.
  2008-05-29 15:00 ` Stuart Anderson
@ 2008-05-29 15:14   ` Paul Brook
  0 siblings, 0 replies; 5+ messages in thread
From: Paul Brook @ 2008-05-29 15:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stuart Anderson

On Thursday 29 May 2008, Stuart Anderson wrote:
> On Thu, 29 May 2008, Paul Brook wrote:
> > Revision: 4616
> >          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4616
> > Author:   pbrook
> > Date:     2008-05-29 14:34:11 +0000 (Thu, 29 May 2008)
> >
> > Log Message:
> > -----------
> > NPTL host detection and futex syscall passthrough.
>
> I'm glad to see this (and the recent TLS) patches make it in finally!
>
> This patch however doesn't handle private futexes which we're now seeing
> in the field, nor does it handle byte swaping as is needed for certain
> host/target combinations.

Byteswapping should work fine.

Paul

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

* Re: [Qemu-devel] [4616] NPTL host detection and futex syscall passthrough.
  2008-05-29 14:34 [Qemu-devel] [4616] NPTL host detection and futex syscall passthrough Paul Brook
  2008-05-29 15:00 ` Stuart Anderson
@ 2008-05-30  9:39 ` Kirill A. Shutemov
  2008-05-30 13:14   ` Paul Brook
  1 sibling, 1 reply; 5+ messages in thread
From: Kirill A. Shutemov @ 2008-05-30  9:39 UTC (permalink / raw)
  To: qemu-devel

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

On Thu, May 29, 2008 at 02:34:12PM +0000, Paul Brook wrote:
> Revision: 4616
>           http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4616
> Author:   pbrook
> Date:     2008-05-29 14:34:11 +0000 (Thu, 29 May 2008)
> 
> Log Message:
> -----------
> NPTL host detection and futex syscall passthrough.

This patch has no support for NPTL-specific clone flags (CLONE_*TID),
which was in your NPTL patch. Do you have any plans to add it?

-- 
Regards,  Kirill A. Shutemov
 + Belarus, Minsk
 + ALT Linux Team, http://www.altlinux.com/

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [Qemu-devel] [4616] NPTL host detection and futex syscall passthrough.
  2008-05-30  9:39 ` Kirill A. Shutemov
@ 2008-05-30 13:14   ` Paul Brook
  0 siblings, 0 replies; 5+ messages in thread
From: Paul Brook @ 2008-05-30 13:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kirill A. Shutemov

On Friday 30 May 2008, Kirill A. Shutemov wrote:
> On Thu, May 29, 2008 at 02:34:12PM +0000, Paul Brook wrote:
> > Revision: 4616
> >           http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4616
> > Author:   pbrook
> > Date:     2008-05-29 14:34:11 +0000 (Thu, 29 May 2008)
> >
> > Log Message:
> > -----------
> > NPTL host detection and futex syscall passthrough.
>
> This patch has no support for NPTL-specific clone flags (CLONE_*TID),
> which was in your NPTL patch. Do you have any plans to add it?

That's deliberate. Implementing clone() is fairly pointless if you don't also 
make qemu threadsafe.
I'll be contributing full thread support shortly.

Paul

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

end of thread, other threads:[~2008-05-30 13:14 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-29 14:34 [Qemu-devel] [4616] NPTL host detection and futex syscall passthrough Paul Brook
2008-05-29 15:00 ` Stuart Anderson
2008-05-29 15:14   ` Paul Brook
2008-05-30  9:39 ` Kirill A. Shutemov
2008-05-30 13:14   ` Paul Brook

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).