Merge remote-tracking branch 'riku/linux-user-for-upstream' into staging

# By Andreas Schwab (2) and others
# Via Riku Voipio
* riku/linux-user-for-upstream:
  linux-user: Do not ignore mmap failure from host
  linux-user: improve target_to_host_sock_type conversion
  user-exec.c: Set is_write correctly in the ARM cpu_signal_handler()
  linux-user: Fix sys_utimensat (would not compile on old glibc)
  linux-user: fix signal number range check
  linux-user: add SIOCADDRT/SIOCDELRT support
  linux-user: handle /proc/$$ like /proc/self

Message-id: cover.1373051589.git.riku.voipio@linaro.org
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 8a47767..439c2a9 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -88,8 +88,6 @@
 #endif
 
   IOCTL(SIOCATMARK, 0, TYPE_NULL)
-  IOCTL(SIOCADDRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry)))
-  IOCTL(SIOCDELRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry)))
   IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(TYPE_INT))
   IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
   IOCTL(SIOCSIFFLAGS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
@@ -379,3 +377,7 @@
                 MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
   IOCTL_SPECIAL(DM_DEV_SET_GEOMETRY, IOC_RW, do_ioctl_dm,
                 MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(SIOCADDRT, IOC_W, do_ioctl_rt,
+                MK_PTR(MK_STRUCT(STRUCT_rtentry)))
+  IOCTL_SPECIAL(SIOCDELRT, IOC_W, do_ioctl_rt,
+                MK_PTR(MK_STRUCT(STRUCT_rtentry)))
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index b412e3f..de22197 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -483,6 +483,10 @@
         if (!(flags & MAP_ANONYMOUS)) {
             p = mmap(g2h(start), len, prot,
                      flags | MAP_FIXED, fd, host_offset);
+            if (p == MAP_FAILED) {
+                munmap(g2h(start), host_len);
+                goto fail;
+            }
             host_start += offset - host_offset;
         }
         start = h2g(host_start);
diff --git a/linux-user/signal.c b/linux-user/signal.c
index c4e20dc..d84e189 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -102,14 +102,14 @@
 
 int host_to_target_signal(int sig)
 {
-    if (sig >= _NSIG)
+    if (sig < 0 || sig >= _NSIG)
         return sig;
     return host_to_target_signal_table[sig];
 }
 
 int target_to_host_signal(int sig)
 {
-    if (sig >= _NSIG)
+    if (sig < 0 || sig >= _NSIG)
         return sig;
     return target_to_host_signal_table[sig];
 }
diff --git a/linux-user/socket.h b/linux-user/socket.h
index 339cae5..ae17959 100644
--- a/linux-user/socket.h
+++ b/linux-user/socket.h
@@ -1,91 +1,104 @@
 
 #if defined(TARGET_MIPS)
-	// MIPS special values for constants
+    /* MIPS special values for constants */
 
-	/*
-	 * For setsockopt(2)
-	 *
-	 * This defines are ABI conformant as far as Linux supports these ...
-	 */
-	#define TARGET_SOL_SOCKET      0xffff
+    /*
+     * For setsockopt(2)
+     *
+     * This defines are ABI conformant as far as Linux supports these ...
+     */
+    #define TARGET_SOL_SOCKET      0xffff
 
-	#define TARGET_SO_DEBUG        0x0001  /* Record debugging information.  */
-	#define TARGET_SO_REUSEADDR    0x0004  /* Allow reuse of local addresses.  */
-	#define TARGET_SO_KEEPALIVE    0x0008  /* Keep connections alive and send
-					  SIGPIPE when they die.  */
-	#define TARGET_SO_DONTROUTE    0x0010  /* Don't do local routing.  */
-	#define TARGET_SO_BROADCAST    0x0020  /* Allow transmission of
-					  broadcast messages.  */
-	#define TARGET_SO_LINGER       0x0080  /* Block on close of a reliable
-					  socket to transmit pending data.  */
-	#define TARGET_SO_OOBINLINE 0x0100     /* Receive out-of-band data in-band.  */
-	#if 0
-	To add: #define TARGET_SO_REUSEPORT 0x0200     /* Allow local address and port reuse.  */
-	#endif
+    #define TARGET_SO_DEBUG        0x0001  /* Record debugging information. */
+    #define TARGET_SO_REUSEADDR    0x0004  /* Allow reuse of local addresses. */
+    #define TARGET_SO_KEEPALIVE    0x0008  /* Keep connections alive and send
+                                              SIGPIPE when they die. */
+    #define TARGET_SO_DONTROUTE    0x0010  /* Don't do local routing. */
+    #define TARGET_SO_BROADCAST    0x0020  /* Allow transmission of
+                                              broadcast messages. */
+    #define TARGET_SO_LINGER       0x0080  /* Block on close of a reliable
+                                            * socket to transmit pending data.
+                                            */
+    #define TARGET_SO_OOBINLINE 0x0100     /* Receive out-of-band data in-band.
+                                            */
+    #if 0
+    /* To add: Allow local address and port reuse. */
+    #define TARGET_SO_REUSEPORT 0x0200
+    #endif
 
-	#define TARGET_SO_TYPE         0x1008  /* Compatible name for SO_STYLE.  */
-	#define TARGET_SO_STYLE        SO_TYPE /* Synonym */
-	#define TARGET_SO_ERROR        0x1007  /* get error status and clear */
-	#define TARGET_SO_SNDBUF       0x1001  /* Send buffer size. */
-	#define TARGET_SO_RCVBUF       0x1002  /* Receive buffer. */
-	#define TARGET_SO_SNDLOWAT     0x1003  /* send low-water mark */
-	#define TARGET_SO_RCVLOWAT     0x1004  /* receive low-water mark */
-	#define TARGET_SO_SNDTIMEO     0x1005  /* send timeout */
-	#define TARGET_SO_RCVTIMEO     0x1006  /* receive timeout */
-	#define TARGET_SO_ACCEPTCONN   0x1009
+    #define TARGET_SO_TYPE         0x1008  /* Compatible name for SO_STYLE. */
+    #define TARGET_SO_STYLE        SO_TYPE /* Synonym */
+    #define TARGET_SO_ERROR        0x1007  /* get error status and clear */
+    #define TARGET_SO_SNDBUF       0x1001  /* Send buffer size. */
+    #define TARGET_SO_RCVBUF       0x1002  /* Receive buffer. */
+    #define TARGET_SO_SNDLOWAT     0x1003  /* send low-water mark */
+    #define TARGET_SO_RCVLOWAT     0x1004  /* receive low-water mark */
+    #define TARGET_SO_SNDTIMEO     0x1005  /* send timeout */
+    #define TARGET_SO_RCVTIMEO     0x1006  /* receive timeout */
+    #define TARGET_SO_ACCEPTCONN   0x1009
 
-	/* linux-specific, might as well be the same as on i386 */
-	#define TARGET_SO_NO_CHECK     11
-	#define TARGET_SO_PRIORITY     12
-	#define TARGET_SO_BSDCOMPAT    14
+    /* linux-specific, might as well be the same as on i386 */
+    #define TARGET_SO_NO_CHECK     11
+    #define TARGET_SO_PRIORITY     12
+    #define TARGET_SO_BSDCOMPAT    14
 
-	#define TARGET_SO_PASSCRED     17
-	#define TARGET_SO_PEERCRED     18
+    #define TARGET_SO_PASSCRED     17
+    #define TARGET_SO_PEERCRED     18
 
-	/* Security levels - as per NRL IPv6 - don't actually do anything */
-	#define TARGET_SO_SECURITY_AUTHENTICATION              22
-	#define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT        23
-	#define TARGET_SO_SECURITY_ENCRYPTION_NETWORK          24
+    /* Security levels - as per NRL IPv6 - don't actually do anything */
+    #define TARGET_SO_SECURITY_AUTHENTICATION              22
+    #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT        23
+    #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK          24
 
-	#define TARGET_SO_BINDTODEVICE         25
+    #define TARGET_SO_BINDTODEVICE         25
 
-	/* Socket filtering */
-	#define TARGET_SO_ATTACH_FILTER        26
-	#define TARGET_SO_DETACH_FILTER        27
+    /* Socket filtering */
+    #define TARGET_SO_ATTACH_FILTER        26
+    #define TARGET_SO_DETACH_FILTER        27
 
-	#define TARGET_SO_PEERNAME             28
-	#define TARGET_SO_TIMESTAMP            29
-	#define SCM_TIMESTAMP          SO_TIMESTAMP
+    #define TARGET_SO_PEERNAME             28
+    #define TARGET_SO_TIMESTAMP            29
+    #define SCM_TIMESTAMP          SO_TIMESTAMP
 
-	#define TARGET_SO_PEERSEC              30
-	#define TARGET_SO_SNDBUFFORCE          31
-	#define TARGET_SO_RCVBUFFORCE          33
+    #define TARGET_SO_PEERSEC              30
+    #define TARGET_SO_SNDBUFFORCE          31
+    #define TARGET_SO_RCVBUFFORCE          33
 
-	/** sock_type - Socket types
-	 *
-	 * Please notice that for binary compat reasons MIPS has to
-	 * override the enum sock_type in include/linux/net.h, so
-	 * we define ARCH_HAS_SOCKET_TYPES here.
-	 *
-	 * @SOCK_DGRAM - datagram (conn.less) socket
-	 * @SOCK_STREAM - stream (connection) socket
-	 * @SOCK_RAW - raw socket
-	 * @SOCK_RDM - reliably-delivered message
-	 * @SOCK_SEQPACKET - sequential packet socket
-	 * @SOCK_PACKET - linux specific way of getting packets at the dev level.
-	 *               For writing rarp and other similar things on the user level.
-	 */
-	enum sock_type {
-	       TARGET_SOCK_DGRAM       = 1,
-	       TARGET_SOCK_STREAM      = 2,
-	       TARGET_SOCK_RAW = 3,
-	       TARGET_SOCK_RDM = 4,
-	       TARGET_SOCK_SEQPACKET   = 5,
-	       TARGET_SOCK_DCCP        = 6,
-	       TARGET_SOCK_PACKET      = 10,
-	};
+    /** sock_type - Socket types
+     *
+     * Please notice that for binary compat reasons MIPS has to
+     * override the enum sock_type in include/linux/net.h, so
+     * we define ARCH_HAS_SOCKET_TYPES here.
+     *
+     * @SOCK_DGRAM - datagram (conn.less) socket
+     * @SOCK_STREAM - stream (connection) socket
+     * @SOCK_RAW - raw socket
+     * @SOCK_RDM - reliably-delivered message
+     * @SOCK_SEQPACKET - sequential packet socket
+     * @SOCK_DCCP - Datagram Congestion Control Protocol socket
+     * @SOCK_PACKET - linux specific way of getting packets at the dev level.
+     *                For writing rarp and other similar things on the user
+     *                level.
+     * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag.
+     * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag.
+     */
 
-	#define TARGET_SOCK_MAX (SOCK_PACKET + 1)
+    #define ARCH_HAS_SOCKET_TYPES          1
+
+    enum sock_type {
+           TARGET_SOCK_DGRAM       = 1,
+           TARGET_SOCK_STREAM      = 2,
+           TARGET_SOCK_RAW         = 3,
+           TARGET_SOCK_RDM         = 4,
+           TARGET_SOCK_SEQPACKET   = 5,
+           TARGET_SOCK_DCCP        = 6,
+           TARGET_SOCK_PACKET      = 10,
+           TARGET_SOCK_CLOEXEC     = 02000000,
+           TARGET_SOCK_NONBLOCK    = 0200,
+    };
+
+    #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1)
+    #define TARGET_SOCK_TYPE_MASK    0xf  /* Covers up to TARGET_SOCK_MAX-1. */
 
 #elif defined(TARGET_ALPHA)
 
@@ -156,61 +169,167 @@
     /* Instruct lower device to use last 4-bytes of skb data as FCS */
     #define TARGET_SO_NOFCS     43
 
+    /** sock_type - Socket types
+     *
+     * Please notice that for binary compat reasons ALPHA has to
+     * override the enum sock_type in include/linux/net.h, so
+     * we define ARCH_HAS_SOCKET_TYPES here.
+     *
+     * @SOCK_DGRAM - datagram (conn.less) socket
+     * @SOCK_STREAM - stream (connection) socket
+     * @SOCK_RAW - raw socket
+     * @SOCK_RDM - reliably-delivered message
+     * @SOCK_SEQPACKET - sequential packet socket
+     * @SOCK_DCCP - Datagram Congestion Control Protocol socket
+     * @SOCK_PACKET - linux specific way of getting packets at the dev level.
+     *                For writing rarp and other similar things on the user
+     *                level.
+     * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag.
+     * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag.
+     */
+
+    #define ARCH_HAS_SOCKET_TYPES          1
+
+    enum sock_type {
+           TARGET_SOCK_STREAM      = 1,
+           TARGET_SOCK_DGRAM       = 2,
+           TARGET_SOCK_RAW         = 3,
+           TARGET_SOCK_RDM         = 4,
+           TARGET_SOCK_SEQPACKET   = 5,
+           TARGET_SOCK_DCCP        = 6,
+           TARGET_SOCK_PACKET      = 10,
+           TARGET_SOCK_CLOEXEC     = 010000000,
+           TARGET_SOCK_NONBLOCK    = 010000000000,
+    };
+
+    #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1)
+    #define TARGET_SOCK_TYPE_MASK    0xf  /* Covers up to TARGET_SOCK_MAX-1. */
 #else
 
-	/* For setsockopt(2) */
-	#define TARGET_SOL_SOCKET      1
+#if defined(TARGET_SPARC)
+    /** sock_type - Socket types
+     *
+     * Please notice that for binary compat reasons SPARC has to
+     * override the enum sock_type in include/linux/net.h, so
+     * we define ARCH_HAS_SOCKET_TYPES here.
+     *
+     * @SOCK_DGRAM - datagram (conn.less) socket
+     * @SOCK_STREAM - stream (connection) socket
+     * @SOCK_RAW - raw socket
+     * @SOCK_RDM - reliably-delivered message
+     * @SOCK_SEQPACKET - sequential packet socket
+     * @SOCK_DCCP - Datagram Congestion Control Protocol socket
+     * @SOCK_PACKET - linux specific way of getting packets at the dev level.
+     *                For writing rarp and other similar things on the user
+     *                level.
+     * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag.
+     * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag.
+     */
 
-	#define TARGET_SO_DEBUG        1
-	#define TARGET_SO_REUSEADDR    2
-	#define TARGET_SO_TYPE         3
-	#define TARGET_SO_ERROR        4
-	#define TARGET_SO_DONTROUTE    5
-	#define TARGET_SO_BROADCAST    6
-	#define TARGET_SO_SNDBUF       7
-	#define TARGET_SO_RCVBUF       8
-	#define TARGET_SO_SNDBUFFORCE  32
-	#define TARGET_SO_RCVBUFFORCE  33
-	#define TARGET_SO_KEEPALIVE    9
-	#define TARGET_SO_OOBINLINE    10
-	#define TARGET_SO_NO_CHECK     11
-	#define TARGET_SO_PRIORITY     12
-	#define TARGET_SO_LINGER       13
-	#define TARGET_SO_BSDCOMPAT    14
-	/* To add :#define TARGET_SO_REUSEPORT 15 */
-#if defined(TARGET_PPC)
-	#define TARGET_SO_RCVLOWAT     16
-	#define TARGET_SO_SNDLOWAT     17
-	#define TARGET_SO_RCVTIMEO     18
-	#define TARGET_SO_SNDTIMEO     19
-	#define TARGET_SO_PASSCRED     20
-	#define TARGET_SO_PEERCRED     21
-#else
-	#define TARGET_SO_PASSCRED     16
-	#define TARGET_SO_PEERCRED     17
-	#define TARGET_SO_RCVLOWAT     18
-	#define TARGET_SO_SNDLOWAT     19
-	#define TARGET_SO_RCVTIMEO     20
-	#define TARGET_SO_SNDTIMEO     21
+    #define ARCH_HAS_SOCKET_TYPES          1
+
+    enum sock_type {
+           TARGET_SOCK_STREAM      = 1,
+           TARGET_SOCK_DGRAM       = 2,
+           TARGET_SOCK_RAW         = 3,
+           TARGET_SOCK_RDM         = 4,
+           TARGET_SOCK_SEQPACKET   = 5,
+           TARGET_SOCK_DCCP        = 6,
+           TARGET_SOCK_PACKET      = 10,
+           TARGET_SOCK_CLOEXEC     = 020000000,
+           TARGET_SOCK_NONBLOCK    = 040000,
+    };
+
+    #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1)
+    #define TARGET_SOCK_TYPE_MASK    0xf  /* Covers up to TARGET_SOCK_MAX-1. */
 #endif
 
-	/* Security levels - as per NRL IPv6 - don't actually do anything */
-	#define TARGET_SO_SECURITY_AUTHENTICATION              22
-	#define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT        23
-	#define TARGET_SO_SECURITY_ENCRYPTION_NETWORK          24
+    /* For setsockopt(2) */
+    #define TARGET_SOL_SOCKET      1
 
-	#define TARGET_SO_BINDTODEVICE 25
+    #define TARGET_SO_DEBUG        1
+    #define TARGET_SO_REUSEADDR    2
+    #define TARGET_SO_TYPE         3
+    #define TARGET_SO_ERROR        4
+    #define TARGET_SO_DONTROUTE    5
+    #define TARGET_SO_BROADCAST    6
+    #define TARGET_SO_SNDBUF       7
+    #define TARGET_SO_RCVBUF       8
+    #define TARGET_SO_SNDBUFFORCE  32
+    #define TARGET_SO_RCVBUFFORCE  33
+    #define TARGET_SO_KEEPALIVE    9
+    #define TARGET_SO_OOBINLINE    10
+    #define TARGET_SO_NO_CHECK     11
+    #define TARGET_SO_PRIORITY     12
+    #define TARGET_SO_LINGER       13
+    #define TARGET_SO_BSDCOMPAT    14
+    /* To add :#define TARGET_SO_REUSEPORT 15 */
+#if defined(TARGET_PPC)
+    #define TARGET_SO_RCVLOWAT     16
+    #define TARGET_SO_SNDLOWAT     17
+    #define TARGET_SO_RCVTIMEO     18
+    #define TARGET_SO_SNDTIMEO     19
+    #define TARGET_SO_PASSCRED     20
+    #define TARGET_SO_PEERCRED     21
+#else
+    #define TARGET_SO_PASSCRED     16
+    #define TARGET_SO_PEERCRED     17
+    #define TARGET_SO_RCVLOWAT     18
+    #define TARGET_SO_SNDLOWAT     19
+    #define TARGET_SO_RCVTIMEO     20
+    #define TARGET_SO_SNDTIMEO     21
+#endif
 
-	/* Socket filtering */
-	#define TARGET_SO_ATTACH_FILTER        26
-	#define TARGET_SO_DETACH_FILTER        27
+    /* Security levels - as per NRL IPv6 - don't actually do anything */
+    #define TARGET_SO_SECURITY_AUTHENTICATION              22
+    #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT        23
+    #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK          24
 
-	#define TARGET_SO_PEERNAME             28
-	#define TARGET_SO_TIMESTAMP            29
-	#define TARGET_SCM_TIMESTAMP           TARGET_SO_TIMESTAMP
+    #define TARGET_SO_BINDTODEVICE 25
 
-	#define TARGET_SO_ACCEPTCONN           30
+    /* Socket filtering */
+    #define TARGET_SO_ATTACH_FILTER        26
+    #define TARGET_SO_DETACH_FILTER        27
 
-	#define TARGET_SO_PEERSEC              31
+    #define TARGET_SO_PEERNAME             28
+    #define TARGET_SO_TIMESTAMP            29
+    #define TARGET_SCM_TIMESTAMP           TARGET_SO_TIMESTAMP
+
+    #define TARGET_SO_ACCEPTCONN           30
+
+    #define TARGET_SO_PEERSEC              31
+
+#endif
+
+#ifndef ARCH_HAS_SOCKET_TYPES
+    /** sock_type - Socket types - default values
+     *
+     *
+     * @SOCK_STREAM - stream (connection) socket
+     * @SOCK_DGRAM - datagram (conn.less) socket
+     * @SOCK_RAW - raw socket
+     * @SOCK_RDM - reliably-delivered message
+     * @SOCK_SEQPACKET - sequential packet socket
+     * @SOCK_DCCP - Datagram Congestion Control Protocol socket
+     * @SOCK_PACKET - linux specific way of getting packets at the dev level.
+     *                For writing rarp and other similar things on the user
+     *                level.
+     * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag.
+     * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag.
+     */
+    enum sock_type {
+           TARGET_SOCK_STREAM      = 1,
+           TARGET_SOCK_DGRAM       = 2,
+           TARGET_SOCK_RAW         = 3,
+           TARGET_SOCK_RDM         = 4,
+           TARGET_SOCK_SEQPACKET   = 5,
+           TARGET_SOCK_DCCP        = 6,
+           TARGET_SOCK_PACKET      = 10,
+           TARGET_SOCK_CLOEXEC     = 02000000,
+           TARGET_SOCK_NONBLOCK    = 04000,
+    };
+
+    #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1)
+    #define TARGET_SOCK_TYPE_MASK    0xf  /* Covers up to TARGET_SOCK_MAX-1. */
 
 #endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index cdd0c28..a6a7828 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -105,6 +105,7 @@
 #include <linux/vt.h>
 #include <linux/dm-ioctl.h>
 #include <linux/reboot.h>
+#include <linux/route.h>
 #include "linux_loop.h"
 #include "cpu-uname.h"
 
@@ -338,6 +339,7 @@
 }
 #endif
 
+#ifdef TARGET_NR_utimensat
 #ifdef CONFIG_UTIMENSAT
 static int sys_utimensat(int dirfd, const char *pathname,
     const struct timespec times[2], int flags)
@@ -347,12 +349,19 @@
     else
         return utimensat(dirfd, pathname, times, flags);
 }
