From: Stuart Anderson <anderson@netsweng.com>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [4616] NPTL host detection and futex syscall passthrough.
Date: Thu, 29 May 2008 11:00:35 -0400 (EDT) [thread overview]
Message-ID: <Pine.LNX.4.64.0805291056350.4030@trantor.stuart.netsweng.com> (raw)
In-Reply-To: <E1K1jCm-0000Xn-2b@cvs.savannah.gnu.org>
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
next prev parent reply other threads:[~2008-05-29 15:01 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-05-29 14:34 [Qemu-devel] [4616] NPTL host detection and futex syscall passthrough Paul Brook
2008-05-29 15:00 ` Stuart Anderson [this message]
2008-05-29 15:14 ` Paul Brook
2008-05-30 9:39 ` Kirill A. Shutemov
2008-05-30 13:14 ` Paul Brook
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.LNX.4.64.0805291056350.4030@trantor.stuart.netsweng.com \
--to=anderson@netsweng.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).