-#else
-#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
+#elif defined(__NR_utimensat)
+#define __NR_sys_utimensat __NR_utimensat
 _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
           const struct timespec *,tsp,int,flags)
+#else
+static int sys_utimensat(int dirfd, const char *pathname,
+                         const struct timespec times[2], int flags)
+{
+    errno = ENOSYS;
+    return -1;
+}
 #endif
-#endif /* CONFIG_UTIMENSAT  */
+#endif /* TARGET_NR_utimensat */
 
 #ifdef CONFIG_INOTIFY
 #include <sys/inotify.h>
@@ -1696,31 +1705,36 @@
     free(vec);
 }
 
+static inline void target_to_host_sock_type(int *type)
+{
+    int host_type = 0;
+    int target_type = *type;
+
+    switch (target_type & TARGET_SOCK_TYPE_MASK) {
+    case TARGET_SOCK_DGRAM:
+        host_type = SOCK_DGRAM;
+        break;
+    case TARGET_SOCK_STREAM:
+        host_type = SOCK_STREAM;
+        break;
+    default:
+        host_type = target_type & TARGET_SOCK_TYPE_MASK;
+        break;
+    }
+    if (target_type & TARGET_SOCK_CLOEXEC) {
+        host_type |= SOCK_CLOEXEC;
+    }
+    if (target_type & TARGET_SOCK_NONBLOCK) {
+        host_type |= SOCK_NONBLOCK;
+    }
+    *type = host_type;
+}
+
 /* do_socket() Must return target values and target errnos. */
 static abi_long do_socket(int domain, int type, int protocol)
 {
-#if defined(TARGET_MIPS)
-    switch(type) {
-    case TARGET_SOCK_DGRAM:
-        type = SOCK_DGRAM;
-        break;
-    case TARGET_SOCK_STREAM:
-        type = SOCK_STREAM;
-        break;
-    case TARGET_SOCK_RAW:
-        type = SOCK_RAW;
-        break;
-    case TARGET_SOCK_RDM:
-        type = SOCK_RDM;
-        break;
-    case TARGET_SOCK_SEQPACKET:
-        type = SOCK_SEQPACKET;
-        break;
-    case TARGET_SOCK_PACKET:
-        type = SOCK_PACKET;
-        break;
-    }
-#endif
+    target_to_host_sock_type(&type);
+
     if (domain == PF_NETLINK)
         return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
     return get_errno(socket(domain, type, protocol));
@@ -1953,6 +1967,8 @@
     int tab[2];
     abi_long ret;
 
+    target_to_host_sock_type(&type);
+
     ret = get_errno(socketpair(domain, type, protocol, tab));
     if (!is_error(ret)) {
         if (put_user_s32(tab[0], target_tab_addr)
@@ -3551,6 +3567,69 @@
     return ret;
 }
 
+static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
+                                int fd, abi_long cmd, abi_long arg)
+{
+    const argtype *arg_type = ie->arg_type;
+    const StructEntry *se;
+    const argtype *field_types;
+    const int *dst_offsets, *src_offsets;
+    int target_size;
+    void *argptr;
+    abi_ulong *target_rt_dev_ptr;
+    unsigned long *host_rt_dev_ptr;
+    abi_long ret;
+    int i;
+
+    assert(ie->access == IOC_W);
+    assert(*arg_type == TYPE_PTR);
+    arg_type++;
+    assert(*arg_type == TYPE_STRUCT);
+    target_size = thunk_type_size(arg_type, 0);
+    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+    if (!argptr) {
+        return -TARGET_EFAULT;
+    }
+    arg_type++;
+    assert(*arg_type == (int)STRUCT_rtentry);
+    se = struct_entries + *arg_type++;
+    assert(se->convert[0] == NULL);
+    /* convert struct here to be able to catch rt_dev string */
+    field_types = se->field_types;
+    dst_offsets = se->field_offsets[THUNK_HOST];
+    src_offsets = se->field_offsets[THUNK_TARGET];
+    for (i = 0; i < se->nb_fields; i++) {
+        if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
+            assert(*field_types == TYPE_PTRVOID);
+            target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]);
+            host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
+            if (*target_rt_dev_ptr != 0) {
+                *host_rt_dev_ptr = (unsigned long)lock_user_string(
+                                                  tswapal(*target_rt_dev_ptr));
+                if (!*host_rt_dev_ptr) {
+                    unlock_user(argptr, arg, 0);
+                    return -TARGET_EFAULT;
+                }
+            } else {
+                *host_rt_dev_ptr = 0;
+            }
+            field_types++;
+            continue;
+        }
+        field_types = thunk_convert(buf_temp + dst_offsets[i],
+                                    argptr + src_offsets[i],
+                                    field_types, THUNK_HOST);
+    }
+    unlock_user(argptr, arg, 0);
+
+    ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
+    if (*host_rt_dev_ptr != 0) {
+        unlock_user((void *)*host_rt_dev_ptr,
+                    *target_rt_dev_ptr, 0);
+    }
+    return ret;
+}
+
 static IOCTLEntry ioctl_entries[] = {
 #define IOCTL(cmd, access, ...) \
     { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
@@ -4973,6 +5052,30 @@
     return 0;
 }
 
+static int is_proc_myself(const char *filename, const char *entry)
+{
+    if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
+        filename += strlen("/proc/");
+        if (!strncmp(filename, "self/", strlen("self/"))) {
+            filename += strlen("self/");
+        } else if (*filename >= '1' && *filename <= '9') {
+            char myself[80];
+            snprintf(myself, sizeof(myself), "%d/", getpid());
+            if (!strncmp(filename, myself, strlen(myself))) {
+                filename += strlen(myself);
+            } else {
+                return 0;
+            }
+        } else {
+            return 0;
+        }
+        if (!strcmp(filename, entry)) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
 static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
 {
     struct fake_open {
@@ -4981,15 +5084,14 @@
     };
     const struct fake_open *fake_open;
     static const struct fake_open fakes[] = {
-        { "/proc/self/maps", open_self_maps },
-        { "/proc/self/stat", open_self_stat },
-        { "/proc/self/auxv", open_self_auxv },
+        { "maps", open_self_maps },
+        { "stat", open_self_stat },
+        { "auxv", open_self_auxv },
         { NULL, NULL }
     };
 
     for (fake_open = fakes; fake_open->filename; fake_open++) {
-        if (!strncmp(pathname, fake_open->filename,
-                     strlen(fake_open->filename))) {
+        if (is_proc_myself(pathname, fake_open->filename)) {
             break;
         }
     }
@@ -6262,20 +6364,18 @@
 #endif
     case TARGET_NR_readlink:
         {
-            void *p2, *temp;
+            void *p2;
             p = lock_user_string(arg1);
             p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
-            if (!p || !p2)
+            if (!p || !p2) {
                 ret = -TARGET_EFAULT;
-            else {
-                if (strncmp((const char *)p, "/proc/self/exe", 14) == 0) {
-                    char real[PATH_MAX];
-                    temp = realpath(exec_path,real);
-                    ret = (temp==NULL) ? get_errno(-1) : strlen(real) ;
-                    snprintf((char *)p2, arg3, "%s", real);
-                    }
-                else
-                    ret = get_errno(readlink(path(p), p2, arg3));
+            } else if (is_proc_myself((const char *)p, "exe")) {
+                char real[PATH_MAX], *temp;
+                temp = realpath(exec_path, real);
+                ret = temp == NULL ? get_errno(-1) : strlen(real) ;
+                snprintf((char *)p2, arg3, "%s", real);
+            } else {
+                ret = get_errno(readlink(path(p), p2, arg3));
             }
             unlock_user(p2, arg2, ret);
             unlock_user(p, arg1, 0);
@@ -6287,10 +6387,16 @@
             void *p2;
             p  = lock_user_string(arg2);
             p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
-            if (!p || !p2)
-        	ret = -TARGET_EFAULT;
-            else
+            if (!p || !p2) {
+                ret = -TARGET_EFAULT;
+            } else if (is_proc_myself((const char *)p, "exe")) {
+                char real[PATH_MAX], *temp;
+                temp = realpath(exec_path, real);
+                ret = temp == NULL ? get_errno(-1) : strlen(real) ;
+                snprintf((char *)p2, arg4, "%s", real);
+            } else {
                 ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
+            }
             unlock_user(p2, arg3, ret);
             unlock_user(p, arg2, 0);
         }
@@ -8536,7 +8642,7 @@
         goto unimplemented_nowarn;
 #endif
 
-#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
+#if defined(TARGET_NR_utimensat)
     case TARGET_NR_utimensat:
         {
             struct timespec *tsp, ts[2];
diff --git a/user-exec.c b/user-exec.c
index fa7f1f1..57c8e8d 100644
--- a/user-exec.c
+++ b/user-exec.c
@@ -20,6 +20,7 @@
 #include "cpu.h"
 #include "disas/disas.h"
 #include "tcg.h"
+#include "qemu/bitops.h"
 
 #undef EAX
 #undef ECX
@@ -441,8 +442,11 @@
 #else
     pc = uc->uc_mcontext.arm_pc;
 #endif
-    /* XXX: compute is_write */
-    is_write = 0;
+
+    /* error_code is the FSR value, in which bit 11 is WnR (assuming a v6 or
+     * later processor; on v5 we will always report this as a read).
+     */
+    is_write = extract32(uc->uc_mcontext.error_code, 11, 1);
     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                              is_write,
                              &uc->uc_sigmask, puc);