aboutsummaryrefslogtreecommitdiffstats
path: root/emulators
diff options
context:
space:
mode:
authornox <nox@FreeBSD.org>2013-03-30 01:40:38 +0800
committernox <nox@FreeBSD.org>2013-03-30 01:40:38 +0800
commit7a377f83c9764832ac648f0063090988152e925a (patch)
treed33294058708ce0ec0faa156a7ed184dea6cdc1d /emulators
parentf176aa0a24c735648b01c2a36384ff823beeb040 (diff)
downloadfreebsd-ports-gnome-7a377f83c9764832ac648f0063090988152e925a.tar.gz
freebsd-ports-gnome-7a377f83c9764832ac648f0063090988152e925a.tar.zst
freebsd-ports-gnome-7a377f83c9764832ac648f0063090988152e925a.zip
- Update net/usbredir to 0.6 .
- Update emulators/qemu-devel to 1.4.0 with preliminary bsd-user patches. Thanx to: sson, cognet, and others for much improved bsd-user support - it now runs at least quite a few mips64 and single-threaded arm binaries, see: https://wiki.freebsd.org/QemuUserModeHowTo
Diffstat (limited to 'emulators')
-rw-r--r--emulators/qemu-devel/Makefile47
-rw-r--r--emulators/qemu-devel/distinfo4
-rw-r--r--emulators/qemu-devel/files/Makefile_objs.patch10
-rw-r--r--emulators/qemu-devel/files/gns3-qemu-options.hx.patch11
-rw-r--r--emulators/qemu-devel/files/net_c.patch38
-rw-r--r--emulators/qemu-devel/files/net_h.patch10
-rw-r--r--emulators/qemu-devel/files/net_udp_c.patch141
-rw-r--r--emulators/qemu-devel/files/net_udp_h.patch35
-rw-r--r--emulators/qemu-devel/files/patch-90_security8
-rw-r--r--emulators/qemu-devel/files/patch-Makefile8
-rw-r--r--emulators/qemu-devel/files/patch-bg4
-rw-r--r--emulators/qemu-devel/files/patch-bsd-user-ld8
-rw-r--r--emulators/qemu-devel/files/patch-bsd-user-qemu.h31
-rw-r--r--emulators/qemu-devel/files/patch-e1000-rx133
-rw-r--r--emulators/qemu-devel/files/patch-hw-ppc_newworld.c4
-rw-r--r--emulators/qemu-devel/files/patch-hw-ppc_oldworld.c4
-rw-r--r--emulators/qemu-devel/files/patch-ppc.ld4
-rw-r--r--emulators/qemu-devel/files/patch-tapclose6
-rw-r--r--emulators/qemu-devel/files/patch-z-arm-bsd-user-00112
-rw-r--r--emulators/qemu-devel/files/patch-z2-bsd-user-cognet-sson-0028355
-rw-r--r--emulators/qemu-devel/files/patch-z2b-bsd-user-sson-002b217
-rw-r--r--emulators/qemu-devel/files/patch-z2c-bsd-user-sson-002c2301
-rw-r--r--emulators/qemu-devel/files/patch-z2d-bsd-user-sson-002d30
-rw-r--r--emulators/qemu-devel/files/patch-z2e-bsd-user-sson-002e3316
-rw-r--r--emulators/qemu-devel/files/patch-z3-bsd-user-8fix61
-rw-r--r--emulators/qemu-devel/files/patch-z3b-bsd-user-8fix34
-rw-r--r--emulators/qemu-devel/files/patch-z3c-bsd-user-8fix12
-rw-r--r--emulators/qemu-devel/files/patch-z3d-bsd-user-8fix47
-rw-r--r--emulators/qemu-devel/files/patch-z4-bsd-user-elfload26
-rw-r--r--emulators/qemu-devel/files/patch-z6-bsd-user-usrstack118
-rw-r--r--emulators/qemu-devel/files/patch-z7-bsd-user-tls1-cognet171
-rw-r--r--emulators/qemu-devel/files/patch-z7b-bsd-user-tls213
-rw-r--r--emulators/qemu-devel/files/patch-z8-bsd-user-unref11
-rw-r--r--emulators/qemu-devel/files/patch-z9-bsd-user-sson003a40
-rw-r--r--emulators/qemu-devel/files/patch-z9b-bsd-user-sson003b332
-rw-r--r--emulators/qemu-devel/files/patch-z9c-bsd-user-sson003c2425
-rw-r--r--emulators/qemu-devel/files/patch-z9d-bsd-user-sson003d92
-rw-r--r--emulators/qemu-devel/files/patch-z9e-bsd-user-cognet-elfload15
-rw-r--r--emulators/qemu-devel/files/patch-z9f-bsd-user-sson003f321
-rw-r--r--emulators/qemu-devel/files/patch-za-bsd-user-8fix28
-rw-r--r--emulators/qemu-devel/files/patch-zb-bsd-user-sson004a1151
-rw-r--r--emulators/qemu-devel/files/pcap-patch226
-rw-r--r--emulators/qemu-devel/pkg-plist15
43 files changed, 19245 insertions, 530 deletions
diff --git a/emulators/qemu-devel/Makefile b/emulators/qemu-devel/Makefile
index c847df93adc9..54d1db15f4f8 100644
--- a/emulators/qemu-devel/Makefile
+++ b/emulators/qemu-devel/Makefile
@@ -2,8 +2,7 @@
# $FreeBSD$
PORTNAME= qemu
-PORTVERSION= 1.1.1
-PORTREVISION= 2
+PORTVERSION= 1.4.0
CATEGORIES= emulators
MASTER_SITES= http://wiki.qemu.org/download/:release \
LOCAL/nox:snapshot
@@ -14,8 +13,10 @@ DIST_SUBDIR= qemu/${PORTVERSION}
MAINTAINER= nox@FreeBSD.org
COMMENT= QEMU CPU Emulator - development version
+LIB_DEPENDS= pixman-1:${PORTSDIR}/x11/pixman
+
HAS_CONFIGURE= yes
-EXTRACT_SUFX= .tar.bz2
+USE_BZIP2= yes
USE_GMAKE= yes
USE_PERL5_BUILD= yes
USE_PYTHON_BUILD= yes
@@ -29,7 +30,8 @@ CONFLICTS_INSTALL= qemu-[0-9]*
MAKE_JOBS_SAFE= yes
OPTIONS_DEFINE= SAMBA SDL OPENGL GNUTLS SASL JPEG PNG CURL CDROM_DMA PCAP \
- USBREDIR GNS3 ADD_AUDIO CLANG_HACK X86_TARGETS BSD_USER
+ USBREDIR GNS3 ADD_AUDIO CLANG_HACK X86_TARGETS BSD_USER \
+ STATIC_LINK
SAMBA_DESC= samba dependency (for -smb)
GNUTLS_DESC= gnutls dependency (vnc encryption)
SASL_DESC= cyrus-sasl dependency (vnc encryption)
@@ -40,11 +42,12 @@ CDROM_DMA_DESC= IDE CDROM DMA
PCAP_DESC= pcap dependency (networking with bpf)
SEABIOS_GIT_DESC= add seabios snapshot (-bios bios.bin-1.6.3.1)
USBREDIR_DESC= usb device network redirection (experimental!)
-GNS3_DESC= gns3 patches (udp, promiscuous multicast)
+GNS3_DESC= gns3 patches (promiscuous multicast)
ADD_AUDIO_DESC= Emulate more audio hardware (experimental!)
CLANG_HACK_DESC= clang workaround (result slow and less stable!)
X86_TARGETS_DESC= Don't build non-x86 system targets
BSD_USER_DESC= Also build bsd-user targets (for testing)
+STATIC_LINK_DESC= Statically link the executables
OPTIONS_DEFAULT=SDL OPENGL GNUTLS SASL JPEG PNG CURL CDROM_DMA PCAP
.include <bsd.port.options.mk>
@@ -64,13 +67,22 @@ USE_GCC= any
.if ${PORT_OPTIONS:MX86_TARGETS}
.if ${PORT_OPTIONS:MBSD_USER}
-CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,i386-bsd-user,x86_64-bsd-user,sparc-bsd-user,sparc64-bsd-user,arm-bsd-user
+.if ${ARCH} != "amd64"
+CONFIGURE_ARGS+= --enable-nptl --target-list=i386-softmmu,x86_64-softmmu,i386-bsd-user,sparc-bsd-user,arm-bsd-user,armeb-bsd-user,mips-bsd-user,mipsel-bsd-user
+.else
+CONFIGURE_ARGS+= --enable-nptl --target-list=i386-softmmu,x86_64-softmmu,i386-bsd-user,x86_64-bsd-user,sparc-bsd-user,sparc64-bsd-user,arm-bsd-user,armeb-bsd-user,mips-bsd-user,mipsel-bsd-user,mips64-bsd-user
+.endif
.else
CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu
.endif
.else
.if empty(PORT_OPTIONS:MBSD_USER)
CONFIGURE_ARGS+= --disable-bsd-user
+.else
+CONFIGURE_ARGS+= --enable-nptl
+.if ${ARCH} != "amd64"
+CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,alpha-softmmu,arm-softmmu,cris-softmmu,lm32-softmmu,m68k-softmmu,microblaze-softmmu,microblazeel-softmmu,mips-softmmu,mipsel-softmmu,mips64-softmmu,mips64el-softmmu,or32-softmmu,ppc-softmmu,ppcemb-softmmu,ppc64-softmmu,sh4-softmmu,sh4eb-softmmu,sparc-softmmu,sparc64-softmmu,s390x-softmmu,xtensa-softmmu,xtensaeb-softmmu,unicore32-softmmu,i386-bsd-user,sparc-bsd-user,arm-bsd-user,armeb-bsd-user,mips-bsd-user,mipsel-bsd-user
+.endif
.endif
.endif
@@ -82,6 +94,11 @@ PLIST_SUB+= BSD_USER=""
IGNORE= bsd-user targets not tested on sparc64
.endif
.endif
+.if empty(PORT_OPTIONS:MBSD_USER) || ${ARCH} != "amd64"
+PLIST_SUB+= BSD_USER64="@comment "
+.else
+PLIST_SUB+= BSD_USER64=""
+.endif
.if ${PORT_OPTIONS:MX86_TARGETS}
PLIST_SUB+= NONX86="@comment "
@@ -90,13 +107,7 @@ PLIST_SUB+= NONX86=""
.endif
.if ${PORT_OPTIONS:MGNS3}
-EXTRA_PATCHES+= ${FILESDIR}/hw_e1000_c.patch \
- ${FILESDIR}/net_c.patch \
- ${FILESDIR}/net_h.patch \
- ${FILESDIR}/net_udp_c.patch \
- ${FILESDIR}/net_udp_h.patch \
- ${FILESDIR}/Makefile_objs.patch \
- ${FILESDIR}/gns3-qemu-options.hx.patch
+EXTRA_PATCHES+= ${FILESDIR}/hw_e1000_c.patch
.endif
WITHOUT_CPU_CFLAGS=yes #to avoid problems with register allocation
@@ -105,6 +116,8 @@ CONFIGURE_ARGS+= --prefix=${PREFIX} --cc=${CC} --enable-docs \
--disable-linux-user --disable-linux-aio \
--disable-kvm --disable-xen \
--smbd=${LOCALBASE}/sbin/smbd \
+ --enable-debug \
+ --enable-debug-info \
--extra-cflags=-I${WRKSRC}\ -I${LOCALBASE}/include\ -DPREFIX=\\\"${PREFIX}\\\"
.if empty(PORT_OPTIONS:MSDL)
@@ -160,6 +173,10 @@ RUN_DEPENDS+= usbredir>=0.4.3:${PORTSDIR}/net/usbredir
CONFIGURE_ARGS+= --enable-pcap
.endif
+.if ${PORT_OPTIONS:MSTATIC_LINK}
+CONFIGURE_ARGS+= --static
+.endif
+
.if ${PORT_OPTIONS:MADD_AUDIO}
CONFIGURE_ARGS+= --audio-card-list=ac97,es1370,sb16,cs4231a,adlib,gus,hda
.endif
@@ -201,9 +218,11 @@ MAKE_ENV+= COMPILER_PATH=${LOCALBASE}/bin
.endif
post-patch:
+.if ${OSVERSION} < 900000
+ @${REINPLACE_CMD} -e '/LIBS/s|-lprocstat||' ${WRKSRC}/configure
+.endif
.if ${PORT_OPTIONS:MPCAP}
@cd ${WRKSRC} && ${PATCH} --quiet < ${FILESDIR}/pcap-patch
- @${REINPLACE_CMD} -f ${FILESDIR}/pcap-client-type.sed ${WRKSRC}/net.h
.endif
.if empty(PORT_OPTIONS:MCDROM_DMA)
@cd ${WRKSRC} && ${PATCH} --quiet < ${FILESDIR}/cdrom-dma-patch
diff --git a/emulators/qemu-devel/distinfo b/emulators/qemu-devel/distinfo
index 7034277098b6..fd3c024c2812 100644
--- a/emulators/qemu-devel/distinfo
+++ b/emulators/qemu-devel/distinfo
@@ -1,2 +1,2 @@
-SHA256 (qemu/1.1.1/qemu-1.1.1.tar.bz2) = 004a3032b504e70174c504d6c156b1ec3445abd9913602af0d7a5ac0703ddf5c
-SIZE (qemu/1.1.1/qemu-1.1.1.tar.bz2) = 11712524
+SHA256 (qemu/1.4.0/qemu-1.4.0.tar.bz2) = 066297ed77408fb7588889c271a85cf3c259ad55c939315988e6062d7708eda8
+SIZE (qemu/1.4.0/qemu-1.4.0.tar.bz2) = 10419510
diff --git a/emulators/qemu-devel/files/Makefile_objs.patch b/emulators/qemu-devel/files/Makefile_objs.patch
deleted file mode 100644
index 5f8c04b5ed8d..000000000000
--- a/emulators/qemu-devel/files/Makefile_objs.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- qemu-0.14.1/Makefile.objs.orig Thu Jun 23 17:44:50 2011
-+++ qemu-0.14.1/Makefile.objs Thu Jun 23 17:45:01 2011
-@@ -34,6 +34,7 @@
- net-nested-y = queue.o checksum.o util.o
- net-nested-y += socket.o
- net-nested-y += dump.o
-+net-nested-y += udp.o
- net-nested-$(CONFIG_POSIX) += tap.o
- net-nested-$(CONFIG_LINUX) += tap-linux.o
- net-nested-$(CONFIG_WIN32) += tap-win32.o
diff --git a/emulators/qemu-devel/files/gns3-qemu-options.hx.patch b/emulators/qemu-devel/files/gns3-qemu-options.hx.patch
deleted file mode 100644
index da8bf2903aa4..000000000000
--- a/emulators/qemu-devel/files/gns3-qemu-options.hx.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/qemu-options.hx
-+++ b/qemu-options.hx
-@@ -1050,6 +1050,8 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
- " connect the user mode network stack to VLAN 'n', configure its\n"
- " DHCP server and enabled optional services\n"
- #endif
-+ "-net udp[,vlan=n],sport=sport,dport=dport,daddr=host\n"
-+ " connect the vlan 'n' to a udp host (for dynamips/pemu/GNS3)\n"
- #ifdef _WIN32
- "-net tap[,vlan=n][,name=str],ifname=name\n"
- " connect the host TAP network interface to VLAN 'n'\n"
diff --git a/emulators/qemu-devel/files/net_c.patch b/emulators/qemu-devel/files/net_c.patch
deleted file mode 100644
index 8672fd4df561..000000000000
--- a/emulators/qemu-devel/files/net_c.patch
+++ /dev/null
@@ -1,38 +0,0 @@
---- qemu-0.15.0/net.c.orig
-+++ qemu-0.15.0/net.c
-@@ -30,6 +30,7 @@
- #include "net/dump.h"
- #include "net/slirp.h"
- #include "net/vde.h"
-+#include "net/udp.h"
- #include "net/util.h"
- #include "monitor.h"
- #include "qemu-common.h"
-@@ -1029,6 +1030,27 @@ static const struct {
- },
- },
- #endif
-+ [NET_CLIENT_TYPE_UDP] = {
-+ .type = "udp",
-+ .init = net_init_udp,
-+ .desc = {
-+ NET_COMMON_PARAMS_DESC,
-+ {
-+ .name = "sport",
-+ .type = QEMU_OPT_NUMBER,
-+ .help = "source port number",
-+ }, {
-+ .name = "daddr",
-+ .type = QEMU_OPT_STRING,
-+ .help = "destination IP address",
-+ }, {
-+ .name = "dport",
-+ .type = QEMU_OPT_NUMBER,
-+ .help = "destination port number",
-+ },
-+ { /* end of list */ }
-+ },
-+ },
- [NET_CLIENT_TYPE_DUMP] = {
- .type = "dump",
- .init = net_init_dump,
diff --git a/emulators/qemu-devel/files/net_h.patch b/emulators/qemu-devel/files/net_h.patch
deleted file mode 100644
index 1af162c568ff..000000000000
--- a/emulators/qemu-devel/files/net_h.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- qemu-0.15.0/net.h.orig
-+++ qemu-0.15.0/net.h
-@@ -35,6 +35,7 @@ typedef enum {
- NET_CLIENT_TYPE_TAP,
- NET_CLIENT_TYPE_SOCKET,
- NET_CLIENT_TYPE_VDE,
-+ NET_CLIENT_TYPE_UDP,
- NET_CLIENT_TYPE_DUMP,
-
- NET_CLIENT_TYPE_MAX
diff --git a/emulators/qemu-devel/files/net_udp_c.patch b/emulators/qemu-devel/files/net_udp_c.patch
deleted file mode 100644
index 9fb9b084b772..000000000000
--- a/emulators/qemu-devel/files/net_udp_c.patch
+++ /dev/null
@@ -1,141 +0,0 @@
---- qemu-0.14.1/net/udp.c.orig Thu Jun 23 17:09:02 2011
-+++ qemu-0.14.1/net/udp.c Thu Jun 23 17:10:17 2011
-@@ -0,0 +1,138 @@
-+/*
-+ * QEMU System Emulator
-+ *
-+ * Copyright (c) 2003-2008 Fabrice Bellard
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this software and associated documentation files (the "Software"), to deal
-+ * in the Software without restriction, including without limitation the rights
-+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-+ * copies of the Software, and to permit persons to whom the Software is
-+ * furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-+ * THE SOFTWARE.
-+ */
-+#include "net/udp.h"
-+
-+#include "config-host.h"
-+
-+#ifndef _WIN32
-+#include <arpa/inet.h>
-+#include <netinet/in.h>
-+#include <netinet/udp.h>
-+#endif
-+
-+#include "net.h"
-+#include "qemu-char.h"
-+#include "qemu-common.h"
-+#include "qemu-option.h"
-+#include "qemu_socket.h"
-+#include "sysemu.h"
-+
-+
-+typedef struct UDPState {
-+ VLANClientState nc;
-+ int rfd;
-+ struct sockaddr_in sender;
-+} UDPState;
-+
-+static void udp_to_qemu(void *opaque)
-+{
-+ UDPState *s = opaque;
-+ uint8_t buf[4096];
-+ int size;
-+
-+ size = recvfrom(s->rfd, (char *)buf, sizeof(buf), 0, NULL, NULL);
-+ if (size > 0) {
-+ qemu_send_packet(&s->nc, buf, size);
-+ }
-+}
-+
-+static ssize_t udp_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
-+{
-+ UDPState *s = DO_UPCAST(UDPState, nc, nc);
-+ int ret;
-+
-+ do {
-+ ret = sendto(s->rfd, (const char *)buf, size, 0, (struct sockaddr *)&s->sender, sizeof (s->sender));
-+ } while (ret < 0 && errno == EINTR);
-+
-+ return ret;
-+}
-+
-+static void udp_cleanup(VLANClientState *nc)
-+{
-+ UDPState *s = DO_UPCAST(UDPState, nc, nc);
-+ qemu_set_fd_handler(s->rfd, NULL, NULL, NULL);
-+ close(s->rfd);
-+}
-+
-+static NetClientInfo net_udp_info = {
-+ .type = NET_CLIENT_TYPE_UDP,
-+ .size = sizeof(UDPState),
-+ .receive = udp_receive,
-+ .cleanup = udp_cleanup,
-+};
-+
-+static int net_udp_init(VLANState *vlan, const char *model,
-+ const char *name, int sport,
-+ const char *daddr, int dport)
-+{
-+ VLANClientState *nc;
-+ UDPState *s;
-+ struct sockaddr_in receiver;
-+ int ret;
-+
-+ nc = qemu_new_net_client(&net_udp_info, vlan, NULL, model, name);
-+
-+ snprintf(nc->info_str, sizeof(nc->info_str),"udp: %i->%s:%i",
-+ sport, daddr, dport);
-+
-+ s = DO_UPCAST(UDPState, nc, nc);
-+
-+ s->rfd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
-+ receiver.sin_family = AF_INET;
-+ receiver.sin_addr.s_addr = INADDR_ANY;
-+ receiver.sin_port = htons(sport);
-+ ret = bind(s->rfd, (struct sockaddr *)&receiver, sizeof(receiver));
-+
-+ if (ret == -1) {
-+ fprintf (stderr, "bind error:%s\n", strerror(errno));
-+ return ret;
-+ }
-+
-+ memset((char*)&s->sender, 0,sizeof(s->sender));
-+ s->sender.sin_family = AF_INET;
-+ s->sender.sin_port = htons(dport);
-+ inet_aton(daddr, &s->sender.sin_addr);
-+
-+ qemu_set_fd_handler(s->rfd, udp_to_qemu, NULL, s);
-+
-+ return 0;
-+}
-+
-+int net_init_udp(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
-+{
-+ const char *daddr;
-+ int sport, dport;
-+
-+ daddr = qemu_opt_get(opts, "daddr");
-+
-+ sport = qemu_opt_get_number(opts, "sport", 0);
-+ dport = qemu_opt_get_number(opts, "dport", 0);
-+
-+ if (net_udp_init(vlan, "udp", name, sport, daddr, dport) == -1) {
-+ return -1;
-+ }
-+
-+ return 0;
-+}
diff --git a/emulators/qemu-devel/files/net_udp_h.patch b/emulators/qemu-devel/files/net_udp_h.patch
deleted file mode 100644
index a6f9d7f75c37..000000000000
--- a/emulators/qemu-devel/files/net_udp_h.patch
+++ /dev/null
@@ -1,35 +0,0 @@
---- qemu-0.14.1/net/udp.h.orig Thu Jun 23 17:12:45 2011
-+++ qemu-0.14.1/net/udp.h Thu Jun 23 17:12:28 2011
-@@ -0,0 +1,32 @@
-+/*
-+ * QEMU System Emulator
-+ *
-+ * Copyright (c) 2003-2008 Fabrice Bellard
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this software and associated documentation files (the "Software"), to deal
-+ * in the Software without restriction, including without limitation the rights
-+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-+ * copies of the Software, and to permit persons to whom the Software is
-+ * furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-+ * THE SOFTWARE.
-+ */
-+#ifndef QEMU_NET_UDP_H
-+#define QEMU_NET_UDP_H
-+
-+#include "qemu-common.h"
-+#include "qemu-option.h"
-+
-+int net_init_udp(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan);
-+
-+#endif /* QEMU_NET_UDP_H */
diff --git a/emulators/qemu-devel/files/patch-90_security b/emulators/qemu-devel/files/patch-90_security
index 12eb0301f4cd..6ce41640d374 100644
--- a/emulators/qemu-devel/files/patch-90_security
+++ b/emulators/qemu-devel/files/patch-90_security
@@ -15,7 +15,7 @@ Index: qemu/hw/dma.c
}
Index: qemu/hw/fdc.c
-@@ -1322,7 +1322,8 @@
+@@ -1445,7 +1445,8 @@ static uint32_t fdctrl_read_data(FDCtrl
fd_sector(cur_drv));
return 0;
}
@@ -25,16 +25,16 @@ Index: qemu/hw/fdc.c
FLOPPY_DPRINTF("error getting sector %d\n",
fd_sector(cur_drv));
/* Sure, image size is too small... */
-@@ -1776,7 +1777,8 @@
+@@ -1905,7 +1906,8 @@ static void fdctrl_write_data(FDCtrl *fd
if (pos == FD_SECTOR_LEN - 1 ||
fdctrl->data_pos == fdctrl->data_len) {
cur_drv = get_cur_drv(fdctrl);
- if (bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
+ if (cur_drv->bs == NULL ||
+ bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
- FLOPPY_ERROR("writing sector %d\n", fd_sector(cur_drv));
+ FLOPPY_DPRINTF("error writing sector %d\n",
+ fd_sector(cur_drv));
return;
- }
Index: qemu-0.8.2/hw/sb16.c
===================================================================
--- qemu-0.8.2.orig/hw/sb16.c 2006-07-22 20:23:34.000000000 +0300
diff --git a/emulators/qemu-devel/files/patch-Makefile b/emulators/qemu-devel/files/patch-Makefile
index 364bde5ba834..87a365001ffc 100644
--- a/emulators/qemu-devel/files/patch-Makefile
+++ b/emulators/qemu-devel/files/patch-Makefile
@@ -1,5 +1,5 @@
Index: qemu/Makefile
-@@ -40,7 +40,11 @@ LIBS+=-lz $(LIBS_TOOLS)
+@@ -53,7 +53,11 @@ LIBS+=-lz $(LIBS_TOOLS)
HELPERS-$(CONFIG_LINUX) = qemu-bridge-helper$(EXESUF)
ifdef BUILD_DOCS
@@ -11,7 +11,7 @@ Index: qemu/Makefile
ifdef CONFIG_VIRTFS
DOCS+=fsdev/virtfs-proxy-helper.1
endif
-@@ -270,8 +274,10 @@ endif
+@@ -311,8 +315,10 @@ endif
install-doc: $(DOCS)
$(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)"
@@ -22,7 +22,7 @@ Index: qemu/Makefile
ifdef CONFIG_POSIX
$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
$(INSTALL_DATA) qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1"
-@@ -290,7 +296,10 @@ install-confdir:
+@@ -331,7 +337,10 @@ install-confdir:
$(INSTALL_DIR) "$(DESTDIR)$(qemu_confdir)"
install-sysconfig: install-datadir install-confdir
@@ -31,6 +31,6 @@ Index: qemu/Makefile
+ if [ ! -f "$(qemu_confdir)/target-x86_64.conf" ]; then \
+ $(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/target-x86_64.conf "$(qemu_confdir)"; \
+ fi
- $(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/cpus-x86_64.conf "$(DESTDIR)$(qemu_datadir)"
install: all $(if $(BUILD_DOCS),install-doc) install-sysconfig install-datadir
+ $(INSTALL_DIR) "$(DESTDIR)$(bindir)"
diff --git a/emulators/qemu-devel/files/patch-bg b/emulators/qemu-devel/files/patch-bg
index b96153595ce5..719e8baf1210 100644
--- a/emulators/qemu-devel/files/patch-bg
+++ b/emulators/qemu-devel/files/patch-bg
@@ -1,4 +1,4 @@
-Index: qemu/net.h
+Index: qemu/include/net/net.h
@@ -174,8 +174,8 @@ void net_host_device_remove(Monitor *mon
int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
@@ -10,7 +10,7 @@ Index: qemu/net.h
#define DEFAULT_BRIDGE_HELPER CONFIG_QEMU_HELPERDIR "/qemu-bridge-helper"
#define DEFAULT_BRIDGE_INTERFACE "br0"
-Index: qemu/net/tap.h
+Index: qemu/net/tap_int.h
@@ -29,8 +29,8 @@
#include "qemu-common.h"
#include "qemu-option.h"
diff --git a/emulators/qemu-devel/files/patch-bsd-user-ld b/emulators/qemu-devel/files/patch-bsd-user-ld
index 33c9ad11e384..fcc577c00063 100644
--- a/emulators/qemu-devel/files/patch-bsd-user-ld
+++ b/emulators/qemu-devel/files/patch-bsd-user-ld
@@ -1,5 +1,5 @@
---- a/x86_64.ld
-+++ b/x86_64.ld
+--- a/ldscripts/x86_64.ld
++++ b/ldscripts/x86_64.ld
@@ -1,54 +1,58 @@
-/* Default linker script, for normal executables */
-OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
@@ -256,8 +256,8 @@
+ .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+ /DISCARD/ : { *(.note.GNU-stack) }
}
---- a/i386.ld
-+++ b/i386.ld
+--- a/ldscripts/i386.ld
++++ b/ldscripts/i386.ld
@@ -1,45 +1,47 @@
-/* ld script to make i386 Linux kernel
- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
diff --git a/emulators/qemu-devel/files/patch-bsd-user-qemu.h b/emulators/qemu-devel/files/patch-bsd-user-qemu.h
new file mode 100644
index 000000000000..6ea43c7ca49b
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-bsd-user-qemu.h
@@ -0,0 +1,31 @@
+--- a/bsd-user/qemu.h
++++ b/bsd-user/qemu.h
+@@ -50,6 +50,10 @@ struct image_info {
+ abi_ulong entry;
+ abi_ulong code_offset;
+ abi_ulong data_offset;
++#if 1
++ abi_ulong arg_start;
++ abi_ulong arg_end;
++#endif
+ int personality;
+ };
+
+@@ -72,6 +76,17 @@ struct emulated_sigtable {
+ typedef struct TaskState {
+ struct TaskState *next;
+ int used; /* non zero if used */
++#if 1
++#ifdef TARGET_ARM
++ int swi_errno;
++#endif
++#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
++ /* Extra fields for semihosted binaries. */
++ uint32_t heap_base;
++ uint32_t heap_limit;
++#endif
++ uint32_t stack_base;
++#endif
+ struct image_info *info;
+
+ struct emulated_sigtable sigtab[TARGET_NSIG];
diff --git a/emulators/qemu-devel/files/patch-e1000-rx b/emulators/qemu-devel/files/patch-e1000-rx
deleted file mode 100644
index c24490138414..000000000000
--- a/emulators/qemu-devel/files/patch-e1000-rx
+++ /dev/null
@@ -1,133 +0,0 @@
-Message-ID: <4FC741F1.4000905@redhat.com>
-Date: Thu, 31 May 2012 12:03:29 +0200
-From: Paolo Bonzini <pbonzini@redhat.com>
-To: Jan Kiszka <jan.kiszka@web.de>
-References: <20120530202311.GA1768@onelab2.iet.unipi.it>
- <20120530212333.GD2672@onelab2.iet.unipi.it>
- <4FC69389.8050404@web.de>
- <CA+hQ2+g-2FdgWnqZUh1-oTZkziq8CTNJ5SeA+aCW32FFF=zi4A@mail.gmail.com>
- <4FC69B28.1000106@web.de>
- <CA+hQ2+gA5hZ2Zk-kwPNDVcguBsu2UfNiLxs84MgqBUK_MQuC4g@mail.gmail.com>
- <4FC71FEB.9030100@redhat.com> <4FC72A95.4040808@web.de>
-In-Reply-To: <4FC72A95.4040808@web.de>
-Cc: Luigi Rizzo <rizzo.unipi@gmail.com>, rizzo@iet.unipi.it,
- qemu-devel@nongnu.org,
- Stefano Stabellini <Stefano.Stabellini@eu.citrix.com>
-Subject: Re: [Qemu-devel] Proposed patch: huge RX speedup for hw/e1000.c
-
-Il 31/05/2012 10:23, Jan Kiszka ha scritto:
->> > @@ -922,6 +923,7 @@ set_rdt(E1000State *s, int index, uint32_t val)
->> > {
->> > s->check_rxov = 0;
->> > s->mac_reg[index] = val & 0xffff;
->> > + qemu_notify_event();
-> This still looks like the wrong tool: Packets that can't be delivered
-> are queued.
-
-Packets that are read from the tap but can't be delivered are queued;
-packets that are left on the tap need qemu_notify_event to be flushed.
-
-> So we need to flush the queue and clear the blocked delivery
-> there. qemu_flush_queued_packets appears more appropriate for this.
-
-Right, and qemu_flush_queued_packets needs to call qemu_notify_event
-which makes the call in virtio-net unnecessary.
-
-Paolo
-
-diff --git a/hw/e1000.c b/hw/e1000.c
-index 4573f13..43d933a 100644
---- a/hw/e1000.c
-+++ b/hw/e1000.c
-@@ -295,6 +295,7 @@ set_rx_control(E1000State *s, int index, uint32_t val)
- s->rxbuf_min_shift = ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1;
- DBGOUT(RX, "RCTL: %d, mac_reg[RCTL] = 0x%x\n", s->mac_reg[RDT],
- s->mac_reg[RCTL]);
-+ qemu_flush_queued_packets(&s->nic->nc);
- }
-
- static void
-@@ -926,6 +927,9 @@ set_rdt(E1000State *s, int index, uint32_t val)
- {
- s->check_rxov = 0;
- s->mac_reg[index] = val & 0xffff;
-+ if (e1000_has_rxbufs(s, 1)) {
-+ qemu_flush_queued_packets(&s->nic->nc);
-+ }
- }
-
- static void
-diff --git a/hw/virtio-net.c b/hw/virtio-net.c
-index 3f190d4..0974945 100644
---- a/hw/virtio-net.c
-+++ b/hw/virtio-net.c
-@@ -447,10 +447,6 @@ static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)
- VirtIONet *n = to_virtio_net(vdev);
-
- qemu_flush_queued_packets(&n->nic->nc);
--
-- /* We now have RX buffers, signal to the IO thread to break out of the
-- * select to re-poll the tap file descriptor */
-- qemu_notify_event();
- }
-
- static int virtio_net_can_receive(VLANClientState *nc)
-diff --git a/net.c b/net.c
-index 1922d8a..fa846ae 100644
---- a/net.c
-+++ b/net.c
-@@ -491,7 +491,12 @@ void qemu_flush_queued_packets(VLANClientState *vc)
- queue = vc->send_queue;
- }
-
-- qemu_net_queue_flush(queue);
-+ if (qemu_net_queue_flush(queue)) {
-+ /* We emptied the queue successfully, signal to the IO thread to repoll
-+ * the file descriptor (for tap, for example).
-+ */
-+ qemu_notify_event();
-+ }
- }
-
- static ssize_t qemu_send_packet_async_with_flags(VLANClientState *sender,
-diff --git a/net/queue.c b/net/queue.c
-index 1ab5247..fd1c7e6 100644
---- a/net/queue.c
-+++ b/net/queue.c
-@@ -232,7 +232,7 @@ void qemu_net_queue_purge(NetQueue *queue, VLANClientState *from)
- }
- }
-
--void qemu_net_queue_flush(NetQueue *queue)
-+bool qemu_net_queue_flush(NetQueue *queue)
- {
- while (!QTAILQ_EMPTY(&queue->packets)) {
- NetPacket *packet;
-@@ -248,7 +248,7 @@ void qemu_net_queue_flush(NetQueue *queue)
- packet->size);
- if (ret == 0) {
- QTAILQ_INSERT_HEAD(&queue->packets, packet, entry);
-- break;
-+ return 0;
- }
-
- if (packet->sent_cb) {
-@@ -257,4 +257,5 @@ void qemu_net_queue_flush(NetQueue *queue)
-
- g_free(packet);
- }
-+ return 1;
- }
-diff --git a/net/queue.h b/net/queue.h
-index a31958e..4bf6d3c 100644
---- a/net/queue.h
-+++ b/net/queue.h
-@@ -66,6 +66,6 @@ ssize_t qemu_net_queue_send_iov(NetQueue *queue,
- NetPacketSent *sent_cb);
-
- void qemu_net_queue_purge(NetQueue *queue, VLANClientState *from);
--void qemu_net_queue_flush(NetQueue *queue);
-+bool qemu_net_queue_flush(NetQueue *queue);
-
- #endif /* QEMU_NET_QUEUE_H */
-
diff --git a/emulators/qemu-devel/files/patch-hw-ppc_newworld.c b/emulators/qemu-devel/files/patch-hw-ppc_newworld.c
index 4e14d5621263..e409d639aecf 100644
--- a/emulators/qemu-devel/files/patch-hw-ppc_newworld.c
+++ b/emulators/qemu-devel/files/patch-hw-ppc_newworld.c
@@ -1,5 +1,5 @@
---- a/hw/ppc_newworld.c
-+++ b/hw/ppc_newworld.c
+--- a/hw/ppc/mac_newworld.c
++++ b/hw/ppc/mac_newworld.c
@@ -68,6 +68,11 @@
#include "hw/usb.h"
#include "blockdev.h"
diff --git a/emulators/qemu-devel/files/patch-hw-ppc_oldworld.c b/emulators/qemu-devel/files/patch-hw-ppc_oldworld.c
index 46fc2ae7e77e..57612edd053e 100644
--- a/emulators/qemu-devel/files/patch-hw-ppc_oldworld.c
+++ b/emulators/qemu-devel/files/patch-hw-ppc_oldworld.c
@@ -1,5 +1,5 @@
---- a/hw/ppc_oldworld.c
-+++ b/hw/ppc_oldworld.c
+--- a/hw/ppc/mac_oldworld.c
++++ b/hw/ppc/mac_oldworld.c
@@ -47,6 +47,11 @@
#define MAX_IDE_BUS 2
#define CFG_ADDR 0xf0000510
diff --git a/emulators/qemu-devel/files/patch-ppc.ld b/emulators/qemu-devel/files/patch-ppc.ld
index 87b5234bfba5..bcd45b4657e9 100644
--- a/emulators/qemu-devel/files/patch-ppc.ld
+++ b/emulators/qemu-devel/files/patch-ppc.ld
@@ -1,5 +1,5 @@
---- a/ppc.ld
-+++ b/ppc.ld
+--- a/ldscripts/ppc.ld
++++ b/ldscripts/ppc.ld
@@ -99,7 +99,7 @@ SECTIONS
PROVIDE (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
diff --git a/emulators/qemu-devel/files/patch-tapclose b/emulators/qemu-devel/files/patch-tapclose
index a5b8dfb0bf3f..d4a27c268197 100644
--- a/emulators/qemu-devel/files/patch-tapclose
+++ b/emulators/qemu-devel/files/patch-tapclose
@@ -1,13 +1,13 @@
Index: qemu/net/tap.c
-@@ -287,12 +287,13 @@ static void tap_cleanup(VLANClientState
+@@ -286,12 +286,13 @@ static void tap_cleanup(NetClientState *
qemu_purge_queued_packets(nc);
- if (s->down_script[0])
- launch_script(s->down_script, s->down_script_arg, s->fd);
-
- tap_read_poll(s, 0);
- tap_write_poll(s, 0);
+ tap_read_poll(s, false);
+ tap_write_poll(s, false);
close(s->fd);
+
+ if (s->down_script[0])
diff --git a/emulators/qemu-devel/files/patch-z-arm-bsd-user-001 b/emulators/qemu-devel/files/patch-z-arm-bsd-user-001
index 4c3a0e06e504..a7fb6ab72b38 100644
--- a/emulators/qemu-devel/files/patch-z-arm-bsd-user-001
+++ b/emulators/qemu-devel/files/patch-z-arm-bsd-user-001
@@ -289,6 +289,18 @@
#endif
--- a/bsd-user/syscall.c.orig
+++ b/bsd-user/syscall.c
+@@ -96,6 +96,11 @@ static abi_long do_obreak(abi_ulong new_
+ return 0;
+ }
+
++abi_long do_brk(abi_ulong new_brk)
++{
++ return do_obreak(new_brk);
++}
++
+ #if defined(TARGET_I386)
+ static abi_long do_freebsd_sysarch(CPUX86State *env, int op, abi_ulong parms)
+ {
@@ -157,6 +161,12 @@ static abi_long do_freebsd_sysarch(void
}
#endif
diff --git a/emulators/qemu-devel/files/patch-z2-bsd-user-cognet-sson-002 b/emulators/qemu-devel/files/patch-z2-bsd-user-cognet-sson-002
new file mode 100644
index 000000000000..de8875875a0e
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z2-bsd-user-cognet-sson-002
@@ -0,0 +1,8355 @@
+#diff --git a/Makefile b/Makefile
+#index 5fa0f1d..55e151e 100644
+#--- a/Makefile
+#+++ b/Makefile
+#@@ -65,7 +65,8 @@ CLANG_CFLAGS_AS+= -no-integrated-as
+#
+# .if ${PORT_OPTIONS:MX86_TARGETS}
+# .if ${PORT_OPTIONS:MBSD_USER}
+#-CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,i386-bsd-user,x86_64-bsd-user,sparc-bsd-user,sparc64-bsd-user,arm-bsd-user
+#+#CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,i386-bsd-user,x86_64-bsd-user,sparc-bsd-user,sparc64-bsd-user,arm-bsd-user,armeb-bsd-user,mips-bsd-user,mipsel-bsd-user
+#+CONFIGURE_ARGS+= --target-list=arm-bsd-user,armeb-bsd-user,mips-bsd-user,mipsel-bsd-user,mips64-bsd-user
+# .else
+# CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu
+# .endif
+#@@ -106,6 +107,8 @@ CONFIGURE_ARGS+= --prefix=${PREFIX} --cc=${CC} --enable-docs \
+# --disable-linux-user --disable-linux-aio \
+# --disable-kvm --disable-xen \
+# --smbd=${LOCALBASE}/sbin/smbd \
+#+ --enable-debug \
+#+ --enable-debug-info \
+# --extra-cflags=-I${WRKSRC}\ -I${LOCALBASE}/include\ -DPREFIX=\\\"${PREFIX}\\\"
+#
+# .if empty(PORT_OPTIONS:MSDL)
+diff --git a/bsd-user/arm/target_signal.h b/bsd-user/arm/target_signal.h
+index 1b644cc..19cc188 100644
+--- a/bsd-user/arm/target_signal.h
++++ b/bsd-user/arm/target_signal.h
+@@ -3,17 +3,12 @@
+
+ #include "cpu.h"
+
+-/* this struct defines a stack used during syscall handling */
+-
+-typedef struct target_sigaltstack {
+- abi_ulong ss_sp;
+- abi_long ss_flags;
+- abi_ulong ss_size;
+-} target_stack_t;
+-
+ static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
+ {
+ return state->regs[13];
+ }
+
++#define TARGET_MINSIGSTKSZ (1024 * 4)
++#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/arm/target_vmparam.h b/bsd-user/arm/target_vmparam.h
+new file mode 100644
+index 0000000..0427244
+--- /dev/null
++++ b/bsd-user/arm/target_vmparam.h
+@@ -0,0 +1,28 @@
++#ifndef _TARGET_VMPARAM_H_
++#define _TARGET_VMPARAM_H_
++
++#if defined(__FreeBSD__)
++ /* KERNBASE - 512 MB */
++#define TARGET_VM_MAXUSER_ADDRESS (0xc0000000 - (512 * 1024 * 1024))
++#define TARGET_USRSTACK TARGET_VM_MAXUSER_ADDRESS
++
++struct target_ps_strings {
++ abi_ulong ps_argvstr;
++ uint32_t ps_nargvstr;
++ abi_ulong ps_envstr;
++ uint32_t ps_nenvstr;
++};
++
++#define TARGET_SPACE_USRSPACE 4096
++#define TARGET_ARG_MAX 262144
++
++#define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
++
++#define TARGET_SZSIGCODE 0
++
++#else
++
++#define TARGET_USRSTACK 0
++#endif
++
++#endif /* _TARGET_VMPARAM_H_ */
+diff --git a/bsd-user/bsdload.c b/bsd-user/bsdload.c
+index 2abc713..dcf6f66 100644
+--- a/bsd-user/bsdload.c
++++ b/bsd-user/bsdload.c
+@@ -53,7 +53,7 @@ static int count(char ** vec)
+ return(i);
+ }
+
+-static int prepare_binprm(struct linux_binprm *bprm)
++static int prepare_binprm(struct bsd_binprm *bprm)
+ {
+ struct stat st;
+ int mode;
+@@ -155,33 +155,33 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
+ }
+
+ int loader_exec(const char * filename, char ** argv, char ** envp,
+- struct target_pt_regs * regs, struct image_info *infop)
++ struct target_pt_regs * regs, struct image_info *infop,
++ struct bsd_binprm *bprm)
+ {
+- struct linux_binprm bprm;
+ int retval;
+ int i;
+
+- bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
++ bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES /*-sizeof(unsigned int) XXX */;
+ for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
+- bprm.page[i] = NULL;
++ bprm->page[i] = NULL;
+ retval = open(filename, O_RDONLY);
+ if (retval < 0)
+ return retval;
+- bprm.fd = retval;
+- bprm.filename = (char *)filename;
+- bprm.argc = count(argv);
+- bprm.argv = argv;
+- bprm.envc = count(envp);
+- bprm.envp = envp;
++ bprm->fd = retval;
++ bprm->filename = (char *)filename;
++ bprm->argc = count(argv);
++ bprm->argv = argv;
++ bprm->envc = count(envp);
++ bprm->envp = envp;
+
+- retval = prepare_binprm(&bprm);
++ retval = prepare_binprm(bprm);
+
+ if(retval>=0) {
+- if (bprm.buf[0] == 0x7f
+- && bprm.buf[1] == 'E'
+- && bprm.buf[2] == 'L'
+- && bprm.buf[3] == 'F') {
+- retval = load_elf_binary(&bprm,regs,infop);
++ if (bprm->buf[0] == 0x7f
++ && bprm->buf[1] == 'E'
++ && bprm->buf[2] == 'L'
++ && bprm->buf[3] == 'F') {
++ retval = load_elf_binary(bprm,regs,infop);
+ } else {
+ fprintf(stderr, "Unknown binary format\n");
+ return -1;
+@@ -196,7 +196,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
+
+ /* Something went wrong, return the inode and free the argument pages*/
+ for (i=0 ; i<MAX_ARG_PAGES ; i++) {
+- g_free(bprm.page[i]);
++ g_free(bprm->page[i]);
+ }
+ return(retval);
+ }
+diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
+index 993dcf7..15cf3a6 100644
+--- a/bsd-user/elfload.c
++++ b/bsd-user/elfload.c
+@@ -9,6 +9,8 @@
+ #include <stdlib.h>
+ #include <string.h>
+
++#include <sys/param.h>
++
+ #include "qemu.h"
+ #include "disas.h"
+
+@@ -93,6 +95,7 @@ enum {
+
+ #ifdef TARGET_I386
+
++#ifndef __FreeBSD__
+ #define ELF_PLATFORM get_elf_platform()
+
+ static const char *get_elf_platform(void)
+@@ -112,6 +115,7 @@ static uint32_t get_elf_hwcap(void)
+ {
+ return thread_env->cpuid_features;
+ }
++#endif /* ! __FreeBSD__ */
+
+ #ifdef TARGET_X86_64
+ #define ELF_START_MMAP 0x2aaaaab000ULL
+@@ -378,13 +382,14 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info *
+
+ #ifdef TARGET_MIPS
+
+-#define ELF_START_MMAP 0x80000000
+
+ #define elf_check_arch(x) ( (x) == EM_MIPS )
+
+-#ifdef TARGET_MIPS64
++#if defined(TARGET_MIPS64)
++#define ELF_START_MMAP 0x2aaaaab000ULL
+ #define ELF_CLASS ELFCLASS64
+ #else
++#define ELF_START_MMAP 0x80000000
+ #define ELF_CLASS ELFCLASS32
+ #endif
+ #ifdef TARGET_WORDS_BIGENDIAN
+@@ -396,9 +401,10 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info *
+
+ static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+ {
++
+ regs->cp0_status = 2 << CP0St_KSU;
+- regs->cp0_epc = infop->entry;
+- regs->regs[29] = infop->start_stack;
++ regs->regs[25] = regs->cp0_epc = infop->entry; /* t9 = pc = entry */
++ regs->regs[4] = regs->regs[29] = infop->start_stack; /* a0 = sp = start_stack */
+ }
+
+ #define USE_ELF_CORE_DUMP
+@@ -576,30 +582,38 @@ static void bswap_ehdr(struct elfhdr *ehdr)
+ bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
+ }
+
+-static void bswap_phdr(struct elf_phdr *phdr)
++static void bswap_phdr(struct elf_phdr *phdr, int phnum)
+ {
+- bswap32s(&phdr->p_type); /* Segment type */
+- bswaptls(&phdr->p_offset); /* Segment file offset */
+- bswaptls(&phdr->p_vaddr); /* Segment virtual address */
+- bswaptls(&phdr->p_paddr); /* Segment physical address */
+- bswaptls(&phdr->p_filesz); /* Segment size in file */
+- bswaptls(&phdr->p_memsz); /* Segment size in memory */
+- bswap32s(&phdr->p_flags); /* Segment flags */
+- bswaptls(&phdr->p_align); /* Segment alignment */
++ int i;
++
++ for (i = 0; i < phnum; ++i, ++phdr) {
++ bswap32s(&phdr->p_type); /* Segment type */
++ bswap32s(&phdr->p_flags); /* Segment flags */
++ bswaptls(&phdr->p_offset); /* Segment file offset */
++ bswaptls(&phdr->p_vaddr); /* Segment virtual address */
++ bswaptls(&phdr->p_paddr); /* Segment physical address */
++ bswaptls(&phdr->p_filesz); /* Segment size in file */
++ bswaptls(&phdr->p_memsz); /* Segment size in memory */
++ bswaptls(&phdr->p_align); /* Segment alignment */
++ }
+ }
+
+-static void bswap_shdr(struct elf_shdr *shdr)
++static void bswap_shdr(struct elf_shdr *shdr, int shnum)
+ {
+- bswap32s(&shdr->sh_name);
+- bswap32s(&shdr->sh_type);
+- bswaptls(&shdr->sh_flags);
+- bswaptls(&shdr->sh_addr);
+- bswaptls(&shdr->sh_offset);
+- bswaptls(&shdr->sh_size);
+- bswap32s(&shdr->sh_link);
+- bswap32s(&shdr->sh_info);
+- bswaptls(&shdr->sh_addralign);
+- bswaptls(&shdr->sh_entsize);
++ int i;
++
++ for (i = 0; i < shnum; ++i, ++shdr) {
++ bswap32s(&shdr->sh_name);
++ bswap32s(&shdr->sh_type);
++ bswaptls(&shdr->sh_flags);
++ bswaptls(&shdr->sh_addr);
++ bswaptls(&shdr->sh_offset);
++ bswaptls(&shdr->sh_size);
++ bswap32s(&shdr->sh_link);
++ bswap32s(&shdr->sh_info);
++ bswaptls(&shdr->sh_addralign);
++ bswaptls(&shdr->sh_entsize);
++ }
+ }
+
+ static void bswap_sym(struct elf_sym *sym)
+@@ -609,7 +623,14 @@ static void bswap_sym(struct elf_sym *sym)
+ bswaptls(&sym->st_size);
+ bswap16s(&sym->st_shndx);
+ }
+-#endif
++
++#else /* ! BSWAP_NEEDED */
++
++static inline void bswap_ehdr(struct elfhdr *ehdr) { }
++static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
++static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
++static inline void bswap_sym(struct elf_sym *sym) { }
++#endif /* ! BSWAP_NEEDED */
+
+ /*
+ * 'copy_elf_strings()' copies argument/envelope strings from user
+@@ -666,7 +687,26 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
+ return p;
+ }
+
+-static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
++#if defined(TARGET_MIPS64)
++static inline int
++install_sigtramp(abi_ulong offset, unsigned sigf_uc, unsigned syscall)
++{
++ int i;
++ uint32_t sigtramp_code[] = {
++ 0x67A40000 + sigf_uc, /* daddu $a0, $sp, (sigf_uc) */
++ 0x24020000 + syscall, /* li $v0, (syscall) */
++ 0x0000000C, /* syscall */
++ 0x0000000D /* break */
++ };
++
++ for(i = 0; i < 4; i++)
++ tswap32s(&sigtramp_code[i]);
++
++ return (memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE));
++}
++#endif
++
++static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
+ struct image_info *info)
+ {
+ abi_ulong stack_base, size, error;
+@@ -678,7 +718,13 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
+ size = x86_stack_size;
+ if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
+ size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
+- error = target_mmap(0,
++
++#ifdef TARGET_USRSTACK
++ stack_base = TARGET_USRSTACK - size;
++#else
++ stack_base = (abi_ulong)0;
++#endif
++ error = target_mmap(stack_base,
+ size + qemu_host_page_size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON,
+@@ -690,6 +736,113 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
+ /* we reserve one extra page at the top of the stack as guard */
+ target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
+
++#if defined(__FreeBSD__)
++ /*
++ * The inital FreeBSD stack looks like follows:
++ * (see kern/kern_exec.c exec_copyout_strings() )
++ *
++ * Hi Address -> char **ps_argvstr (struct ps_strings for ps, w, etc.)
++ * unsigned ps_nargvstr
++ * char **ps_envstr
++ * PS_STRINGS -> unsigned ps_nenvstr
++ *
++ * machine dependent sigcode (sv_sigcode of size
++ * sv_szsigcode)
++ *
++ * execpath (absolute image path for rtld)
++ *
++ * SSP Canary (sizeof(long) * 8)
++ *
++ * page sizes array (usually sizeof(u_long) )
++ *
++ * "destp" -> argv, env strings (up to 262144 bytes)
++ */
++
++ {
++ abi_ulong stack_hi_addr;
++ size_t execpath_len;
++ abi_ulong destp;
++ struct target_ps_strings ps_strs;
++ char canary[sizeof(abi_long) * 8];
++ char execpath[PATH_MAX];
++
++ stack_hi_addr = p = error + size;
++
++ /* Save some space for ps_strings. */
++ p -= sizeof(struct target_ps_strings);
++
++#if TARGET_SZSIGCODE > 0
++ /* Add machine depedent sigcode. */
++ p -= TARGET_SZSIGCODE;
++ /* XXX - check return value of memcpy_to_target() for failure */
++ install_sigtramp( p, (unsigned)offsetof(struct target_sigframe,
++ sf_uc), TARGET_FREEBSD_NR_sigreturn);
++#endif
++
++ /* Add execpath for rtld. */
++ if (strlen(bprm->filename)) {
++ /* XXX - check return value of realpath() */
++ realpath(bprm->filename, execpath);
++ execpath_len = strlen(execpath) + 1;
++ } else
++ execpath_len = 0;
++
++ if (execpath_len) {
++ p -= roundup(execpath_len, sizeof(abi_ulong));
++ /* XXX - check return value of memcpy_to_target() */
++ memcpy_to_target(p, execpath, execpath_len);
++ }
++
++ /* Add canary for SSP. */
++ arc4random_buf(canary, sizeof(canary));
++ p -= roundup(sizeof(canary), sizeof(abi_ulong));
++ /* XXX - check return value of memcpy_to_target(). */
++ memcpy_to_target(p, canary, sizeof(canary));
++
++ /* Add page sizes array. */
++ p -= sizeof(abi_ulong);
++ /* XXX - check return value of put_user_ual(). */
++ put_user_ual(TARGET_PAGE_SIZE, p);
++
++ p = destp = p - TARGET_SPACE_USRSPACE - TARGET_ARG_MAX;
++
++ /* XXX should check strlen(argv and envp strings) < TARGET_ARG_MAX */
++
++ /*
++ * Add argv strings. Note that the argv[] vectors are added by
++ * loader_build_argptr()
++ */
++ i = bprm->argc;
++ while (i-- > 0) {
++ size_t len = strlen(bprm->argv[i]) + 1;
++ /* XXX - check return value of memcpy_to_target(). */
++ memcpy_to_target(destp, bprm->argv[i], len);
++ destp += len;
++ }
++ ps_strs.ps_argvstr = tswapl(destp);
++ ps_strs.ps_nargvstr = tswap32(bprm->argc);
++
++ /*
++ * Add env strings. Note that the envp[] vectors are added by
++ * loader_build_argptr().
++ */
++ i = bprm->envc;
++ while(i-- > 0) {
++ size_t len = strlen(bprm->envp[i]) + 1;
++ /* XXX - check return value of memcpy_to_target(). */
++ memcpy_to_target(destp, bprm->envp[i], len);
++ destp += len;
++ }
++ ps_strs.ps_envstr = tswapl(destp);
++ ps_strs.ps_nenvstr = tswap32(bprm->envc);
++
++ /* XXX - check return value of memcpy_to_target(). */
++ memcpy_to_target(stack_hi_addr - sizeof(ps_strs), &ps_strs,
++ sizeof(ps_strs));
++ }
++
++#else
++
+ stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
+ p += stack_base;
+
+@@ -702,6 +855,8 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
+ }
+ stack_base += TARGET_PAGE_SIZE;
+ }
++#endif
++
+ return p;
+ }
+
+@@ -769,11 +924,14 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
+ {
+ abi_ulong sp;
+ int size;
++#ifndef __FreeBSD__
+ abi_ulong u_platform;
+ const char *k_platform;
++#endif
+ const int n = sizeof(elf_addr_t);
+
+ sp = p;
++#ifndef __FreeBSD__
+ u_platform = 0;
+ k_platform = ELF_PLATFORM;
+ if (k_platform) {
+@@ -783,22 +941,28 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
+ /* FIXME - check return value of memcpy_to_target() for failure */
+ memcpy_to_target(sp, k_platform, len);
+ }
++#endif /* ! __FreeBSD__ */
+ /*
+ * Force 16 byte _final_ alignment here for generality.
+ */
+ sp = sp &~ (abi_ulong)15;
++#ifdef __FreeBSD__
++ size = 0;
++#else
+ size = (DLINFO_ITEMS + 1) * 2;
+ if (k_platform)
+ size += 2;
+ #ifdef DLINFO_ARCH_ITEMS
+ size += DLINFO_ARCH_ITEMS * 2;
+ #endif
++#endif /* ! __FreeBSD__ */
+ size += envc + argc + 2;
+ size += (!ibcs ? 3 : 1); /* argc itself */
+ size *= n;
+ if (size & 15)
+ sp -= 16 - (size & 15);
+
++#ifndef __FreeBSD__
+ /* This is correct because Linux defines
+ * elf_addr_t as Elf32_Off / Elf64_Off
+ */
+@@ -833,6 +997,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
+ ARCH_DLINFO;
+ #endif
+ #undef NEW_AUX_ENT
++#endif /* ! __FreeBSD__ */
+
+ sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
+ return sp;
+@@ -856,9 +1021,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
+ last_bss = 0;
+ error = 0;
+
+-#ifdef BSWAP_NEEDED
+ bswap_ehdr(interp_elf_ex);
+-#endif
+ /* First of all, some simple consistency checks */
+ if ((interp_elf_ex->e_type != ET_EXEC &&
+ interp_elf_ex->e_type != ET_DYN) ||
+@@ -899,12 +1062,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
+ free (elf_phdata);
+ return retval;
+ }
+-#ifdef BSWAP_NEEDED
+- eppnt = elf_phdata;
+- for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
+- bswap_phdr(eppnt);
+- }
+-#endif
++ bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
+
+ if (interp_elf_ex->e_type == ET_DYN) {
+ /* in order to avoid hardcoding the interpreter load
+@@ -1049,9 +1207,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
+ for (i = 0; i < hdr->e_shnum; i++) {
+ if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
+ return;
+-#ifdef BSWAP_NEEDED
+- bswap_shdr(&sechdr);
+-#endif
++ bswap_shdr(&sechdr, 1);
+ if (sechdr.sh_type == SHT_SYMTAB) {
+ symtab = sechdr;
+ lseek(fd, hdr->e_shoff
+@@ -1059,9 +1215,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
+ if (read(fd, &strtab, sizeof(strtab))
+ != sizeof(strtab))
+ return;
+-#ifdef BSWAP_NEEDED
+- bswap_shdr(&strtab);
+-#endif
++ bswap_shdr(&strtab, 1);
+ goto found;
+ }
+ }
+@@ -1094,9 +1248,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
+
+ i = 0;
+ while (i < nsyms) {
+-#ifdef BSWAP_NEEDED
+ bswap_sym(syms + i);
+-#endif
+ // Throw away entries which we do not need.
+ if (syms[i].st_shndx == SHN_UNDEF ||
+ syms[i].st_shndx >= SHN_LORESERVE ||
+@@ -1148,7 +1300,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
+ syminfos = s;
+ }
+
+-int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
++int load_elf_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs,
+ struct image_info * info)
+ {
+ struct elfhdr elf_ex;
+@@ -1178,9 +1330,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+ load_addr = 0;
+ load_bias = 0;
+ elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
+-#ifdef BSWAP_NEEDED
+ bswap_ehdr(&elf_ex);
+-#endif
+
+ /* First of all, some simple consistency checks */
+ if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
+@@ -1188,12 +1338,14 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+ return -ENOEXEC;
+ }
+
++#ifndef __FreeBSD__
+ bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
+ bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
+ bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
+ if (!bprm->p) {
+ retval = -E2BIG;
+ }
++#endif /* ! __FreeBSD__ */
+
+ /* Now read in all of the header information */
+ elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
+@@ -1214,12 +1366,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+ return -errno;
+ }
+
+-#ifdef BSWAP_NEEDED
+- elf_ppnt = elf_phdata;
+- for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
+- bswap_phdr(elf_ppnt);
+- }
+-#endif
++ bswap_phdr(elf_phdata, elf_ex.e_phnum);
+ elf_ppnt = elf_phdata;
+
+ elf_bss = 0;
+@@ -1229,9 +1376,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+ elf_stack = ~((abi_ulong)0UL);
+ elf_interpreter = NULL;
+ start_code = ~((abi_ulong)0UL);
+- end_code = 0;
+- start_data = 0;
+- end_data = 0;
++ end_code = (abi_ulong)0UL;
++ start_data = (abi_ulong)0UL;
++ end_data = (abi_ulong)0UL;
+ interp_ex.a_info = 0;
+
+ for(i=0;i < elf_ex.e_phnum; i++) {
+@@ -1431,7 +1578,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+ perror("mmap");
+ exit(-1);
+ }
+- load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
++ load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
+ }
+
+ error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
+@@ -1541,12 +1688,13 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+ padzero(elf_bss, elf_brk);
+
+ #if 0
+- printf("(start_brk) %x\n" , info->start_brk);
+- printf("(end_code) %x\n" , info->end_code);
+- printf("(start_code) %x\n" , info->start_code);
+- printf("(end_data) %x\n" , info->end_data);
+- printf("(start_stack) %x\n" , info->start_stack);
+- printf("(brk) %x\n" , info->brk);
++ printf("(start_brk) 0x" TARGET_FMT_lx "\n" , info->start_brk);
++ printf("(end_code) 0x" TARGET_FMT_lx "\n" , info->end_code);
++ printf("(start_code) 0x" TARGET_FMT_lx "\n" , info->start_code);
++ printf("(start_data) 0x" TARGET_FMT_lx "\n" , info->start_data);
++ printf("(end_data) 0x" TARGET_FMT_lx "\n" , info->end_data);
++ printf("(start_stack) 0x" TARGET_FMT_lx "\n" , info->start_stack);
++ printf("(brk) 0x" TARGET_FMT_lx "\n" , info->brk);
+ #endif
+
+ if ( info->personality == PER_SVR4 )
+@@ -1561,6 +1709,11 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+
+ info->entry = elf_entry;
+
++#ifdef USE_ELF_CORE_DUMP
++ /* bprm->core_dump = &elf_core_dump; */
++ bprm->core_dump = NULL;
++#endif
++
+ return 0;
+ }
+
+diff --git a/bsd-user/freebsd/syscall_nr.h b/bsd-user/freebsd/syscall_nr.h
+index 36336ab..e46571f 100644
+--- a/bsd-user/freebsd/syscall_nr.h
++++ b/bsd-user/freebsd/syscall_nr.h
+@@ -1,373 +1,448 @@
+ /*
+ * System call numbers.
+ *
+- * $FreeBSD$
+- * created from FreeBSD: head/sys/kern/syscalls.master 182123 2008-08-24 21:20:35Z rwatson
++ * created from FreeBSD: releng/9.1/sys/kern/syscalls.master 229723 2012-01-06 19:29:16Z jhb
+ */
+
+-#define TARGET_FREEBSD_NR_syscall 0
+-#define TARGET_FREEBSD_NR_exit 1
+-#define TARGET_FREEBSD_NR_fork 2
+-#define TARGET_FREEBSD_NR_read 3
+-#define TARGET_FREEBSD_NR_write 4
+-#define TARGET_FREEBSD_NR_open 5
+-#define TARGET_FREEBSD_NR_close 6
+-#define TARGET_FREEBSD_NR_wait4 7
+-#define TARGET_FREEBSD_NR_link 9
+-#define TARGET_FREEBSD_NR_unlink 10
+-#define TARGET_FREEBSD_NR_chdir 12
+-#define TARGET_FREEBSD_NR_fchdir 13
+-#define TARGET_FREEBSD_NR_mknod 14
+-#define TARGET_FREEBSD_NR_chmod 15
+-#define TARGET_FREEBSD_NR_chown 16
+-#define TARGET_FREEBSD_NR_break 17
+-#define TARGET_FREEBSD_NR_freebsd4_getfsstat 18
+-#define TARGET_FREEBSD_NR_getpid 20
+-#define TARGET_FREEBSD_NR_mount 21
+-#define TARGET_FREEBSD_NR_unmount 22
+-#define TARGET_FREEBSD_NR_setuid 23
+-#define TARGET_FREEBSD_NR_getuid 24
+-#define TARGET_FREEBSD_NR_geteuid 25
+-#define TARGET_FREEBSD_NR_ptrace 26
+-#define TARGET_FREEBSD_NR_recvmsg 27
+-#define TARGET_FREEBSD_NR_sendmsg 28
+-#define TARGET_FREEBSD_NR_recvfrom 29
+-#define TARGET_FREEBSD_NR_accept 30
+-#define TARGET_FREEBSD_NR_getpeername 31
+-#define TARGET_FREEBSD_NR_getsockname 32
+-#define TARGET_FREEBSD_NR_access 33
+-#define TARGET_FREEBSD_NR_chflags 34
+-#define TARGET_FREEBSD_NR_fchflags 35
+-#define TARGET_FREEBSD_NR_sync 36
+-#define TARGET_FREEBSD_NR_kill 37
+-#define TARGET_FREEBSD_NR_getppid 39
+-#define TARGET_FREEBSD_NR_dup 41
+-#define TARGET_FREEBSD_NR_pipe 42
+-#define TARGET_FREEBSD_NR_getegid 43
+-#define TARGET_FREEBSD_NR_profil 44
+-#define TARGET_FREEBSD_NR_ktrace 45
+-#define TARGET_FREEBSD_NR_getgid 47
+-#define TARGET_FREEBSD_NR_getlogin 49
+-#define TARGET_FREEBSD_NR_setlogin 50
+-#define TARGET_FREEBSD_NR_acct 51
+-#define TARGET_FREEBSD_NR_sigaltstack 53
+-#define TARGET_FREEBSD_NR_ioctl 54
+-#define TARGET_FREEBSD_NR_reboot 55
+-#define TARGET_FREEBSD_NR_revoke 56
+-#define TARGET_FREEBSD_NR_symlink 57
+-#define TARGET_FREEBSD_NR_readlink 58
+-#define TARGET_FREEBSD_NR_execve 59
+-#define TARGET_FREEBSD_NR_umask 60
+-#define TARGET_FREEBSD_NR_chroot 61
+-#define TARGET_FREEBSD_NR_msync 65
+-#define TARGET_FREEBSD_NR_vfork 66
+-#define TARGET_FREEBSD_NR_sbrk 69
+-#define TARGET_FREEBSD_NR_sstk 70
+-#define TARGET_FREEBSD_NR_vadvise 72
+-#define TARGET_FREEBSD_NR_munmap 73
+-#define TARGET_FREEBSD_NR_mprotect 74
+-#define TARGET_FREEBSD_NR_madvise 75
+-#define TARGET_FREEBSD_NR_mincore 78
+-#define TARGET_FREEBSD_NR_getgroups 79
+-#define TARGET_FREEBSD_NR_setgroups 80
+-#define TARGET_FREEBSD_NR_getpgrp 81
+-#define TARGET_FREEBSD_NR_setpgid 82
+-#define TARGET_FREEBSD_NR_setitimer 83
+-#define TARGET_FREEBSD_NR_swapon 85
+-#define TARGET_FREEBSD_NR_getitimer 86
+-#define TARGET_FREEBSD_NR_getdtablesize 89
+-#define TARGET_FREEBSD_NR_dup2 90
+-#define TARGET_FREEBSD_NR_fcntl 92
+-#define TARGET_FREEBSD_NR_select 93
+-#define TARGET_FREEBSD_NR_fsync 95
+-#define TARGET_FREEBSD_NR_setpriority 96
+-#define TARGET_FREEBSD_NR_socket 97
+-#define TARGET_FREEBSD_NR_connect 98
+-#define TARGET_FREEBSD_NR_getpriority 100
+-#define TARGET_FREEBSD_NR_bind 104
+-#define TARGET_FREEBSD_NR_setsockopt 105
+-#define TARGET_FREEBSD_NR_listen 106
+-#define TARGET_FREEBSD_NR_gettimeofday 116
+-#define TARGET_FREEBSD_NR_getrusage 117
+-#define TARGET_FREEBSD_NR_getsockopt 118
+-#define TARGET_FREEBSD_NR_readv 120
+-#define TARGET_FREEBSD_NR_writev 121
+-#define TARGET_FREEBSD_NR_settimeofday 122
+-#define TARGET_FREEBSD_NR_fchown 123
+-#define TARGET_FREEBSD_NR_fchmod 124
+-#define TARGET_FREEBSD_NR_setreuid 126
+-#define TARGET_FREEBSD_NR_setregid 127
+-#define TARGET_FREEBSD_NR_rename 128
+-#define TARGET_FREEBSD_NR_flock 131
+-#define TARGET_FREEBSD_NR_mkfifo 132
+-#define TARGET_FREEBSD_NR_sendto 133
+-#define TARGET_FREEBSD_NR_shutdown 134
+-#define TARGET_FREEBSD_NR_socketpair 135
+-#define TARGET_FREEBSD_NR_mkdir 136
+-#define TARGET_FREEBSD_NR_rmdir 137
+-#define TARGET_FREEBSD_NR_utimes 138
+-#define TARGET_FREEBSD_NR_adjtime 140
+-#define TARGET_FREEBSD_NR_setsid 147
+-#define TARGET_FREEBSD_NR_quotactl 148
+-#define TARGET_FREEBSD_NR_nlm_syscall 154
+-#define TARGET_FREEBSD_NR_nfssvc 155
+-#define TARGET_FREEBSD_NR_freebsd4_statfs 157
+-#define TARGET_FREEBSD_NR_freebsd4_fstatfs 158
+-#define TARGET_FREEBSD_NR_lgetfh 160
+-#define TARGET_FREEBSD_NR_getfh 161
+-#define TARGET_FREEBSD_NR_getdomainname 162
+-#define TARGET_FREEBSD_NR_setdomainname 163
+-#define TARGET_FREEBSD_NR_uname 164
+-#define TARGET_FREEBSD_NR_sysarch 165
+-#define TARGET_FREEBSD_NR_rtprio 166
+-#define TARGET_FREEBSD_NR_semsys 169
+-#define TARGET_FREEBSD_NR_msgsys 170
+-#define TARGET_FREEBSD_NR_shmsys 171
+-#define TARGET_FREEBSD_NR_freebsd6_pread 173
+-#define TARGET_FREEBSD_NR_freebsd6_pwrite 174
+-#define TARGET_FREEBSD_NR_setfib 175
+-#define TARGET_FREEBSD_NR_ntp_adjtime 176
+-#define TARGET_FREEBSD_NR_setgid 181
+-#define TARGET_FREEBSD_NR_setegid 182
+-#define TARGET_FREEBSD_NR_seteuid 183
+-#define TARGET_FREEBSD_NR_stat 188
+-#define TARGET_FREEBSD_NR_fstat 189
+-#define TARGET_FREEBSD_NR_lstat 190
+-#define TARGET_FREEBSD_NR_pathconf 191
+-#define TARGET_FREEBSD_NR_fpathconf 192
+-#define TARGET_FREEBSD_NR_getrlimit 194
+-#define TARGET_FREEBSD_NR_setrlimit 195
+-#define TARGET_FREEBSD_NR_getdirentries 196
+-#define TARGET_FREEBSD_NR_freebsd6_mmap 197
+-#define TARGET_FREEBSD_NR___syscall 198
+-#define TARGET_FREEBSD_NR_freebsd6_lseek 199
+-#define TARGET_FREEBSD_NR_freebsd6_truncate 200
+-#define TARGET_FREEBSD_NR_freebsd6_ftruncate 201
+-#define TARGET_FREEBSD_NR___sysctl 202
+-#define TARGET_FREEBSD_NR_mlock 203
+-#define TARGET_FREEBSD_NR_munlock 204
+-#define TARGET_FREEBSD_NR_undelete 205
+-#define TARGET_FREEBSD_NR_futimes 206
+-#define TARGET_FREEBSD_NR_getpgid 207
+-#define TARGET_FREEBSD_NR_poll 209
+-#define TARGET_FREEBSD_NR___semctl 220
+-#define TARGET_FREEBSD_NR_semget 221
+-#define TARGET_FREEBSD_NR_semop 222
+-#define TARGET_FREEBSD_NR_msgctl 224
+-#define TARGET_FREEBSD_NR_msgget 225
+-#define TARGET_FREEBSD_NR_msgsnd 226
+-#define TARGET_FREEBSD_NR_msgrcv 227
+-#define TARGET_FREEBSD_NR_shmat 228
+-#define TARGET_FREEBSD_NR_shmctl 229
+-#define TARGET_FREEBSD_NR_shmdt 230
+-#define TARGET_FREEBSD_NR_shmget 231
+-#define TARGET_FREEBSD_NR_clock_gettime 232
+-#define TARGET_FREEBSD_NR_clock_settime 233
+-#define TARGET_FREEBSD_NR_clock_getres 234
+-#define TARGET_FREEBSD_NR_ktimer_create 235
+-#define TARGET_FREEBSD_NR_ktimer_delete 236
+-#define TARGET_FREEBSD_NR_ktimer_settime 237
+-#define TARGET_FREEBSD_NR_ktimer_gettime 238
+-#define TARGET_FREEBSD_NR_ktimer_getoverrun 239
+-#define TARGET_FREEBSD_NR_nanosleep 240
+-#define TARGET_FREEBSD_NR_ntp_gettime 248
+-#define TARGET_FREEBSD_NR_minherit 250
+-#define TARGET_FREEBSD_NR_rfork 251
+-#define TARGET_FREEBSD_NR_openbsd_poll 252
+-#define TARGET_FREEBSD_NR_issetugid 253
+-#define TARGET_FREEBSD_NR_lchown 254
+-#define TARGET_FREEBSD_NR_aio_read 255
+-#define TARGET_FREEBSD_NR_aio_write 256
+-#define TARGET_FREEBSD_NR_lio_listio 257
+-#define TARGET_FREEBSD_NR_getdents 272
+-#define TARGET_FREEBSD_NR_lchmod 274
+-#define TARGET_FREEBSD_NR_netbsd_lchown 275
+-#define TARGET_FREEBSD_NR_lutimes 276
+-#define TARGET_FREEBSD_NR_netbsd_msync 277
+-#define TARGET_FREEBSD_NR_nstat 278
+-#define TARGET_FREEBSD_NR_nfstat 279
+-#define TARGET_FREEBSD_NR_nlstat 280
+-#define TARGET_FREEBSD_NR_preadv 289
+-#define TARGET_FREEBSD_NR_pwritev 290
+-#define TARGET_FREEBSD_NR_freebsd4_fhstatfs 297
+-#define TARGET_FREEBSD_NR_fhopen 298
+-#define TARGET_FREEBSD_NR_fhstat 299
+-#define TARGET_FREEBSD_NR_modnext 300
+-#define TARGET_FREEBSD_NR_modstat 301
+-#define TARGET_FREEBSD_NR_modfnext 302
+-#define TARGET_FREEBSD_NR_modfind 303
+-#define TARGET_FREEBSD_NR_kldload 304
+-#define TARGET_FREEBSD_NR_kldunload 305
+-#define TARGET_FREEBSD_NR_kldfind 306
+-#define TARGET_FREEBSD_NR_kldnext 307
+-#define TARGET_FREEBSD_NR_kldstat 308
+-#define TARGET_FREEBSD_NR_kldfirstmod 309
+-#define TARGET_FREEBSD_NR_getsid 310
+-#define TARGET_FREEBSD_NR_setresuid 311
+-#define TARGET_FREEBSD_NR_setresgid 312
+-#define TARGET_FREEBSD_NR_aio_return 314
+-#define TARGET_FREEBSD_NR_aio_suspend 315
+-#define TARGET_FREEBSD_NR_aio_cancel 316
+-#define TARGET_FREEBSD_NR_aio_error 317
+-#define TARGET_FREEBSD_NR_oaio_read 318
+-#define TARGET_FREEBSD_NR_oaio_write 319
+-#define TARGET_FREEBSD_NR_olio_listio 320
+-#define TARGET_FREEBSD_NR_yield 321
+-#define TARGET_FREEBSD_NR_mlockall 324
+-#define TARGET_FREEBSD_NR_munlockall 325
+-#define TARGET_FREEBSD_NR___getcwd 326
+-#define TARGET_FREEBSD_NR_sched_setparam 327
+-#define TARGET_FREEBSD_NR_sched_getparam 328
+-#define TARGET_FREEBSD_NR_sched_setscheduler 329
+-#define TARGET_FREEBSD_NR_sched_getscheduler 330
+-#define TARGET_FREEBSD_NR_sched_yield 331
+-#define TARGET_FREEBSD_NR_sched_get_priority_max 332
+-#define TARGET_FREEBSD_NR_sched_get_priority_min 333
+-#define TARGET_FREEBSD_NR_sched_rr_get_interval 334
+-#define TARGET_FREEBSD_NR_utrace 335
+-#define TARGET_FREEBSD_NR_freebsd4_sendfile 336
+-#define TARGET_FREEBSD_NR_kldsym 337
+-#define TARGET_FREEBSD_NR_jail 338
+-#define TARGET_FREEBSD_NR_sigprocmask 340
+-#define TARGET_FREEBSD_NR_sigsuspend 341
+-#define TARGET_FREEBSD_NR_freebsd4_sigaction 342
+-#define TARGET_FREEBSD_NR_sigpending 343
+-#define TARGET_FREEBSD_NR_freebsd4_sigreturn 344
+-#define TARGET_FREEBSD_NR_sigtimedwait 345
+-#define TARGET_FREEBSD_NR_sigwaitinfo 346
+-#define TARGET_FREEBSD_NR___acl_get_file 347
+-#define TARGET_FREEBSD_NR___acl_set_file 348
+-#define TARGET_FREEBSD_NR___acl_get_fd 349
+-#define TARGET_FREEBSD_NR___acl_set_fd 350
+-#define TARGET_FREEBSD_NR___acl_delete_file 351
+-#define TARGET_FREEBSD_NR___acl_delete_fd 352
+-#define TARGET_FREEBSD_NR___acl_aclcheck_file 353
+-#define TARGET_FREEBSD_NR___acl_aclcheck_fd 354
+-#define TARGET_FREEBSD_NR_extattrctl 355
+-#define TARGET_FREEBSD_NR_extattr_set_file 356
+-#define TARGET_FREEBSD_NR_extattr_get_file 357
+-#define TARGET_FREEBSD_NR_extattr_delete_file 358
+-#define TARGET_FREEBSD_NR_aio_waitcomplete 359
+-#define TARGET_FREEBSD_NR_getresuid 360
+-#define TARGET_FREEBSD_NR_getresgid 361
+-#define TARGET_FREEBSD_NR_kqueue 362
+-#define TARGET_FREEBSD_NR_kevent 363
+-#define TARGET_FREEBSD_NR_extattr_set_fd 371
+-#define TARGET_FREEBSD_NR_extattr_get_fd 372
+-#define TARGET_FREEBSD_NR_extattr_delete_fd 373
+-#define TARGET_FREEBSD_NR___setugid 374
+-#define TARGET_FREEBSD_NR_nfsclnt 375
+-#define TARGET_FREEBSD_NR_eaccess 376
+-#define TARGET_FREEBSD_NR_nmount 378
+-#define TARGET_FREEBSD_NR___mac_get_proc 384
+-#define TARGET_FREEBSD_NR___mac_set_proc 385
+-#define TARGET_FREEBSD_NR___mac_get_fd 386
+-#define TARGET_FREEBSD_NR___mac_get_file 387
+-#define TARGET_FREEBSD_NR___mac_set_fd 388
+-#define TARGET_FREEBSD_NR___mac_set_file 389
+-#define TARGET_FREEBSD_NR_kenv 390
+-#define TARGET_FREEBSD_NR_lchflags 391
+-#define TARGET_FREEBSD_NR_uuidgen 392
+-#define TARGET_FREEBSD_NR_sendfile 393
+-#define TARGET_FREEBSD_NR_mac_syscall 394
+-#define TARGET_FREEBSD_NR_getfsstat 395
+-#define TARGET_FREEBSD_NR_statfs 396
+-#define TARGET_FREEBSD_NR_fstatfs 397
+-#define TARGET_FREEBSD_NR_fhstatfs 398
+-#define TARGET_FREEBSD_NR_ksem_close 400
+-#define TARGET_FREEBSD_NR_ksem_post 401
+-#define TARGET_FREEBSD_NR_ksem_wait 402
+-#define TARGET_FREEBSD_NR_ksem_trywait 403
+-#define TARGET_FREEBSD_NR_ksem_init 404
+-#define TARGET_FREEBSD_NR_ksem_open 405
+-#define TARGET_FREEBSD_NR_ksem_unlink 406
+-#define TARGET_FREEBSD_NR_ksem_getvalue 407
+-#define TARGET_FREEBSD_NR_ksem_destroy 408
+-#define TARGET_FREEBSD_NR___mac_get_pid 409
+-#define TARGET_FREEBSD_NR___mac_get_link 410
+-#define TARGET_FREEBSD_NR___mac_set_link 411
+-#define TARGET_FREEBSD_NR_extattr_set_link 412
+-#define TARGET_FREEBSD_NR_extattr_get_link 413
+-#define TARGET_FREEBSD_NR_extattr_delete_link 414
+-#define TARGET_FREEBSD_NR___mac_execve 415
+-#define TARGET_FREEBSD_NR_sigaction 416
+-#define TARGET_FREEBSD_NR_sigreturn 417
+-#define TARGET_FREEBSD_NR_getcontext 421
+-#define TARGET_FREEBSD_NR_setcontext 422
+-#define TARGET_FREEBSD_NR_swapcontext 423
+-#define TARGET_FREEBSD_NR_swapoff 424
+-#define TARGET_FREEBSD_NR___acl_get_link 425
+-#define TARGET_FREEBSD_NR___acl_set_link 426
+-#define TARGET_FREEBSD_NR___acl_delete_link 427
+-#define TARGET_FREEBSD_NR___acl_aclcheck_link 428
+-#define TARGET_FREEBSD_NR_sigwait 429
+-#define TARGET_FREEBSD_NR_thr_create 430
+-#define TARGET_FREEBSD_NR_thr_exit 431
+-#define TARGET_FREEBSD_NR_thr_self 432
+-#define TARGET_FREEBSD_NR_thr_kill 433
+-#define TARGET_FREEBSD_NR__umtx_lock 434
+-#define TARGET_FREEBSD_NR__umtx_unlock 435
+-#define TARGET_FREEBSD_NR_jail_attach 436
+-#define TARGET_FREEBSD_NR_extattr_list_fd 437
+-#define TARGET_FREEBSD_NR_extattr_list_file 438
+-#define TARGET_FREEBSD_NR_extattr_list_link 439
+-#define TARGET_FREEBSD_NR_ksem_timedwait 441
+-#define TARGET_FREEBSD_NR_thr_suspend 442
+-#define TARGET_FREEBSD_NR_thr_wake 443
+-#define TARGET_FREEBSD_NR_kldunloadf 444
+-#define TARGET_FREEBSD_NR_audit 445
+-#define TARGET_FREEBSD_NR_auditon 446
+-#define TARGET_FREEBSD_NR_getauid 447
+-#define TARGET_FREEBSD_NR_setauid 448
+-#define TARGET_FREEBSD_NR_getaudit 449
+-#define TARGET_FREEBSD_NR_setaudit 450
+-#define TARGET_FREEBSD_NR_getaudit_addr 451
+-#define TARGET_FREEBSD_NR_setaudit_addr 452
+-#define TARGET_FREEBSD_NR_auditctl 453
+-#define TARGET_FREEBSD_NR__umtx_op 454
+-#define TARGET_FREEBSD_NR_thr_new 455
+-#define TARGET_FREEBSD_NR_sigqueue 456
+-#define TARGET_FREEBSD_NR_kmq_open 457
+-#define TARGET_FREEBSD_NR_kmq_setattr 458
+-#define TARGET_FREEBSD_NR_kmq_timedreceive 459
+-#define TARGET_FREEBSD_NR_kmq_timedsend 460
+-#define TARGET_FREEBSD_NR_kmq_notify 461
+-#define TARGET_FREEBSD_NR_kmq_unlink 462
+-#define TARGET_FREEBSD_NR_abort2 463
+-#define TARGET_FREEBSD_NR_thr_set_name 464
+-#define TARGET_FREEBSD_NR_aio_fsync 465
+-#define TARGET_FREEBSD_NR_rtprio_thread 466
+-#define TARGET_FREEBSD_NR_sctp_peeloff 471
+-#define TARGET_FREEBSD_NR_sctp_generic_sendmsg 472
+-#define TARGET_FREEBSD_NR_sctp_generic_sendmsg_iov 473
+-#define TARGET_FREEBSD_NR_sctp_generic_recvmsg 474
+-#define TARGET_FREEBSD_NR_pread 475
+-#define TARGET_FREEBSD_NR_pwrite 476
+-#define TARGET_FREEBSD_NR_mmap 477
+-#define TARGET_FREEBSD_NR_lseek 478
+-#define TARGET_FREEBSD_NR_truncate 479
+-#define TARGET_FREEBSD_NR_ftruncate 480
+-#define TARGET_FREEBSD_NR_thr_kill2 481
+-#define TARGET_FREEBSD_NR_shm_open 482
+-#define TARGET_FREEBSD_NR_shm_unlink 483
+-#define TARGET_FREEBSD_NR_cpuset 484
+-#define TARGET_FREEBSD_NR_cpuset_setid 485
+-#define TARGET_FREEBSD_NR_cpuset_getid 486
+-#define TARGET_FREEBSD_NR_cpuset_getaffinity 487
+-#define TARGET_FREEBSD_NR_cpuset_setaffinity 488
+-#define TARGET_FREEBSD_NR_faccessat 489
+-#define TARGET_FREEBSD_NR_fchmodat 490
+-#define TARGET_FREEBSD_NR_fchownat 491
+-#define TARGET_FREEBSD_NR_fexecve 492
+-#define TARGET_FREEBSD_NR_fstatat 493
+-#define TARGET_FREEBSD_NR_futimesat 494
+-#define TARGET_FREEBSD_NR_linkat 495
+-#define TARGET_FREEBSD_NR_mkdirat 496
+-#define TARGET_FREEBSD_NR_mkfifoat 497
+-#define TARGET_FREEBSD_NR_mknodat 498
+-#define TARGET_FREEBSD_NR_openat 499
+-#define TARGET_FREEBSD_NR_readlinkat 500
+-#define TARGET_FREEBSD_NR_renameat 501
+-#define TARGET_FREEBSD_NR_symlinkat 502
+-#define TARGET_FREEBSD_NR_unlinkat 503
+-#define TARGET_FREEBSD_NR_posix_openpt 504
++#define TARGET_FREEBSD_NR_syscall 0
++#define TARGET_FREEBSD_NR_exit 1
++#define TARGET_FREEBSD_NR_fork 2
++#define TARGET_FREEBSD_NR_read 3
++#define TARGET_FREEBSD_NR_write 4
++#define TARGET_FREEBSD_NR_open 5
++#define TARGET_FREEBSD_NR_close 6
++#define TARGET_FREEBSD_NR_wait4 7
++ /* 8 is old creat */
++#define TARGET_FREEBSD_NR_link 9
++#define TARGET_FREEBSD_NR_unlink 10
++ /* 11 is obsolete execv */
++#define TARGET_FREEBSD_NR_chdir 12
++#define TARGET_FREEBSD_NR_fchdir 13
++#define TARGET_FREEBSD_NR_mknod 14
++#define TARGET_FREEBSD_NR_chmod 15
++#define TARGET_FREEBSD_NR_chown 16
++#define TARGET_FREEBSD_NR_break 17
++#define TARGET_FREEBSD_NR_freebsd4_getfsstat 18
++ /* 19 is old lseek */
++#define TARGET_FREEBSD_NR_getpid 20
++#define TARGET_FREEBSD_NR_mount 21
++#define TARGET_FREEBSD_NR_unmount 22
++#define TARGET_FREEBSD_NR_setuid 23
++#define TARGET_FREEBSD_NR_getuid 24
++#define TARGET_FREEBSD_NR_geteuid 25
++#define TARGET_FREEBSD_NR_ptrace 26
++#define TARGET_FREEBSD_NR_recvmsg 27
++#define TARGET_FREEBSD_NR_sendmsg 28
++#define TARGET_FREEBSD_NR_recvfrom 29
++#define TARGET_FREEBSD_NR_accept 30
++#define TARGET_FREEBSD_NR_getpeername 31
++#define TARGET_FREEBSD_NR_getsockname 32
++#define TARGET_FREEBSD_NR_access 33
++#define TARGET_FREEBSD_NR_chflags 34
++#define TARGET_FREEBSD_NR_fchflags 35
++#define TARGET_FREEBSD_NR_sync 36
++#define TARGET_FREEBSD_NR_kill 37
++ /* 38 is old stat */
++#define TARGET_FREEBSD_NR_getppid 39
++ /* 40 is old lstat */
++#define TARGET_FREEBSD_NR_dup 41
++#define TARGET_FREEBSD_NR_pipe 42
++#define TARGET_FREEBSD_NR_getegid 43
++#define TARGET_FREEBSD_NR_profil 44
++#define TARGET_FREEBSD_NR_ktrace 45
++ /* 46 is old sigaction */
++#define TARGET_FREEBSD_NR_getgid 47
++ /* 48 is old sigprocmask */
++#define TARGET_FREEBSD_NR_getlogin 49
++#define TARGET_FREEBSD_NR_setlogin 50
++#define TARGET_FREEBSD_NR_acct 51
++ /* 52 is old sigpending */
++#define TARGET_FREEBSD_NR_sigaltstack 53
++#define TARGET_FREEBSD_NR_ioctl 54
++#define TARGET_FREEBSD_NR_reboot 55
++#define TARGET_FREEBSD_NR_revoke 56
++#define TARGET_FREEBSD_NR_symlink 57
++#define TARGET_FREEBSD_NR_readlink 58
++#define TARGET_FREEBSD_NR_execve 59
++#define TARGET_FREEBSD_NR_umask 60
++#define TARGET_FREEBSD_NR_chroot 61
++ /* 62 is old fstat */
++ /* 63 is old getkerninfo */
++ /* 64 is old getpagesize */
++#define TARGET_FREEBSD_NR_msync 65
++#define TARGET_FREEBSD_NR_vfork 66
++ /* 67 is obsolete vread */
++ /* 68 is obsolete vwrite */
++#define TARGET_FREEBSD_NR_sbrk 69
++#define TARGET_FREEBSD_NR_sstk 70
++ /* 71 is old mmap */
++#define TARGET_FREEBSD_NR_vadvise 72
++#define TARGET_FREEBSD_NR_munmap 73
++#define TARGET_FREEBSD_NR_mprotect 74
++#define TARGET_FREEBSD_NR_madvise 75
++ /* 76 is obsolete vhangup */
++ /* 77 is obsolete vlimit */
++#define TARGET_FREEBSD_NR_mincore 78
++#define TARGET_FREEBSD_NR_getgroups 79
++#define TARGET_FREEBSD_NR_setgroups 80
++#define TARGET_FREEBSD_NR_getpgrp 81
++#define TARGET_FREEBSD_NR_setpgid 82
++#define TARGET_FREEBSD_NR_setitimer 83
++ /* 84 is old wait */
++#define TARGET_FREEBSD_NR_swapon 85
++#define TARGET_FREEBSD_NR_getitimer 86
++ /* 87 is old gethostname */
++ /* 88 is old sethostname */
++#define TARGET_FREEBSD_NR_getdtablesize 89
++#define TARGET_FREEBSD_NR_dup2 90
++#define TARGET_FREEBSD_NR_fcntl 92
++#define TARGET_FREEBSD_NR_select 93
++#define TARGET_FREEBSD_NR_fsync 95
++#define TARGET_FREEBSD_NR_setpriority 96
++#define TARGET_FREEBSD_NR_socket 97
++#define TARGET_FREEBSD_NR_connect 98
++ /* 99 is old accept */
++#define TARGET_FREEBSD_NR_getpriority 100
++ /* 101 is old send */
++ /* 102 is old recv */
++ /* 103 is old sigreturn */
++#define TARGET_FREEBSD_NR_bind 104
++#define TARGET_FREEBSD_NR_setsockopt 105
++#define TARGET_FREEBSD_NR_listen 106
++ /* 107 is obsolete vtimes */
++ /* 108 is old sigvec */
++ /* 109 is old sigblock */
++ /* 110 is old sigsetmask */
++ /* 111 is old sigsuspend */
++ /* 112 is old sigstack */
++ /* 113 is old recvmsg */
++ /* 114 is old sendmsg */
++ /* 115 is obsolete vtrace */
++#define TARGET_FREEBSD_NR_gettimeofday 116
++#define TARGET_FREEBSD_NR_getrusage 117
++#define TARGET_FREEBSD_NR_getsockopt 118
++#define TARGET_FREEBSD_NR_readv 120
++#define TARGET_FREEBSD_NR_writev 121
++#define TARGET_FREEBSD_NR_settimeofday 122
++#define TARGET_FREEBSD_NR_fchown 123
++#define TARGET_FREEBSD_NR_fchmod 124
++ /* 125 is old recvfrom */
++#define TARGET_FREEBSD_NR_setreuid 126
++#define TARGET_FREEBSD_NR_setregid 127
++#define TARGET_FREEBSD_NR_rename 128
++ /* 129 is old truncate */
++ /* 130 is old ftruncate */
++#define TARGET_FREEBSD_NR_flock 131
++#define TARGET_FREEBSD_NR_mkfifo 132
++#define TARGET_FREEBSD_NR_sendto 133
++#define TARGET_FREEBSD_NR_shutdown 134
++#define TARGET_FREEBSD_NR_socketpair 135
++#define TARGET_FREEBSD_NR_mkdir 136
++#define TARGET_FREEBSD_NR_rmdir 137
++#define TARGET_FREEBSD_NR_utimes 138
++ /* 139 is obsolete 4.2 sigreturn */
++#define TARGET_FREEBSD_NR_adjtime 140
++ /* 141 is old getpeername */
++ /* 142 is old gethostid */
++ /* 143 is old sethostid */
++ /* 144 is old getrlimit */
++ /* 145 is old setrlimit */
++ /* 146 is old killpg */
++#define TARGET_FREEBSD_NR_setsid 147
++#define TARGET_FREEBSD_NR_quotactl 148
++ /* 149 is old quota */
++ /* 150 is old getsockname */
++#define TARGET_FREEBSD_NR_nlm_syscall 154
++#define TARGET_FREEBSD_NR_nfssvc 155
++ /* 156 is old getdirentries */
++#define TARGET_FREEBSD_NR_freebsd4_statfs 157
++#define TARGET_FREEBSD_NR_freebsd4_fstatfs 158
++#define TARGET_FREEBSD_NR_lgetfh 160
++#define TARGET_FREEBSD_NR_getfh 161
++#define TARGET_FREEBSD_NR_freebsd4_getdomainname 162
++#define TARGET_FREEBSD_NR_freebsd4_setdomainname 163
++#define TARGET_FREEBSD_NR_freebsd4_uname 164
++#define TARGET_FREEBSD_NR_sysarch 165
++#define TARGET_FREEBSD_NR_rtprio 166
++#define TARGET_FREEBSD_NR_semsys 169
++#define TARGET_FREEBSD_NR_msgsys 170
++#define TARGET_FREEBSD_NR_shmsys 171
++#define TARGET_FREEBSD_NR_freebsd6_pread 173
++#define TARGET_FREEBSD_NR_freebsd6_pwrite 174
++#define TARGET_FREEBSD_NR_setfib 175
++#define TARGET_FREEBSD_NR_ntp_adjtime 176
++#define TARGET_FREEBSD_NR_setgid 181
++#define TARGET_FREEBSD_NR_setegid 182
++#define TARGET_FREEBSD_NR_seteuid 183
++#define TARGET_FREEBSD_NR_stat 188
++#define TARGET_FREEBSD_NR_fstat 189
++#define TARGET_FREEBSD_NR_lstat 190
++#define TARGET_FREEBSD_NR_pathconf 191
++#define TARGET_FREEBSD_NR_fpathconf 192
++#define TARGET_FREEBSD_NR_getrlimit 194
++#define TARGET_FREEBSD_NR_setrlimit 195
++#define TARGET_FREEBSD_NR_getdirentries 196
++#define TARGET_FREEBSD_NR_freebsd6_mmap 197
++#define TARGET_FREEBSD_NR___syscall 198
++#define TARGET_FREEBSD_NR_freebsd6_lseek 199
++#define TARGET_FREEBSD_NR_freebsd6_truncate 200
++#define TARGET_FREEBSD_NR_freebsd6_ftruncate 201
++#define TARGET_FREEBSD_NR___sysctl 202
++#define TARGET_FREEBSD_NR_mlock 203
++#define TARGET_FREEBSD_NR_munlock 204
++#define TARGET_FREEBSD_NR_undelete 205
++#define TARGET_FREEBSD_NR_futimes 206
++#define TARGET_FREEBSD_NR_getpgid 207
++#define TARGET_FREEBSD_NR_poll 209
++#define TARGET_FREEBSD_NR_freebsd7___semctl 220
++#define TARGET_FREEBSD_NR_semget 221
++#define TARGET_FREEBSD_NR_semop 222
++#define TARGET_FREEBSD_NR_freebsd7_msgctl 224
++#define TARGET_FREEBSD_NR_msgget 225
++#define TARGET_FREEBSD_NR_msgsnd 226
++#define TARGET_FREEBSD_NR_msgrcv 227
++#define TARGET_FREEBSD_NR_shmat 228
++#define TARGET_FREEBSD_NR_freebsd7_shmctl 229
++#define TARGET_FREEBSD_NR_shmdt 230
++#define TARGET_FREEBSD_NR_shmget 231
++#define TARGET_FREEBSD_NR_clock_gettime 232
++#define TARGET_FREEBSD_NR_clock_settime 233
++#define TARGET_FREEBSD_NR_clock_getres 234
++#define TARGET_FREEBSD_NR_ktimer_create 235
++#define TARGET_FREEBSD_NR_ktimer_delete 236
++#define TARGET_FREEBSD_NR_ktimer_settime 237
++#define TARGET_FREEBSD_NR_ktimer_gettime 238
++#define TARGET_FREEBSD_NR_ktimer_getoverrun 239
++#define TARGET_FREEBSD_NR_nanosleep 240
++#define TARGET_FREEBSD_NR_ntp_gettime 248
++#define TARGET_FREEBSD_NR_minherit 250
++#define TARGET_FREEBSD_NR_rfork 251
++#define TARGET_FREEBSD_NR_openbsd_poll 252
++#define TARGET_FREEBSD_NR_issetugid 253
++#define TARGET_FREEBSD_NR_lchown 254
++#define TARGET_FREEBSD_NR_aio_read 255
++#define TARGET_FREEBSD_NR_aio_write 256
++#define TARGET_FREEBSD_NR_lio_listio 257
++#define TARGET_FREEBSD_NR_getdents 272
++#define TARGET_FREEBSD_NR_lchmod 274
++#define TARGET_FREEBSD_NR_netbsd_lchown 275
++#define TARGET_FREEBSD_NR_lutimes 276
++#define TARGET_FREEBSD_NR_netbsd_msync 277
++#define TARGET_FREEBSD_NR_nstat 278
++#define TARGET_FREEBSD_NR_nfstat 279
++#define TARGET_FREEBSD_NR_nlstat 280
++#define TARGET_FREEBSD_NR_preadv 289
++#define TARGET_FREEBSD_NR_pwritev 290
++#define TARGET_FREEBSD_NR_freebsd4_fhstatfs 297
++#define TARGET_FREEBSD_NR_fhopen 298
++#define TARGET_FREEBSD_NR_fhstat 299
++#define TARGET_FREEBSD_NR_modnext 300
++#define TARGET_FREEBSD_NR_modstat 301
++#define TARGET_FREEBSD_NR_modfnext 302
++#define TARGET_FREEBSD_NR_modfind 303
++#define TARGET_FREEBSD_NR_kldload 304
++#define TARGET_FREEBSD_NR_kldunload 305
++#define TARGET_FREEBSD_NR_kldfind 306
++#define TARGET_FREEBSD_NR_kldnext 307
++#define TARGET_FREEBSD_NR_kldstat 308
++#define TARGET_FREEBSD_NR_kldfirstmod 309
++#define TARGET_FREEBSD_NR_getsid 310
++#define TARGET_FREEBSD_NR_setresuid 311
++#define TARGET_FREEBSD_NR_setresgid 312
++ /* 313 is obsolete signanosleep */
++#define TARGET_FREEBSD_NR_aio_return 314
++#define TARGET_FREEBSD_NR_aio_suspend 315
++#define TARGET_FREEBSD_NR_aio_cancel 316
++#define TARGET_FREEBSD_NR_aio_error 317
++#define TARGET_FREEBSD_NR_oaio_read 318
++#define TARGET_FREEBSD_NR_oaio_write 319
++#define TARGET_FREEBSD_NR_olio_listio 320
++#define TARGET_FREEBSD_NR_yield 321
++ /* 322 is obsolete thr_sleep */
++ /* 323 is obsolete thr_wakeup */
++#define TARGET_FREEBSD_NR_mlockall 324
++#define TARGET_FREEBSD_NR_munlockall 325
++#define TARGET_FREEBSD_NR___getcwd 326
++#define TARGET_FREEBSD_NR_sched_setparam 327
++#define TARGET_FREEBSD_NR_sched_getparam 328
++#define TARGET_FREEBSD_NR_sched_setscheduler 329
++#define TARGET_FREEBSD_NR_sched_getscheduler 330
++#define TARGET_FREEBSD_NR_sched_yield 331
++#define TARGET_FREEBSD_NR_sched_get_priority_max 332
++#define TARGET_FREEBSD_NR_sched_get_priority_min 333
++#define TARGET_FREEBSD_NR_sched_rr_get_interval 334
++#define TARGET_FREEBSD_NR_utrace 335
++#define TARGET_FREEBSD_NR_freebsd4_sendfile 336
++#define TARGET_FREEBSD_NR_kldsym 337
++#define TARGET_FREEBSD_NR_jail 338
++#define TARGET_FREEBSD_NR_nnpfs_syscall 339
++#define TARGET_FREEBSD_NR_sigprocmask 340
++#define TARGET_FREEBSD_NR_sigsuspend 341
++#define TARGET_FREEBSD_NR_freebsd4_sigaction 342
++#define TARGET_FREEBSD_NR_sigpending 343
++#define TARGET_FREEBSD_NR_freebsd4_sigreturn 344
++#define TARGET_FREEBSD_NR_sigtimedwait 345
++#define TARGET_FREEBSD_NR_sigwaitinfo 346
++#define TARGET_FREEBSD_NR___acl_get_file 347
++#define TARGET_FREEBSD_NR___acl_set_file 348
++#define TARGET_FREEBSD_NR___acl_get_fd 349
++#define TARGET_FREEBSD_NR___acl_set_fd 350
++#define TARGET_FREEBSD_NR___acl_delete_file 351
++#define TARGET_FREEBSD_NR___acl_delete_fd 352
++#define TARGET_FREEBSD_NR___acl_aclcheck_file 353
++#define TARGET_FREEBSD_NR___acl_aclcheck_fd 354
++#define TARGET_FREEBSD_NR_extattrctl 355
++#define TARGET_FREEBSD_NR_extattr_set_file 356
++#define TARGET_FREEBSD_NR_extattr_get_file 357
++#define TARGET_FREEBSD_NR_extattr_delete_file 358
++#define TARGET_FREEBSD_NR_aio_waitcomplete 359
++#define TARGET_FREEBSD_NR_getresuid 360
++#define TARGET_FREEBSD_NR_getresgid 361
++#define TARGET_FREEBSD_NR_kqueue 362
++#define TARGET_FREEBSD_NR_kevent 363
++#define TARGET_FREEBSD_NR_extattr_set_fd 371
++#define TARGET_FREEBSD_NR_extattr_get_fd 372
++#define TARGET_FREEBSD_NR_extattr_delete_fd 373
++#define TARGET_FREEBSD_NR___setugid 374
++#define TARGET_FREEBSD_NR_eaccess 376
++#define TARGET_FREEBSD_NR_afs3_syscall 377
++#define TARGET_FREEBSD_NR_nmount 378
++#define TARGET_FREEBSD_NR___mac_get_proc 384
++#define TARGET_FREEBSD_NR___mac_set_proc 385
++#define TARGET_FREEBSD_NR___mac_get_fd 386
++#define TARGET_FREEBSD_NR___mac_get_file 387
++#define TARGET_FREEBSD_NR___mac_set_fd 388
++#define TARGET_FREEBSD_NR___mac_set_file 389
++#define TARGET_FREEBSD_NR_kenv 390
++#define TARGET_FREEBSD_NR_lchflags 391
++#define TARGET_FREEBSD_NR_uuidgen 392
++#define TARGET_FREEBSD_NR_sendfile 393
++#define TARGET_FREEBSD_NR_mac_syscall 394
++#define TARGET_FREEBSD_NR_getfsstat 395
++#define TARGET_FREEBSD_NR_statfs 396
++#define TARGET_FREEBSD_NR_fstatfs 397
++#define TARGET_FREEBSD_NR_fhstatfs 398
++#define TARGET_FREEBSD_NR_ksem_close 400
++#define TARGET_FREEBSD_NR_ksem_post 401
++#define TARGET_FREEBSD_NR_ksem_wait 402
++#define TARGET_FREEBSD_NR_ksem_trywait 403
++#define TARGET_FREEBSD_NR_ksem_init 404
++#define TARGET_FREEBSD_NR_ksem_open 405
++#define TARGET_FREEBSD_NR_ksem_unlink 406
++#define TARGET_FREEBSD_NR_ksem_getvalue 407
++#define TARGET_FREEBSD_NR_ksem_destroy 408
++#define TARGET_FREEBSD_NR___mac_get_pid 409
++#define TARGET_FREEBSD_NR___mac_get_link 410
++#define TARGET_FREEBSD_NR___mac_set_link 411
++#define TARGET_FREEBSD_NR_extattr_set_link 412
++#define TARGET_FREEBSD_NR_extattr_get_link 413
++#define TARGET_FREEBSD_NR_extattr_delete_link 414
++#define TARGET_FREEBSD_NR___mac_execve 415
++#define TARGET_FREEBSD_NR_sigaction 416
++#define TARGET_FREEBSD_NR_sigreturn 417
++#define TARGET_FREEBSD_NR_getcontext 421
++#define TARGET_FREEBSD_NR_setcontext 422
++#define TARGET_FREEBSD_NR_swapcontext 423
++#define TARGET_FREEBSD_NR_swapoff 424
++#define TARGET_FREEBSD_NR___acl_get_link 425
++#define TARGET_FREEBSD_NR___acl_set_link 426
++#define TARGET_FREEBSD_NR___acl_delete_link 427
++#define TARGET_FREEBSD_NR___acl_aclcheck_link 428
++#define TARGET_FREEBSD_NR_sigwait 429
++#define TARGET_FREEBSD_NR_thr_create 430
++#define TARGET_FREEBSD_NR_thr_exit 431
++#define TARGET_FREEBSD_NR_thr_self 432
++#define TARGET_FREEBSD_NR_thr_kill 433
++#define TARGET_FREEBSD_NR__umtx_lock 434
++#define TARGET_FREEBSD_NR__umtx_unlock 435
++#define TARGET_FREEBSD_NR_jail_attach 436
++#define TARGET_FREEBSD_NR_extattr_list_fd 437
++#define TARGET_FREEBSD_NR_extattr_list_file 438
++#define TARGET_FREEBSD_NR_extattr_list_link 439
++#define TARGET_FREEBSD_NR_ksem_timedwait 441
++#define TARGET_FREEBSD_NR_thr_suspend 442
++#define TARGET_FREEBSD_NR_thr_wake 443
++#define TARGET_FREEBSD_NR_kldunloadf 444
++#define TARGET_FREEBSD_NR_audit 445
++#define TARGET_FREEBSD_NR_auditon 446
++#define TARGET_FREEBSD_NR_getauid 447
++#define TARGET_FREEBSD_NR_setauid 448
++#define TARGET_FREEBSD_NR_getaudit 449
++#define TARGET_FREEBSD_NR_setaudit 450
++#define TARGET_FREEBSD_NR_getaudit_addr 451
++#define TARGET_FREEBSD_NR_setaudit_addr 452
++#define TARGET_FREEBSD_NR_auditctl 453
++#define TARGET_FREEBSD_NR__umtx_op 454
++#define TARGET_FREEBSD_NR_thr_new 455
++#define TARGET_FREEBSD_NR_sigqueue 456
++#define TARGET_FREEBSD_NR_kmq_open 457
++#define TARGET_FREEBSD_NR_kmq_setattr 458
++#define TARGET_FREEBSD_NR_kmq_timedreceive 459
++#define TARGET_FREEBSD_NR_kmq_timedsend 460
++#define TARGET_FREEBSD_NR_kmq_notify 461
++#define TARGET_FREEBSD_NR_kmq_unlink 462
++#define TARGET_FREEBSD_NR_abort2 463
++#define TARGET_FREEBSD_NR_thr_set_name 464
++#define TARGET_FREEBSD_NR_aio_fsync 465
++#define TARGET_FREEBSD_NR_rtprio_thread 466
++#define TARGET_FREEBSD_NR_sctp_peeloff 471
++#define TARGET_FREEBSD_NR_sctp_generic_sendmsg 472
++#define TARGET_FREEBSD_NR_sctp_generic_sendmsg_iov 473
++#define TARGET_FREEBSD_NR_sctp_generic_recvmsg 474
++#define TARGET_FREEBSD_NR_pread 475
++#define TARGET_FREEBSD_NR_pwrite 476
++#define TARGET_FREEBSD_NR_mmap 477
++#define TARGET_FREEBSD_NR_lseek 478
++#define TARGET_FREEBSD_NR_truncate 479
++#define TARGET_FREEBSD_NR_ftruncate 480
++#define TARGET_FREEBSD_NR_thr_kill2 481
++#define TARGET_FREEBSD_NR_shm_open 482
++#define TARGET_FREEBSD_NR_shm_unlink 483
++#define TARGET_FREEBSD_NR_cpuset 484
++#define TARGET_FREEBSD_NR_cpuset_setid 485
++#define TARGET_FREEBSD_NR_cpuset_getid 486
++#define TARGET_FREEBSD_NR_cpuset_getaffinity 487
++#define TARGET_FREEBSD_NR_cpuset_setaffinity 488
++#define TARGET_FREEBSD_NR_faccessat 489
++#define TARGET_FREEBSD_NR_fchmodat 490
++#define TARGET_FREEBSD_NR_fchownat 491
++#define TARGET_FREEBSD_NR_fexecve 492
++#define TARGET_FREEBSD_NR_fstatat 493
++#define TARGET_FREEBSD_NR_futimesat 494
++#define TARGET_FREEBSD_NR_linkat 495
++#define TARGET_FREEBSD_NR_mkdirat 496
++#define TARGET_FREEBSD_NR_mkfifoat 497
++#define TARGET_FREEBSD_NR_mknodat 498
++#define TARGET_FREEBSD_NR_openat 499
++#define TARGET_FREEBSD_NR_readlinkat 500
++#define TARGET_FREEBSD_NR_renameat 501
++#define TARGET_FREEBSD_NR_symlinkat 502
++#define TARGET_FREEBSD_NR_unlinkat 503
++#define TARGET_FREEBSD_NR_posix_openpt 504
++#define TARGET_FREEBSD_NR_gssd_syscall 505
++#define TARGET_FREEBSD_NR_jail_get 506
++#define TARGET_FREEBSD_NR_jail_set 507
++#define TARGET_FREEBSD_NR_jail_remove 508
++#define TARGET_FREEBSD_NR_closefrom 509
++#define TARGET_FREEBSD_NR___semctl 510
++#define TARGET_FREEBSD_NR_msgctl 511
++#define TARGET_FREEBSD_NR_shmctl 512
++#define TARGET_FREEBSD_NR_lpathconf 513
++#define TARGET_FREEBSD_NR_cap_new 514
++#define TARGET_FREEBSD_NR_cap_getrights 515
++#define TARGET_FREEBSD_NR_cap_enter 516
++#define TARGET_FREEBSD_NR_cap_getmode 517
++#define TARGET_FREEBSD_NR_pdfork 518
++#define TARGET_FREEBSD_NR_pdkill 519
++#define TARGET_FREEBSD_NR_pdgetpid 520
++#define TARGET_FREEBSD_NR_pselect 522
++#define TARGET_FREEBSD_NR_getloginclass 523
++#define TARGET_FREEBSD_NR_setloginclass 524
++#define TARGET_FREEBSD_NR_rctl_get_racct 525
++#define TARGET_FREEBSD_NR_rctl_get_rules 526
++#define TARGET_FREEBSD_NR_rctl_get_limits 527
++#define TARGET_FREEBSD_NR_rctl_add_rule 528
++#define TARGET_FREEBSD_NR_rctl_remove_rule 529
++#define TARGET_FREEBSD_NR_posix_fallocate 530
++#define TARGET_FREEBSD_NR_posix_fadvise 531
++#define TARGET_FREEBSD_NR_MAXSYSCALL 532
+diff --git a/bsd-user/i386/target_signal.h b/bsd-user/i386/target_signal.h
+index 2ef36d1..285e7f9 100644
+--- a/bsd-user/i386/target_signal.h
++++ b/bsd-user/i386/target_signal.h
+@@ -3,18 +3,12 @@
+
+ #include "cpu.h"
+
+-/* this struct defines a stack used during syscall handling */
+-
+-typedef struct target_sigaltstack {
+- abi_ulong ss_sp;
+- abi_long ss_flags;
+- abi_ulong ss_size;
+-} target_stack_t;
+-
+-
+ static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
+ {
+ return state->regs[R_ESP];
+ }
+
++#define TARGET_MINSIGSTKSZ (512 * 4)
++#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/i386/target_vmparam.h b/bsd-user/i386/target_vmparam.h
+new file mode 100644
+index 0000000..8fc98d5
+--- /dev/null
++++ b/bsd-user/i386/target_vmparam.h
+@@ -0,0 +1,27 @@
++#ifndef _TARGET_VMPARAM_H_
++#define _TARGET_VMPARAM_H_
++
++#if defined(__FreeBSD__)
++
++#define TARGET_USRSTACK (0xbfc00000)
++
++struct target_ps_strings {
++ abi_ulong ps_argvstr;
++ uint32_t ps_nargvstr;
++ abi_ulong ps_envstr;
++ uint32_t ps_nenvstr;
++};
++
++#define TARGET_SPACE_USRSPACE 4096
++#define TARGET_ARG_MAX 262144
++
++#define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
++
++#define TARGET_SZSIGCODE 0
++
++#else
++
++#define TARGET_USRSTACK 0
++#endif
++
++#endif /* _TARGET_VMPARAM_H_ */
+diff --git a/bsd-user/main.c b/bsd-user/main.c
+index b4e42f3..146f022 100644
+--- a/bsd-user/main.c
++++ b/bsd-user/main.c
+@@ -642,6 +642,243 @@ void cpu_loop(CPUARMState *env)
+
+ #endif
+
++#if defined(TARGET_MIPS) || defined(TARGET_MIPS64)
++
++/*
++ * From sys/mips/mips/trap.c syscalls have the following stored away in the
++ * registers:
++ *
++ * v0(2): if either SYS___syscall (198) or SYS_syscall (0) then indirect syscall
++ * otherwise it is a direct syscall.
++ *
++ * If direct syscall:
++ *
++ * MIPS MIPS64
++ * v0(2): v0(2) syscall #
++ * a0(4): a0(4) arg0
++ * a1(5): a1(5) arg1
++ * a2(6): a2(6) arg2
++ * a3(7): a3(7) arg3
++ * t4(12): a4(8) arg4
++ * t5(13): a5(9) arg5
++ * t6(14): a6(10) arg6
++ * t7(15): a7(11) arg7
++ *
++ * If indirect syscall:
++ *
++ * MIPS MIPS64
++ * a0(4): a0(4) syscall #
++ * a1(5): a1(5) arg0
++ * a2(6): a2(6) arg1
++ * a3(7): a3(7) arg2
++ * t4(12): a4(8) arg3
++ * t5(13): a5(9) arg4
++ * t6(14): a6(10) arg5
++ * t7(15): a7(11) arg6
++ *
++ */
++
++#include <sys/syscall.h> /* For SYS_[__]syscall, SYS_MAXSYSCALL */
++
++static int do_store_exclusive(CPUMIPSState *env)
++{
++ target_ulong addr;
++ target_ulong page_addr;
++ target_ulong val;
++ int flags;
++ int segv = 0;
++ int reg;
++ int d;
++
++ addr = env->lladdr;
++ page_addr = addr & TARGET_PAGE_MASK;
++ start_exclusive();
++ mmap_lock();
++ flags = page_get_flags(page_addr);
++ if ((flags & PAGE_READ) == 0) {
++ segv = 1;
++ } else {
++ reg = env->llreg & 0x1f;
++ d = (env->llreg & 0x20) != 0;
++ if (d) {
++ segv = get_user_s64(val, addr);
++ } else {
++ segv = get_user_s32(val, addr);
++ }
++ if (!segv) {
++ if (val != env->llval) {
++ env->active_tc.gpr[reg] = 0;
++ } else {
++ if (d) {
++ segv =
++ put_user_u64(env->llnewval, addr);
++ } else {
++ segv =
++ put_user_u32(env->llnewval, addr);
++ }
++ if (!segv) {
++ env->active_tc.gpr[reg] = 1;
++ }
++ }
++ }
++ }
++ env->lladdr = -1;
++ if (!segv) {
++ env->active_tc.PC += 4;
++ }
++ mmap_unlock();
++ end_exclusive();
++ return (segv);
++}
++
++void cpu_loop(CPUMIPSState *env)
++{
++ target_siginfo_t info;
++ int trapnr;
++ abi_long ret;
++ unsigned int syscall_num;
++
++ for(;;) {
++ cpu_exec_start(env);
++ trapnr = cpu_mips_exec(env);
++ cpu_exec_end(env);
++ switch(trapnr) {
++ case EXCP_SYSCALL: /* syscall exception */
++ syscall_num = env->active_tc.gpr[2]; /* v0 */
++ env->active_tc.PC += 4;
++ if (syscall_num >= SYS_MAXSYSCALL) {
++ ret = -TARGET_ENOSYS;
++ } else {
++ if (SYS_syscall == syscall_num ||
++ SYS___syscall == syscall_num) {
++#if defined(TARGET_MIPS64)
++ ret = do_freebsd_syscall(env,
++ env->active_tc.gpr[4],/* syscall #*/
++ env->active_tc.gpr[5], /* arg0 */
++ env->active_tc.gpr[6], /* arg1 */
++ env->active_tc.gpr[7], /* arg2 */
++ env->active_tc.gpr[8], /* arg3 */
++ env->active_tc.gpr[9], /* arg4 */
++ env->active_tc.gpr[10],/* arg5 */
++ env->active_tc.gpr[11],/* arg6 */
++ 0 /* no arg 7 */);
++ } else {
++ ret = do_freebsd_syscall(env,
++ syscall_num,
++ env->active_tc.gpr[4],
++ env->active_tc.gpr[5],
++ env->active_tc.gpr[6],
++ env->active_tc.gpr[7],
++ env->active_tc.gpr[8],
++ env->active_tc.gpr[9],
++ env->active_tc.gpr[10],
++ env->active_tc.gpr[11]
++ );
++
++#else /* ! TARGET_MIPS64 */
++ /* indirect syscall */
++ ret = do_freebsd_syscall(env,
++ env->active_tc.gpr[4],/* syscall #*/
++ env->active_tc.gpr[5], /* a1/arg0 */
++ env->active_tc.gpr[6], /* a2/arg1 */
++ env->active_tc.gpr[7], /* a3/arg2 */
++ env->active_tc.gpr[12],/* t4/arg3 */
++ env->active_tc.gpr[13],/* t5/arg4 */
++ env->active_tc.gpr[14],/* t6/arg5 */
++ env->active_tc.gpr[15],/* t7/arg6 */
++ 0 /* no arg7 */ );
++ } else {
++ /* direct syscall */
++ ret = do_freebsd_syscall(env,
++ syscall_num,
++ env->active_tc.gpr[4], /* a0/arg0 */
++ env->active_tc.gpr[5], /* a1/arg1 */
++ env->active_tc.gpr[6], /* a2/arg2 */
++ env->active_tc.gpr[7], /* a3/arg3 */
++ env->active_tc.gpr[12],/* t4/arg4 */
++ env->active_tc.gpr[13],/* t5/arg5 */
++ env->active_tc.gpr[14],/* t6/arg6 */
++ env->active_tc.gpr[15] /* t7/arg7 */
++ );
++#endif /* ! TARGET_MIPS64 */
++ }
++ }
++/* done_syscall: */
++ if (-TARGET_QEMU_ESIGRETURN == ret) {
++ /*
++ * Returning from a successful sigreturn
++ * syscall. Avoid clobbering register state.
++ */
++ break;
++ }
++ if ((unsigned int)ret >= (unsigned int)(-1133)) {
++ env->active_tc.gpr[7] = 1;
++ ret = -ret;
++ } else {
++ env->active_tc.gpr[7] = 0;
++ }
++ env->active_tc.gpr[2] = ret; /* v0 <- ret */
++ break;
++
++ case EXCP_TLBL: /* TLB miss on load */
++ case EXCP_TLBS: /* TLB miss on store */
++ case EXCP_AdEL: /* bad address on load */
++ case EXCP_AdES: /* bad address on store */
++ info.si_signo = TARGET_SIGSEGV;
++ info.si_errno = 0;
++ /* XXX: check env->error_code */
++ info.si_code = TARGET_SEGV_MAPERR;
++ info.si_addr = env->CP0_BadVAddr;
++ queue_signal(env, info.si_signo, &info);
++ break;
++
++ case EXCP_CpU: /* coprocessor unusable */
++ case EXCP_RI: /* reserved instruction */
++ info.si_signo = TARGET_SIGILL;
++ info.si_errno = 0;
++ info.si_code = 0;
++ queue_signal(env, info.si_signo, &info);
++ break;
++
++ case EXCP_INTERRUPT: /* async interrupt */
++ /* just indicate that signals should be handled asap */
++ break;
++
++ case EXCP_DEBUG: /* cpu stopped after a breakpoint */
++ {
++ int sig;
++
++ sig = gdb_handlesig(env, TARGET_SIGTRAP);
++ if (sig) {
++ info.si_signo = sig;
++ info.si_errno = 0;
++ info.si_code = TARGET_TRAP_BRKPT;
++ queue_signal(env, info.si_signo, &info);
++ }
++ }
++ break;
++
++ case EXCP_SC:
++ if (do_store_exclusive(env)) {
++ info.si_signo = TARGET_SIGSEGV;
++ info.si_errno = 0;
++ info.si_code = TARGET_SEGV_MAPERR;
++ info.si_addr = env->active_tc.PC;
++ queue_signal(env, info.si_signo, &info);
++ }
++ break;
++
++ default:
++ fprintf(stderr, "qemu: unhandled CPU exception "
++ "0x%x - aborting\n", trapnr);
++ cpu_dump_state(env, stderr, fprintf, 0);
++ abort();
++ }
++ process_pending_signals(env);
++ }
++}
++#endif /* defined(TARGET_MIPS) */
++
+ #ifdef TARGET_SPARC
+ #define SPARC64_STACK_BIAS 2047
+
+@@ -969,6 +1206,15 @@ static void usage(void)
+
+ THREAD CPUArchState *thread_env;
+
++void stop_all_tasks(void)
++{
++ /*
++ * We trust when using NPTL (pthreads) start_exclusive() handles thread
++ * stopping correctly.
++ */
++ start_exclusive();
++}
++
+ /* Assumes contents are already zeroed. */
+ void init_task_state(TaskState *ts)
+ {
+@@ -990,6 +1236,7 @@ int main(int argc, char **argv)
+ const char *log_mask = NULL;
+ struct target_pt_regs regs1, *regs = &regs1;
+ struct image_info info1, *info = &info1;
++ struct bsd_binprm bprm;
+ TaskState ts1, *ts = &ts1;
+ CPUArchState *env;
+ int optind;
+@@ -997,7 +1244,11 @@ int main(int argc, char **argv)
+ int gdbstub_port = 0;
+ char **target_environ, **wrk;
+ envlist_t *envlist = NULL;
++#ifdef __FreeBSD__
++ bsd_type = target_freebsd;
++#else
+ bsd_type = target_openbsd;
++#endif
+
+ if (argc <= 1)
+ usage();
+@@ -1141,6 +1392,8 @@ int main(int argc, char **argv)
+ /* Zero out image_info */
+ memset(info, 0, sizeof(struct image_info));
+
++ memset(&bprm, 0, sizeof(bprm));
++
+ /* Scan interp_prefix dir for replacement files. */
+ init_paths(interp_prefix);
+
+@@ -1151,6 +1404,12 @@ int main(int argc, char **argv)
+ #else
+ cpu_model = "qemu32";
+ #endif
++#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
++#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
++ cpu_model = "20Kc";
++#else
++ cpu_model = "24Kf";
++#endif
+ #elif defined(TARGET_SPARC)
+ #ifdef TARGET_SPARC64
+ cpu_model = "TI UltraSparc II";
+@@ -1211,7 +1470,8 @@ int main(int argc, char **argv)
+ }
+ #endif /* CONFIG_USE_GUEST_BASE */
+
+- if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) {
++ if (loader_exec(filename, argv+optind, target_environ, regs, info,
++ &bprm)!= 0) {
+ printf("Error loading %s\n", filename);
+ _exit(1);
+ }
+@@ -1256,6 +1516,7 @@ int main(int argc, char **argv)
+ memset(ts, 0, sizeof(TaskState));
+ init_task_state(ts);
+ ts->info = info;
++ ts->bprm = &bprm;
+ env->opaque = ts;
+
+ #if defined(TARGET_I386)
+@@ -1394,6 +1655,20 @@ int main(int argc, char **argv)
+ env->regs[i] = regs->uregs[i];
+ }
+ }
++#elif defined(TARGET_MIPS)
++ {
++ int i;
++ for(i = 0; i < 32; i++) {
++ env->active_tc.gpr[i] = regs->regs[i];
++ }
++ env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1;
++ if (regs->cp0_epc & 1) {
++ env->hflags |= MIPS_HFLAG_M16;
++ }
++#if defined(TARGET_MIPS64)
++ env->hflags |= MIPS_HFLAG_UX;
++#endif
++ }
+ #else
+ #error unsupported target CPU
+ #endif
+diff --git a/bsd-user/mips/syscall.h b/bsd-user/mips/syscall.h
+new file mode 100644
+index 0000000..8923556
+--- /dev/null
++++ b/bsd-user/mips/syscall.h
+@@ -0,0 +1,21 @@
++
++/* this struct defines the way the registers are stored on the
++ stack during a system call. */
++
++struct target_pt_regs {
++ /* Pad bytes for argument save space on the stack. */
++ abi_ulong pad0[6];
++
++ /* Saved main processor registers. */
++ abi_ulong regs[32];
++
++ /* Saved special registers. */
++ abi_ulong cp0_status;
++ abi_ulong lo;
++ abi_ulong hi;
++ abi_ulong cp0_badvaddr;
++ abi_ulong cp0_cause;
++ abi_ulong cp0_epc;
++};
++
++#define UNAME_MACHINE "mips"
+diff --git a/bsd-user/mips/target_signal.h b/bsd-user/mips/target_signal.h
+new file mode 100644
+index 0000000..28871c3
+--- /dev/null
++++ b/bsd-user/mips/target_signal.h
+@@ -0,0 +1,14 @@
++#ifndef TARGET_SIGNAL_H
++#define TARGET_SIGNAL_H
++
++#include "cpu.h"
++
++#define TARGET_MINSIGSTKSZ (512 * 4)
++#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
++
++static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state)
++{
++ return state->active_tc.gpr[29];
++}
++
++#endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/mips/target_vmparam.h b/bsd-user/mips/target_vmparam.h
+new file mode 100644
+index 0000000..9fca7f3
+--- /dev/null
++++ b/bsd-user/mips/target_vmparam.h
+@@ -0,0 +1,30 @@
++#ifndef _TARGET_VMPARAM_H_
++#define _TARGET_VMPARAM_H_
++
++#if defined(__FreeBSD__)
++#define TARGET_VM_MINUSER_ADDRESS (0x00000000)
++#define TARGET_VM_MAXUSER_ADDRESS (0x80000000)
++
++#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
++
++struct target_ps_strings {
++ abi_ulong ps_argvstr;
++ uint32_t ps_nargvstr;
++ abi_ulong ps_envstr;
++ uint32_t ps_nenvstr;
++};
++
++#define TARGET_SPACE_USRSPACE 4096
++#define TARGET_ARG_MAX 262144
++
++#define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
++
++#define TARGET_SZSIGCODE 0
++
++#else
++
++#define TARGET_USRSTACK 0
++#endif
++
++
++#endif /* _TARGET_VMPARAM_H_ */
+diff --git a/bsd-user/mips64/syscall.h b/bsd-user/mips64/syscall.h
+new file mode 100644
+index 0000000..fca3634
+--- /dev/null
++++ b/bsd-user/mips64/syscall.h
+@@ -0,0 +1,21 @@
++
++/* this struct defines the way the registers are stored on the
++ stack during a system call. */
++
++struct target_pt_regs {
++ /* Saved main processor registers. */
++ abi_ulong regs[32];
++
++ /* Saved special registers. */
++ abi_ulong cp0_status;
++ abi_ulong lo;
++ abi_ulong hi;
++ abi_ulong cp0_badvaddr;
++ abi_ulong cp0_cause;
++ abi_ulong cp0_epc;
++};
++
++/* Nasty hack: define a fake errno value for use by sigreturn. */
++#define TARGET_QEMU_ESIGRETURN 255
++
++#define UNAME_MACHINE "mips64"
+diff --git a/bsd-user/mips64/target_signal.h b/bsd-user/mips64/target_signal.h
+new file mode 100644
+index 0000000..d671f4e
+--- /dev/null
++++ b/bsd-user/mips64/target_signal.h
+@@ -0,0 +1,17 @@
++#ifndef TARGET_SIGNAL_H
++#define TARGET_SIGNAL_H
++
++#include "cpu.h"
++
++#define TARGET_MINSIGSTKSZ (512 * 4)
++#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
++#define TARGET_SZSIGCODE 16
++
++#define TARGET_UCONTEXT_MAGIC 0xACEDBADE
++
++static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state)
++{
++ return state->active_tc.gpr[29];
++}
++
++#endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/mips64/target_vmparam.h b/bsd-user/mips64/target_vmparam.h
+new file mode 100644
+index 0000000..47c2267
+--- /dev/null
++++ b/bsd-user/mips64/target_vmparam.h
+@@ -0,0 +1,28 @@
++#ifndef _TARGET_VMPARAM_H_
++#define _TARGET_VMPARAM_H_
++
++#if defined(__FreeBSD__)
++
++#define TARGET_VM_MINUSER_ADDRESS (0x0000000000000000UL)
++#define TARGET_VM_MAXUSER_ADDRESS (0x0000008000000000UL)
++
++#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
++
++struct target_ps_strings {
++ abi_ulong ps_argvstr;
++ uint32_t ps_nargvstr;
++ abi_ulong ps_envstr;
++ uint32_t ps_nenvstr;
++};
++
++#define TARGET_SPACE_USRSPACE 4096
++#define TARGET_ARG_MAX 262144
++
++#define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
++
++#else
++
++#define TARGET_USRSTACK 0
++#endif
++
++#endif /* _TARGET_VMPARAM_H_ */
+diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
+index 5d6cffc..9f42c27 100644
+--- a/bsd-user/mmap.c
++++ b/bsd-user/mmap.c
+@@ -275,7 +275,8 @@ unsigned long last_brk;
+ */
+ /* page_init() marks pages used by the host as reserved to be sure not
+ to use them. */
+-static abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
++abi_ulong
++mmap_find_vma(abi_ulong start, abi_ulong size)
+ {
+ abi_ulong addr, addr1, addr_start;
+ int prot;
+@@ -493,7 +494,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
+ int prot, ret;
+
+ #ifdef DEBUG_MMAP
+- printf("munmap: start=0x%lx len=0x%lx\n", start, len);
++ printf("munmap: start=0x" TARGET_FMT_lx " len=0x" TARGET_FMT_lx "\n", start, len);
+ #endif
+ if (start & ~TARGET_PAGE_MASK)
+ return -EINVAL;
+diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
+--- a/bsd-user/qemu.h
++++ b/bsd-user/qemu.h
+@@ -20,9 +20,13 @@ enum BSDType {
+ };
+ extern enum BSDType bsd_type;
+
++abi_long memcpy_to_target(abi_ulong dest, const void *src,
++ unsigned long len);
++
+ #include "syscall_defs.h"
+ #include "syscall.h"
++#include "target_vmparam.h"
+ #include "target_signal.h"
+ #include "exec/gdbstub.h"
+
+ #if defined(CONFIG_USE_NPTL)
+@@ -61,7 +65,7 @@ struct image_info {
+
+ struct sigqueue {
+ struct sigqueue *next;
+- //target_siginfo_t info;
++ target_siginfo_t info;
+ };
+
+ struct emulated_sigtable {
+@@ -88,6 +92,7 @@ typedef struct TaskState {
+ uint32_t stack_base;
+ #endif
+ struct image_info *info;
++ struct bsd_binprm *bprm;
+
+ struct emulated_sigtable sigtab[TARGET_NSIG];
+ struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
+@@ -98,6 +103,8 @@ typedef struct TaskState {
+ } __attribute__((aligned(16))) TaskState;
+
+ void init_task_state(TaskState *ts);
++void task_settid(TaskState *);
++void stop_all_tasks(void);
+ extern const char *qemu_uname_release;
+ #if defined(CONFIG_USE_GUEST_BASE)
+ extern unsigned long mmap_min_addr;
+@@ -115,7 +122,7 @@ extern unsigned long mmap_min_addr;
+ * This structure is used to hold the arguments that are
+ * used when loading binaries.
+ */
+-struct linux_binprm {
++struct bsd_binprm {
+ char buf[128];
+ void *page[MAX_ARG_PAGES];
+ abi_ulong p;
+@@ -125,21 +132,21 @@ struct linux_binprm {
+ char **argv;
+ char **envp;
+ char * filename; /* Name of binary */
++ int (*core_dump)(int, const CPUArchState *); /* coredump routine */
+ };
+
+ void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
+ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
+ abi_ulong stringp, int push_ptr);
+ int loader_exec(const char * filename, char ** argv, char ** envp,
+- struct target_pt_regs * regs, struct image_info *infop);
++ struct target_pt_regs * regs, struct image_info *infop,
++ struct bsd_binprm *);
+
+-int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
++int load_elf_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs,
+ struct image_info * info);
+-int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
++int load_flt_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs,
+ struct image_info * info);
+
+-abi_long memcpy_to_target(abi_ulong dest, const void *src,
+- unsigned long len);
+ void target_set_brk(abi_ulong new_brk);
+ abi_long do_brk(abi_ulong new_brk);
+ void syscall_init(void);
+@@ -184,10 +191,12 @@ extern int do_strace;
+ /* signal.c */
+ void process_pending_signals(CPUArchState *cpu_env);
+ void signal_init(void);
+-//int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
+-//void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
+-//void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
+-long do_sigreturn(CPUArchState *env);
++int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
++void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
++void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
++int target_to_host_signal(int sig);
++int host_to_target_signal(int sig);
++long do_sigreturn(CPUArchState *env, abi_ulong uc_addr);
+ long do_rt_sigreturn(CPUArchState *env);
+ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
+
+@@ -203,6 +212,7 @@ int target_msync(abi_ulong start, abi_ul
+ extern unsigned long last_brk;
+ void mmap_lock(void);
+ void mmap_unlock(void);
++abi_ulong mmap_find_vma(abi_ulong, abi_ulong);
+ void cpu_list_lock(void);
+ void cpu_list_unlock(void);
+ #if defined(CONFIG_USE_NPTL)
+diff --git a/bsd-user/signal.c b/bsd-user/signal.c
+index 445f69e..0502a6a 100644
+--- a/bsd-user/signal.c
++++ b/bsd-user/signal.c
+@@ -2,6 +2,7 @@
+ * Emulation of BSD signals
+ *
+ * Copyright (c) 2003 - 2008 Fabrice Bellard
++ * Copyright (c) 2012 Stacey Son
+ *
+ * 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
+@@ -23,16 +24,1218 @@
+ #include <unistd.h>
+ #include <signal.h>
+ #include <errno.h>
++#include <sys/types.h>
++#include <sys/time.h>
++#include <sys/resource.h>
+
+ #include "qemu.h"
+ #include "target_signal.h"
+
+-//#define DEBUG_SIGNAL
++// #define DEBUG_SIGNAL
+
+-void signal_init(void)
++#ifndef _NSIG
++#define _NSIG 128
++#endif
++
++static target_stack_t target_sigaltstack_used = {
++ .ss_sp = 0,
++ .ss_size = 0,
++ .ss_flags = TARGET_SS_DISABLE,
++};
++
++static uint8_t host_to_target_signal_table[_NSIG] = {
++ [SIGHUP] = TARGET_SIGHUP,
++ [SIGINT] = TARGET_SIGINT,
++ [SIGQUIT] = TARGET_SIGQUIT,
++ [SIGILL] = TARGET_SIGILL,
++ [SIGTRAP] = TARGET_SIGTRAP,
++ [SIGABRT] = TARGET_SIGABRT,
++ /* [SIGIOT] = TARGET_SIGIOT, */
++ [SIGEMT] = TARGET_SIGEMT,
++ [SIGFPE] = TARGET_SIGFPE,
++ [SIGKILL] = TARGET_SIGKILL,
++ [SIGBUS] = TARGET_SIGBUS,
++ [SIGSEGV] = TARGET_SIGSEGV,
++ [SIGSYS] = TARGET_SIGSYS,
++ [SIGPIPE] = TARGET_SIGPIPE,
++ [SIGALRM] = TARGET_SIGALRM,
++ [SIGTERM] = TARGET_SIGTERM,
++ [SIGURG] = TARGET_SIGURG,
++ [SIGSTOP] = TARGET_SIGSTOP,
++ [SIGTSTP] = TARGET_SIGTSTP,
++ [SIGCONT] = TARGET_SIGCONT,
++ [SIGCHLD] = TARGET_SIGCHLD,
++ [SIGTTIN] = TARGET_SIGTTIN,
++ [SIGTTOU] = TARGET_SIGTTOU,
++ [SIGIO] = TARGET_SIGIO,
++ [SIGXCPU] = TARGET_SIGXCPU,
++ [SIGXFSZ] = TARGET_SIGXFSZ,
++ [SIGVTALRM] = TARGET_SIGVTALRM,
++ [SIGPROF] = TARGET_SIGPROF,
++ [SIGWINCH] = TARGET_SIGWINCH,
++ [SIGINFO] = TARGET_SIGINFO,
++ [SIGUSR1] = TARGET_SIGUSR1,
++ [SIGUSR2] = TARGET_SIGUSR2,
++#ifdef SIGTHR
++ [SIGTHR] = TARGET_SIGTHR,
++#endif
++ /* [SIGLWP] = TARGET_SIGLWP, */
++#ifdef SIGLIBRT
++ [SIGLIBRT] = TARGET_SIGLIBRT,
++#endif
++
++ /*
++ * The following signals stay the same.
++ * Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
++ * host libpthread signals. This assumes no one actually uses
++ * SIGRTMAX. To fix this properly we need to manual signal delivery
++ * multiplexed over a single host signal.
++ */
++ [SIGRTMIN] = SIGRTMAX,
++ [SIGRTMAX] = SIGRTMIN,
++};
++
++static uint8_t target_to_host_signal_table[_NSIG];
++
++static struct target_sigaction sigact_table[TARGET_NSIG];
++
++static void host_signal_handler(int host_signum, siginfo_t *info, void *puc);
++
++static inline int
++on_sig_stack(unsigned long sp)
++{
++ return (sp - target_sigaltstack_used.ss_sp
++ < target_sigaltstack_used.ss_size);
++}
++
++static inline int
++sas_ss_flags(unsigned long sp)
++{
++ return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
++ : on_sig_stack(sp) ? SS_ONSTACK : 0);
++}
++
++int
++host_to_target_signal(int sig)
++{
++
++ if (sig >= _NSIG)
++ return (sig);
++ return (host_to_target_signal_table[sig]);
++}
++
++int
++target_to_host_signal(int sig)
++{
++
++ if (sig >= _NSIG)
++ return (sig);
++ return (target_to_host_signal_table[sig]);
++}
++
++static inline void
++target_sigemptyset(target_sigset_t *set)
+ {
++ memset(set, 0, sizeof(*set));
+ }
+
+-void process_pending_signals(CPUArchState *cpu_env)
++static inline void
++target_sigaddset(target_sigset_t *set, int signum)
+ {
++ signum--;
++ uint32_t mask = (uint32_t)1 << (signum % TARGET_NSIG_BPW);
++ set->__bits[signum / TARGET_NSIG_BPW] |= mask;
++}
++
++static inline int
++target_sigismember(const target_sigset_t *set, int signum)
++{
++ signum--;
++ abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
++ return ((set->__bits[signum / TARGET_NSIG_BPW] & mask) != 0);
++}
++
++static void
++host_to_target_sigset_internal(target_sigset_t *d, const sigset_t *s)
++{
++ int i;
++
++ target_sigemptyset(d);
++ for (i = 1; i <= TARGET_NSIG; i++) {
++ if (sigismember(s, i)) {
++ target_sigaddset(d, host_to_target_signal(i));
++ }
++ }
++}
++
++void
++host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
++{
++ target_sigset_t d1;
++ int i;
++
++ host_to_target_sigset_internal(&d1, s);
++ for(i = 0;i < TARGET_NSIG_WORDS; i++)
++ d->__bits[i] = tswap32(d1.__bits[i]);
++}
++
++static void
++target_to_host_sigset_internal(sigset_t *d, const target_sigset_t *s)
++{
++ int i;
++
++ sigemptyset(d);
++ for (i = 1; i <= TARGET_NSIG; i++) {
++ if (target_sigismember(s, i)) {
++ sigaddset(d, target_to_host_signal(i));
++ }
++ }
++}
++
++void
++target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
++{
++ target_sigset_t s1;
++ int i;
++
++ for(i = 0; i < TARGET_NSIG_WORDS; i++)
++ s1.__bits[i] = tswap32(s->__bits[i]);
++ target_to_host_sigset_internal(d, &s1);
++}
++
++/* Siginfo conversion. */
++static inline void
++host_to_target_siginfo_noswap(target_siginfo_t *tinfo, const siginfo_t *info)
++{
++ int sig;
++
++ sig = host_to_target_signal(info->si_signo);
++ tinfo->si_signo = sig;
++ tinfo->si_errno = info->si_errno;
++ tinfo->si_code = info->si_code;
++ tinfo->si_pid = info->si_pid;
++ tinfo->si_uid = info->si_uid;
++ tinfo->si_addr = (abi_ulong)(unsigned long)info->si_addr;
++ /* si_value is opaque to kernel */
++ tinfo->si_value.sival_ptr =
++ (abi_ulong)(unsigned long)info->si_value.sival_ptr;
++ if (SIGILL == sig || SIGFPE == sig || SIGSEGV == sig ||
++ SIGBUS == sig || SIGTRAP == sig) {
++ tinfo->_reason._fault._trapno = info->_reason._fault._trapno;
++#ifdef SIGPOLL
++ } else if (SIGPOLL == sig) {
++ tinfo->_reason._poll._band = info->_reason._poll._band;
++#endif
++ } else {
++ tinfo->_reason._timer._timerid = info->_reason._timer._timerid;
++ tinfo->_reason._timer._overrun = info->_reason._timer._overrun;
++ }
++}
++
++static void
++tswap_siginfo(target_siginfo_t *tinfo, const target_siginfo_t *info)
++{
++ int sig;
++ sig = info->si_signo;
++ tinfo->si_signo = tswap32(sig);
++ tinfo->si_errno = tswap32(info->si_errno);
++ tinfo->si_code = tswap32(info->si_code);
++ tinfo->si_pid = tswap32(info->si_pid);
++ tinfo->si_uid = tswap32(info->si_uid);
++ tinfo->si_addr = tswapal(info->si_addr);
++ if (SIGILL == sig || SIGFPE == sig || SIGSEGV == sig ||
++ SIGBUS == sig || SIGTRAP == sig) {
++ tinfo->_reason._fault._trapno =
++ tswap32(info->_reason._fault._trapno);
++#ifdef SIGPOLL
++ } else if (SIGPOLL == sig) {
++ tinfo->_reason._poll._band = tswap32(info->_reason._poll._band);
++#endif
++ } else {
++ tinfo->_reason._timer._timerid =
++ tswap32(info->_reason._timer._timerid);
++ tinfo->_reason._timer._overrun =
++ tswap32(info->_reason._timer._overrun);
++ }
++}
++
++void
++host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
++{
++
++ host_to_target_siginfo_noswap(tinfo, info);
++ tswap_siginfo(tinfo, tinfo);
++}
++
++/* Returns 1 if given signal should dump core if not handled. */
++static int
++core_dump_signal(int sig)
++{
++ switch (sig) {
++ case TARGET_SIGABRT:
++ case TARGET_SIGFPE:
++ case TARGET_SIGILL:
++ case TARGET_SIGQUIT:
++ case TARGET_SIGSEGV:
++ case TARGET_SIGTRAP:
++ case TARGET_SIGBUS:
++ return (1);
++ default:
++ return (0);
++ }
++}
++
++/* Signal queue handling. */
++static inline struct sigqueue *
++alloc_sigqueue(CPUArchState *env)
++{
++ TaskState *ts = env->opaque;
++ struct sigqueue *q = ts->first_free;
++
++ if (!q)
++ return (NULL);
++ ts->first_free = q->next;
++ return (q);
++}
++
++static inline void
++free_sigqueue(CPUArchState *env, struct sigqueue *q)
++{
++
++ TaskState *ts = env->opaque;
++ q->next = ts->first_free;
++ ts->first_free = q;
++}
++
++/* Abort execution with signal. */
++static void QEMU_NORETURN
++force_sig(int target_sig)
++{
++ TaskState *ts = (TaskState *)thread_env->opaque;
++ int host_sig, core_dumped = 0;
++ struct sigaction act;
++
++ host_sig = target_to_host_signal(target_sig);
++ gdb_signalled(thread_env, target_sig);
++
++ /* Dump core if supported by target binary format */
++ if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
++ stop_all_tasks();
++ core_dumped =
++ ((*ts->bprm->core_dump)(target_sig, thread_env) == 0);
++ }
++ if (core_dumped) {
++ struct rlimit nodump;
++
++ /*
++ * We already dumped the core of target process, we don't want
++ * a coredump of qemu itself.
++ */
++ getrlimit(RLIMIT_CORE, &nodump);
++ nodump.rlim_cur = 0;
++ (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) "
++ "- %s\n", target_sig, strsignal(host_sig), "core dumped");
++ }
++
++ /*
++ * The proper exit code for dying from an uncaught signal is
++ * -<signal>. The kernel doesn't allow exit() or _exit() to pass
++ * a negative value. To get the proper exit code we need to
++ * actually die from an uncaught signal. Here the default signal
++ * handler is installed, we send ourself a signal and we wait for
++ * it to arrive.
++ */
++ memset(&act, 0, sizeof(act));
++ sigfillset(&act.sa_mask);
++ act.sa_handler = SIG_DFL;
++ sigaction(host_sig, &act, NULL);
++
++ kill(getpid(), host_sig);
++
++ /*
++ * Make sure the signal isn't masked (just reuse the mask inside
++ * of act).
++ */
++ sigdelset(&act.sa_mask, host_sig);
++ sigsuspend(&act.sa_mask);
++
++ /* unreachable */
++ abort();
++}
++
++/*
++ * Queue a signal so that it will be send to the virtual CPU as soon as
++ * possible.
++ */
++int
++queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
++{
++ TaskState *ts = env->opaque;
++ struct emulated_sigtable *k;
++ struct sigqueue *q, **pq;
++ abi_ulong handler;
++ int queue;
++
++ k = &ts->sigtab[sig - 1];
++ queue = gdb_queuesig ();
++ handler = sigact_table[sig - 1]._sa_handler;
++#ifdef DEBUG_SIGNAL
++ fprintf(stderr, "queue_signal: sig=%d handler=0x%lx flags=0x%x\n", sig,
++ handler, (uint32_t)sigact_table[sig - 1].sa_flags);
++#endif
++ if (!queue && (TARGET_SIG_DFL == handler)) {
++ if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN ||
++ sig == TARGET_SIGTTOU) {
++ kill(getpid(), SIGSTOP);
++ return (0);
++ } else {
++ if (sig != TARGET_SIGCHLD &&
++ sig != TARGET_SIGURG &&
++ sig != TARGET_SIGWINCH &&
++ sig != TARGET_SIGCONT) {
++ force_sig(sig);
++ } else {
++ return (0); /* The signal was ignored. */
++ }
++ }
++ } else if (!queue && (TARGET_SIG_IGN == handler)) {
++ return (0); /* Ignored signal. */
++ } else if (!queue && (TARGET_SIG_ERR == handler)) {
++ force_sig(sig);
++ } else {
++ pq = &k->first;
++
++ /*
++ * FreeBSD signals are always queued.
++ * Linux only queues real time signals.
++ * XXX this code is not thread safe.
++ */
++ if (!k->pending) {
++ /* first signal */
++ q = &k->info;
++ } else {
++ q = alloc_sigqueue(env);
++ if (!q)
++ return (-EAGAIN);
++ while (*pq != NULL)
++ pq = &(*pq)->next;
++ }
++ *pq = q;
++ q->info = *info;
++ q->next = NULL;
++ k->pending = 1;
++ /* Signal that a new signal is pending. */
++ ts->signal_pending = 1;
++ return (1); /* Indicates that the signal was queued. */
++ }
++}
++
++static void
++host_signal_handler(int host_signum, siginfo_t *info, void *puc)
++{
++ int sig;
++ target_siginfo_t tinfo;
++
++ /*
++ * The CPU emulator uses some host signal to detect exceptions so
++ * we forward to it some signals.
++ */
++ if ((host_signum == SIGSEGV || host_signum == SIGBUS) &&
++ info->si_code > 0) {
++ if (cpu_signal_handler(host_signum, info, puc))
++ return;
++ }
++
++ /* Get the target signal number. */
++ sig = host_to_target_signal(host_signum);
++ if (sig < 1 || sig > TARGET_NSIG)
++ return;
++#ifdef DEBUG_SIGNAL
++ fprintf(stderr, "qemu: got signal %d\n", sig);
++#endif
++ host_to_target_siginfo_noswap(&tinfo, info);
++ if (queue_signal(thread_env, sig, &tinfo) == 1) {
++ /* Interrupt the virtual CPU as soon as possible. */
++ cpu_exit(thread_env);
++ }
++}
++
++/* do_sigaltstack() returns target values and errnos. */
++/* compare to kern/kern_sig.c sys_sigaltstack() and kern_sigaltstack() */
++abi_long
++do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
++{
++ int ret = 0;
++ target_stack_t ss, oss, *uss;
++
++ if (uoss_addr) {
++ /* Save current signal stack params */
++ oss.ss_sp = tswapl(target_sigaltstack_used.ss_sp);
++ oss.ss_size = tswapl(target_sigaltstack_used.ss_size);
++ oss.ss_flags = tswapl(sas_ss_flags(sp));
++ }
++
++ if (uss_addr) {
++
++ if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1) ||
++ __get_user(ss.ss_sp, &uss->ss_sp) ||
++ __get_user(ss.ss_size, &uss->ss_size) ||
++ __get_user(ss.ss_flags, &uss->ss_flags)) {
++ ret = -TARGET_EFAULT;
++ goto out;
++ }
++ unlock_user_struct(uss, uss_addr, 0);
++
++ if (on_sig_stack(sp)) {
++ ret = -TARGET_EPERM;
++ goto out;
++ }
++
++ if ((ss.ss_flags & ~TARGET_SS_DISABLE) != 0) {
++ ret = -TARGET_EINVAL;
++ goto out;
++ }
++
++ if (!(ss.ss_flags & ~TARGET_SS_DISABLE)) {
++ if (ss.ss_size < TARGET_MINSIGSTKSZ) {
++ ret = -TARGET_ENOMEM;
++ goto out;
++ }
++ } else {
++ ss.ss_size = 0;
++ ss.ss_sp = 0;
++ }
++
++ target_sigaltstack_used.ss_sp = ss.ss_sp;
++ target_sigaltstack_used.ss_size = ss.ss_size;
++ }
++
++ if (uoss_addr) {
++ /* Copy out to user saved signal stack params */
++ if (copy_to_user(uoss_addr, &oss, sizeof(oss))) {
++ ret = -TARGET_EFAULT;
++ goto out;
++ }
++ }
++
++out:
++ return (ret);
++}
++
++static int
++fatal_signal(int sig)
++{
++
++ switch (sig) {
++ case TARGET_SIGCHLD:
++ case TARGET_SIGURG:
++ case TARGET_SIGWINCH:
++ /* Ignored by default. */
++ return (0);
++ case TARGET_SIGCONT:
++ case TARGET_SIGSTOP:
++ case TARGET_SIGTSTP:
++ case TARGET_SIGTTIN:
++ case TARGET_SIGTTOU:
++ /* Job control signals. */
++ return (0);
++ default:
++ return (1);
++ }
++}
++
++/* do_sigaction() return host values and errnos */
++int
++do_sigaction(int sig, const struct target_sigaction *act,
++ struct target_sigaction *oact)
++{
++ struct target_sigaction *k;
++ struct sigaction act1;
++ int host_sig;
++ int ret = 0;
++
++ if (sig < 1 || sig > TARGET_NSIG || TARGET_SIGKILL == sig ||
++ TARGET_SIGSTOP == sig)
++ return (-EINVAL);
++ k = &sigact_table[sig - 1];
++#if defined(DEBUG_SIGNAL)
++ fprintf(stderr, "do_sigaction sig=%d act=%p, oact=%p\n",
++ sig, act, oact);
++#endif
++ if (oact) {
++ oact->_sa_handler = tswapal(k->_sa_handler);
++ oact->sa_flags = tswap32(k->sa_flags);
++ oact->sa_mask = k->sa_mask;
++ }
++ if (act) {
++ /* XXX: this is most likely not threadsafe. */
++ k->_sa_handler = tswapal(act->_sa_handler);
++ k->sa_flags = tswap32(act->sa_flags);
++ k->sa_mask = act->sa_mask;
++
++ /* Update the host signal state. */
++ host_sig = target_to_host_signal(sig);
++ if (host_sig != SIGSEGV && host_sig != SIGBUS) {
++ memset(&act1, 0, sizeof(struct sigaction));
++ sigfillset(&act1.sa_mask);
++ if (k->sa_flags & TARGET_SA_RESTART)
++ act1.sa_flags |= SA_RESTART;
++ /*
++ * Note: It is important to update the host kernel
++ * signal mask to avoid getting unexpected interrupted
++ * system calls.
++ */
++ if (k->_sa_handler == TARGET_SIG_IGN) {
++ act1.sa_sigaction = (void *)SIG_IGN;
++ } else if (k->_sa_handler == TARGET_SIG_DFL) {
++ if (fatal_signal(sig))
++ act1.sa_sigaction =
++ host_signal_handler;
++ else
++ act1.sa_sigaction = (void *)SIG_DFL;
++ } else {
++ act1.sa_flags = SA_SIGINFO;
++ act1.sa_sigaction = host_signal_handler;
++ }
++ ret = sigaction(host_sig, &act1, NULL);
++#if defined(DEBUG_SIGNAL)
++ fprintf(stderr, "sigaction (action = %p (host_signal_handler = %p)) returned: %d\n", act1.sa_sigaction, host_signal_handler, ret);
++#endif
++ }
++ }
++ return (ret);
++}
++
++#if defined(TARGET_MIPS64)
++static inline int
++restore_sigmcontext(CPUMIPSState *regs, target_mcontext_t *mc)
++{
++ int i, err = 0;
++
++ for(i = 1; i < 32; i++)
++ err |= __get_user(regs->active_tc.gpr[i],
++ &mc->mc_regs[i]);
++ err |= __get_user(regs->CP0_EPC, &mc->mc_pc);
++ err |= __get_user(regs->active_tc.LO[0], &mc->mullo);
++ err |= __get_user(regs->active_tc.HI[0], &mc->mulhi);
++ err |= __get_user(regs->tls_value, &mc->mc_tls); /* XXX thread tls */
++
++#if 0 /* XXX */
++ int used_fp = 0;
++
++ err |= __get_user(used_fp, &mc->mc_fpused);
++ conditional_used_math(used_fp);
++
++ preempt_disabled();
++ if (used_math()) {
++ /* restore fpu context if we have used it before */
++ own_fpu();
++ err |= restore_fp_context(mc);
++ } else {
++ /* signal handler may have used FPU. Give it up. */
++ lose_fpu();
++ }
++ preempt_enable();
++#endif
++
++ return (err);
++}
++
++static inline int
++setup_sigmcontext(CPUMIPSState *regs, target_mcontext_t *mc, int32_t oonstack)
++{
++ int i, err = 0;
++ abi_long ucontext_magic = TARGET_UCONTEXT_MAGIC;
++
++ err = __put_user(oonstack ? 1 : 0, &mc->mc_onstack);
++ err |= __put_user(regs->active_tc.PC, &mc->mc_pc);
++ err |= __put_user(regs->active_tc.LO[0], &mc->mullo);
++ err |= __put_user(regs->active_tc.HI[0], &mc->mulhi);
++ err |= __put_user(regs->tls_value, &mc->mc_tls); /* XXX thread tls */
++
++ err |= __put_user(ucontext_magic, &mc->mc_regs[0]);
++ for(i = 1; i < 32; i++)
++ err |= __put_user(regs->active_tc.gpr[i], &mc->mc_regs[i]);
++
++ err |= __put_user(0, &mc->mc_fpused);
++
++#if 0 /* XXX */
++ err |= __put_user(used_math(), &mc->mc_fpused);
++ if (used_math())
++ goto out;
++
++ /*
++ * Save FPU state to signal context. Signal handler will "inherit"
++ * current FPU state.
++ */
++ preempt_disable();
++
++ if (!is_fpu_owner()) {
++ own_fpu();
++ for(i = 0; i < 33; i++)
++ err |= __put_user(regs->active_tc.fpregs[i], &mc->mc_fpregs[i]);
++ }
++ err |= save_fp_context(fg);
++
++ preempt_enable();
++out:
++#endif
++ return (err);
++}
++
++static inline abi_ulong
++get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
++{
++ abi_ulong sp;
++
++ /* Use default user stack */
++ sp = regs->active_tc.gpr[29];
++
++ if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
++ sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
++ }
++
++ return ((sp - frame_size) & ~7);
++}
++
++/* compare to mips/mips/pm_machdep.c sendsig() */
++static void setup_frame(int sig, struct target_sigaction *ka,
++ target_sigset_t *set, CPUMIPSState *regs)
++{
++ struct target_sigframe *frame;
++ abi_ulong frame_addr;
++ int i;
++
++#ifdef DEBUG_SIGNAL
++ fprintf(stderr, "setup_frame()\n");
++#endif
++
++ frame_addr = get_sigframe(ka, regs, sizeof(*frame));
++ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
++ goto give_sigsegv;
++
++ if (setup_sigmcontext(regs, &frame->sf_uc.uc_mcontext,
++ ! on_sig_stack(frame_addr)))
++ goto give_sigsegv;
++
++ for(i = 0; i < TARGET_NSIG_WORDS; i++) {
++ if (__put_user(set->__bits[i], &frame->sf_uc.uc_sigmask.__bits[i]))
++ goto give_sigsegv;
++ }
++
++ /* fill in sigframe structure */
++ if (__put_user(sig, &frame->sf_signum))
++ goto give_sigsegv;
++ if (__put_user(0, &frame->sf_siginfo))
++ goto give_sigsegv;
++ if (__put_user(0, &frame->sf_ucontext))
++ goto give_sigsegv;
++
++ /* fill in siginfo structure */
++ if (__put_user(sig, &frame->sf_si.si_signo))
++ goto give_sigsegv;
++ if (__put_user(TARGET_SA_SIGINFO, &frame->sf_si.si_code))
++ goto give_sigsegv;
++ if (__put_user(regs->CP0_BadVAddr, &frame->sf_si.si_addr))
++ goto give_sigsegv;
++
++ /*
++ * Arguments to signal handler:
++ * a0 ($4) = signal number
++ * a1 ($5) = siginfo pointer
++ * a2 ($6) = ucontext pointer
++ * PC = signal handler pointer
++ * t9 ($25) = signal handler pointer
++ * $29 = point to sigframe struct
++ * ra ($31) = sigtramp at base of user stack
++ */
++ regs->active_tc.gpr[ 4] = sig;
++ regs->active_tc.gpr[ 5] = frame_addr +
++ offsetof(struct target_sigframe, sf_si);
++ regs->active_tc.gpr[ 6] = frame_addr +
++ offsetof(struct target_sigframe, sf_uc);
++ regs->active_tc.gpr[25] = regs->active_tc.PC = ka->_sa_handler;
++ regs->active_tc.gpr[29] = frame_addr;
++ regs->active_tc.gpr[31] = TARGET_PS_STRINGS - TARGET_SZSIGCODE;
++ unlock_user_struct(frame, frame_addr, 1);
++ return;
++
++give_sigsegv:
++ unlock_user_struct(frame, frame_addr, 1);
++ force_sig(TARGET_SIGSEGV);
++}
++
++long
++do_sigreturn(CPUMIPSState *regs, abi_ulong uc_addr)
++{
++ target_ucontext_t *ucontext;
++ sigset_t blocked;
++ target_sigset_t target_set;
++ int i;
++
++#if defined(DEBUG_SIGNAL)
++ fprintf(stderr, "do_sigreturn\n");
++#endif
++ if (!lock_user_struct(VERIFY_READ, ucontext, uc_addr, 1))
++ goto badframe;
++
++ for(i = 0; i < TARGET_NSIG_WORDS; i++) {
++ if (__get_user(target_set.__bits[i], &ucontext->uc_sigmask.__bits[i]))
++ goto badframe;
++ }
++
++ if (restore_sigmcontext(regs, &ucontext->uc_mcontext))
++ goto badframe;
++
++ target_to_host_sigset_internal(&blocked, &target_set);
++ sigprocmask(SIG_SETMASK, &blocked, NULL);
++
++ regs->active_tc.PC = regs->CP0_EPC;
++ regs->CP0_EPC = 0; /* XXX for nested signals ? */
++ return (-TARGET_QEMU_ESIGRETURN);
++
++badframe:
++ force_sig(TARGET_SIGSEGV);
++ return (0);
++}
++
++#elif defined(TARGET_SPARC64)
++
++extern abi_ulong sparc_user_sigtramp;
++
++#define mc_flags mc_global[0]
++#define mc_sp mc_out[6]
++#define mc_fprs mc_local[0]
++#define mc_fsr mc_local[1]
++#define mc_qsr mc_local[2]
++#define mc_tnpc mc_in[0]
++#define mc_tpc mc_in[1]
++#define mc_tstate mc_in[2]
++#define mc_y mc_in[4]
++#define mc_wstate mc_in[5]
++
++#define ureg_i0 regwptr[0 ]
++#define ureg_i1 regwptr[1 ]
++#define ureg_i2 regwptr[2 ]
++#define ureg_i3 regwptr[3 ]
++#define ureg_i4 regwptr[4 ]
++#define ureg_i5 regwptr[5 ]
++#define ureg_i6 regwptr[6 ]
++#define ureg_i7 regwptr[7 ]
++#define ureg_l0 regwptr[8 ]
++#define ureg_l1 regwptr[9 ]
++#define ureg_l2 regwptr[10]
++#define ureg_l3 regwptr[11]
++#define ureg_l4 regwptr[12]
++#define ureg_l5 regwptr[13]
++#define ureg_l6 regwptr[14]
++#define ureg_l7 regwptr[15]
++#define ureg_o0 regwptr[16]
++#define ureg_o1 regwptr[17]
++#define ureg_o2 regwptr[18]
++#define ureg_o3 regwptr[19]
++#define ureg_o4 regwptr[20]
++#define ureg_o5 regwptr[21]
++#define ureg_o6 regwptr[22]
++#define ureg_o7 regwptr[23]
++#define ureg_fp ureg_i6
++#define ureg_sp ureg_o6
++#define ureg_tnpc ureg_i0
++#define ureg_tpc ureg_i1
++
++#define TARGET_FPRS_FEF (1 << 2)
++#define TARGET_MC_VERSION 1L
++
++/* compare to sparc64/sparc64/machdep.c set_mcontext() */
++static inline int
++restore_sigmcontext(CPUSPARCState *regs, target_mcontext_t *mc)
++{
++ int err = 0;
++
++ err |= __get_user(regs->gregs[1], &mc->mc_global[1]);
++ err |= __get_user(regs->gregs[2], &mc->mc_global[2]);
++ err |= __get_user(regs->gregs[3], &mc->mc_global[3]);
++ err |= __get_user(regs->gregs[4], &mc->mc_global[4]);
++ err |= __get_user(regs->gregs[5], &mc->mc_global[5]);
++ err |= __get_user(regs->gregs[6], &mc->mc_global[6]);
++
++ err |= __get_user(regs->ureg_o0, &mc->mc_out[0]);
++ err |= __get_user(regs->ureg_o1, &mc->mc_out[1]);
++ err |= __get_user(regs->ureg_o2, &mc->mc_out[2]);
++ err |= __get_user(regs->ureg_o3, &mc->mc_out[3]);
++ err |= __get_user(regs->ureg_o4, &mc->mc_out[4]);
++ err |= __get_user(regs->ureg_o5, &mc->mc_out[5]);
++ err |= __get_user(regs->ureg_o6, &mc->mc_out[6]);
++ err |= __get_user(regs->ureg_o7, &mc->mc_out[0]);
++
++ err |= __get_user(regs->ureg_l0, &mc->mc_fprs); /* mc_local[0] */
++ err |= __get_user(regs->ureg_l1, &mc->mc_fsr); /* mc_local[1] */
++ err |= __get_user(regs->ureg_l2, &mc->mc_qsr); /* mc_local[2] */
++
++ err |= __get_user(regs->ureg_i0, &mc->mc_tnpc); /* mc_in[0] */
++ err |= __get_user(regs->ureg_i1, &mc->mc_tpc); /* mc_in[1] */
++ err |= __get_user(regs->ureg_i2, &mc->mc_tstate);/* mc_in[2] */
++
++ err |= __get_user(regs->ureg_i4, &mc->mc_y); /* mc_in[4] */
++
++ /* XXX
++ if ((regs->ureg_l0 & TARGET_FPRS_FEF) != 0) {
++ regs->ureg_l0 = 0;
++ for(i = 0; i < 64; i++)
++ err |= __get_user(regs->fpr[i], &mc->mc_fp[i]);
++ }
++ */
++
++ return (err);
++}
++
++/* compare to sparc64/sparc64/machdep.c get_mcontext() */
++static inline int
++setup_sigmcontext(CPUSPARCState *regs, target_mcontext_t *mc)
++{
++ int err = 0;
++ abi_ulong ver = TARGET_MC_VERSION;
++
++ err |= __put_user(ver, &mc->mc_flags); /* aka. mc_global[0] */
++ err |= __put_user(regs->gregs[1], &mc->mc_global[1]);
++ err |= __put_user(regs->gregs[2], &mc->mc_global[2]);
++ err |= __put_user(regs->gregs[3], &mc->mc_global[3]);
++ err |= __put_user(regs->gregs[4], &mc->mc_global[4]);
++ err |= __put_user(regs->gregs[5], &mc->mc_global[5]);
++ err |= __put_user(regs->gregs[6], &mc->mc_global[6]);
++ /* skip %g7 since it is used as the userland TLS register */
++
++ err |= __put_user(regs->ureg_o0, &mc->mc_out[0]);
++ err |= __put_user(regs->ureg_o1, &mc->mc_out[1]);
++ err |= __put_user(regs->ureg_o2, &mc->mc_out[2]);
++ err |= __put_user(regs->ureg_o3, &mc->mc_out[3]);
++ err |= __put_user(regs->ureg_o4, &mc->mc_out[4]);
++ err |= __put_user(regs->ureg_o5, &mc->mc_out[5]);
++ err |= __put_user(regs->ureg_o6, &mc->mc_out[6]);
++ err |= __put_user(regs->ureg_o7, &mc->mc_out[7]);
++
++ err |= __put_user(regs->ureg_l0, &mc->mc_fprs); /* mc_local[0] */
++ err |= __put_user(regs->ureg_l1, &mc->mc_fsr); /* mc_local[1] */
++ err |= __put_user(regs->ureg_l2, &mc->mc_qsr); /* mc_local[2] */
++
++ err |= __put_user(regs->ureg_i0, &mc->mc_tnpc); /* mc_in[0] */
++ err |= __put_user(regs->ureg_i1, &mc->mc_tpc); /* mc_in[1] */
++ err |= __put_user(regs->ureg_i2, &mc->mc_tstate);/* mc_in[2] */
++
++ err |= __put_user(regs->ureg_i4, &mc->mc_y); /* mc_in[4] */
++
++ /* XXX
++ if ((regs->ureg_l0 & TARGET_FPRS_FEF) != 0) {
++ for(i = 0; i < 64; i++)
++ err |= __put_user(regs->fpr[i], &mc->mc_fp[i]);
++ }
++ */
++
++ return (err);
++}
++
++static inline abi_ulong
++get_sigframe(struct target_sigaction *ka, CPUSPARCState *regs, size_t frame_size)
++{
++ abi_ulong sp;
++
++ /* Use default user stack */
++ sp = regs->ureg_sp;
++
++ if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
++ sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
++ }
++
++ return (sp - frame_size);
++}
++
++/* compare to sparc64/sparc64/machdep.c sendsig() */
++static void setup_frame(int sig, struct target_sigaction *ka,
++ target_sigset_t *set, CPUSPARCState *regs)
++{
++ struct target_sigframe *frame;
++ abi_ulong frame_addr;
++ int i;
++
++ if (!sparc_user_sigtramp) {
++ /* No signal trampoline... kill the process. */
++ fprintf(stderr, "setup_frame(): no sigtramp\n");
++ force_sig(TARGET_SIGKILL);
++ }
++
++ frame_addr = get_sigframe(ka, regs, sizeof(*frame));
++ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
++ goto give_sigsegv;
++
++ if (setup_sigmcontext(regs, &frame->sf_uc.uc_mcontext))
++ goto give_sigsegv;
++
++ for(i = 0; i < TARGET_NSIG_WORDS; i++) {
++ if (__put_user(set->__bits[i], &frame->sf_uc.uc_sigmask.__bits[i]))
++ goto give_sigsegv;
++ }
++
++ /* Fill in siginfo structure */
++ if (__put_user(sig, &frame->sf_si.si_signo))
++ goto give_sigsegv;
++ if (__put_user(TARGET_SA_SIGINFO, &frame->sf_si.si_code))
++ goto give_sigsegv;
++
++ /* Arguments to signal handler:
++ *
++ * o0 = signal number
++ * o1 = pointer to siginfo struct
++ * o2 = pointer to ucontext struct
++ * o3 = (not used in new style)
++ * o4 = signal handler address (called by sigtramp)
++ */
++ regs->ureg_o0 = sig;
++ regs->ureg_o1 = frame_addr +
++ offsetof(struct target_sigframe, sf_si);
++ regs->ureg_o2 = frame_addr +
++ offsetof(struct target_sigframe, sf_uc);
++ /* env->ureg_o3 used in the Old FreeBSD-style arguments. */
++ regs->ureg_o4 = ka->_sa_handler;
++
++ regs->ureg_tpc = sparc_user_sigtramp;
++ regs->ureg_tnpc = (regs->ureg_tpc + 4);
++ regs->ureg_sp = frame_addr - 2047 /* SPOFF */;
++ unlock_user_struct(frame, frame_addr, 1);
++ return;
++
++give_sigsegv:
++ unlock_user_struct(frame, frame_addr, 1);
++ force_sig(TARGET_SIGSEGV);
++}
++
++
++long do_sigreturn(CPUSPARCState *regs, abi_ulong uc_addr)
++{
++ target_ucontext_t *ucontext;
++ sigset_t blocked;
++ target_sigset_t target_set;
++ int i;
++
++#if defined(DEBUG_SIGNAL)
++ fprintf(stderr, "do_sigreturn\n");
++#endif
++ if (!lock_user_struct(VERIFY_READ, ucontext, uc_addr, 1))
++ goto badframe;
++
++ for(i = 0; i < TARGET_NSIG_WORDS; i++) {
++ if (__get_user(target_set.__bits[i], &ucontext->uc_sigmask.__bits[i]))
++ goto badframe;
++ }
++
++ if (restore_sigmcontext(regs, &ucontext->uc_mcontext))
++ goto badframe;
++
++ target_to_host_sigset_internal(&blocked, &target_set);
++ sigprocmask(SIG_SETMASK, &blocked, NULL);
++
++ return (-TARGET_QEMU_ESIGRETURN);
++
++badframe:
++ force_sig(TARGET_SIGSEGV);
++ return (0);
++}
++
++#else
++
++static void
++setup_frame(int sig, struct target_sigaction *ka, target_sigset_t *set,
++ CPUArchState *env)
++{
++ fprintf(stderr, "setup_frame: not implemented\n");
++}
++
++#if 0
++static void
++setup_rt_frame(int sig, struct target_sigaction *ka, target_siginfo_t *info,
++ target_sigset_t *set, CPUArchState *env)
++{
++ fprintf(stderr, "setup_rt_frame: not implemented\n");
++}
++#endif
++
++long
++do_sigreturn(CPUArchState *env, abi_ulong uc_addr)
++{
++ fprintf(stderr,"do_sigreturn: not implemented\n");
++ return (-TARGET_ENOSYS);
++}
++
++long
++do_rt_sigreturn(CPUArchState *env)
++{
++ fprintf(stderr, "do_rt_sigreturn: not implemented\n");
++ return (-TARGET_ENOSYS);
++}
++#endif
++
++void
++signal_init(void)
++{
++ struct sigaction act;
++ struct sigaction oact;
++ int i, j;
++ int host_sig;
++
++ /* Generate the signal conversion tables. */
++ for(i = 1; i < _NSIG; i++) {
++ if (host_to_target_signal_table[i] == 0)
++ host_to_target_signal_table[i] = i;
++ }
++ for(i = 1; i < _NSIG; i++) {
++ j = host_to_target_signal_table[i];
++ target_to_host_signal_table[j] = i;
++ }
++
++ /*
++ * Set all host signal handlers. ALL signals are blocked during the
++ * handlers to serialize them.
++ */
++ memset(sigact_table, 0, sizeof(sigact_table));
++
++ sigfillset(&act.sa_mask);
++ act.sa_sigaction = host_signal_handler;
++
++ for (i = 1; i <= TARGET_NSIG; i++) {
++ host_sig = target_to_host_signal(i);
++ sigaction(host_sig, NULL, &oact);
++ if (oact.sa_sigaction == (void *)SIG_IGN) {
++ sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
++ } else if (oact.sa_sigaction == (void *)SIG_DFL) {
++ sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
++ }
++ /*
++ * If there's already a handler installed then something has
++ * gone horribly wrong, so don't even try to handle that case.
++ * Install some handlers for our own use. We need at least
++ * SIGSEGV and SIGBUS, to detect exceptions. We can not just
++ * trap all signals because it affects syscall interrupt
++ * behavior. But do trap all default-fatal signals.
++ */
++ if (fatal_signal(i)) {
++ sigaction(host_sig, &act, NULL);
++ }
++ }
++}
++
++void
++process_pending_signals(CPUArchState *cpu_env)
++{
++ int sig;
++ abi_ulong handler;
++ sigset_t set, old_set;
++ target_sigset_t target_old_set;
++ struct emulated_sigtable *k;
++ struct target_sigaction *sa;
++ struct sigqueue *q;
++ TaskState *ts = cpu_env->opaque;
++
++ if (!ts->signal_pending)
++ return;
++
++ /* FIXME: This is not threadsafe. */
++ k = ts->sigtab;
++ for(sig = 1; sig <= TARGET_NSIG; sig++) {
++ if (k->pending)
++ goto handle_signal;
++ k++;
++ }
++#ifdef DEBUG_SIGNAL
++ fprintf(stderr, "qemu: process_pending_signals has no signals\n");
++#endif
++ /* If no signal is pending then just return. */
++ ts->signal_pending = 0;
++ return;
++
++handle_signal:
++#ifdef DEBUG_SIGNAL
++ fprintf(stderr, "qemu: process signal %d\n", sig);
++#endif
++
++ /* Dequeue signal. */
++ q = k->first;
++ k->first = q->next;
++ if (!k->first)
++ k->pending = 0;
++
++ sig = gdb_handlesig (cpu_env, sig);
++ if (!sig) {
++ sa = NULL;
++ handler = TARGET_SIG_IGN;
++ } else {
++ sa = &sigact_table[sig - 1];
++ handler = sa->_sa_handler;
++ }
++
++ if (handler == TARGET_SIG_DFL) {
++#ifdef DEBUG_SIGNAL
++ fprintf(stderr, "qemu: TARGET_SIG_DFL\n");
++#endif
++ /*
++ * default handler : ignore some signal. The other are job
++ * control or fatal.
++ */
++ if (TARGET_SIGTSTP == sig || TARGET_SIGTTIN == sig ||
++ TARGET_SIGTTOU == sig) {
++ kill(getpid(),SIGSTOP);
++ } else if (TARGET_SIGCHLD != sig && TARGET_SIGURG != sig &&
++ TARGET_SIGWINCH != sig && TARGET_SIGCONT != sig) {
++ force_sig(sig);
++ }
++ } else if (TARGET_SIG_IGN == handler) {
++ /* ignore sig */
++#ifdef DEBUG_SIGNAL
++ fprintf(stderr, "qemu: TARGET_SIG_IGN\n");
++#endif
++ } else if (TARGET_SIG_ERR == handler) {
++#ifdef DEBUG_SIGNAL
++ fprintf(stderr, "qemu: TARGET_SIG_ERR\n");
++#endif
++ force_sig(sig);
++ } else {
++ /* compute the blocked signals during the handler execution */
++ target_to_host_sigset(&set, &sa->sa_mask);
++ /*
++ * SA_NODEFER indicates that the current signal should not be
++ * blocked during the handler.
++ */
++ if (!(sa->sa_flags & TARGET_SA_NODEFER))
++ sigaddset(&set, target_to_host_signal(sig));
++
++ /* block signals in the handler */
++ sigprocmask(SIG_BLOCK, &set, &old_set);
++
++ /*
++ * Save the previous blocked signal state to restore it at the
++ * end of the signal execution (see do_sigreturn).
++ */
++ host_to_target_sigset_internal(&target_old_set, &old_set);
++
++#if 0
++#if defined(TARGET_I386) && !defined(TARGET_X86_64)
++ /* if the CPU is in VM86 mode, we restore the 32 bit values */
++ {
++ CPUX86State *env = cpu_env;
++ if (env->eflags & VM_MASK)
++ save_v86_state(env);
++ }
++#endif
++#endif
++ /* prepare the stack frame of the virtual CPU */
++#if 0 /* XXX no rt for fbsd */
++ if (sa->sa_flags & TARGET_SA_SIGINFO)
++ setup_rt_frame(sig, sa, &q->info, &target_old_set,
++ cpu_env);
++ else
++#endif
++ setup_frame(sig, sa, &target_old_set, cpu_env);
++ if (sa->sa_flags & TARGET_SA_RESETHAND)
++ sa->_sa_handler = TARGET_SIG_DFL;
++ }
++ if (q != &k->info)
++ free_sigqueue(cpu_env, q);
+ }
+diff --git a/bsd-user/socket.h b/bsd-user/socket.h
+new file mode 100644
+index 0000000..c9e019b
+--- /dev/null
++++ b/bsd-user/socket.h
+@@ -0,0 +1,66 @@
++/*
++ * Target socket definitions.
++ */
++
++/*
++ * Types
++ */
++#define TARGET_SOCK_STREAM 1 /* stream socket */
++#define TARGET_SOCK_DGRAM 2 /* datagram socket */
++#define TARGET_SOCK_RAW 3 /* raw-protocol interface */
++#define TARGET_SOCK_RDM 4 /* reliably-delivered message */
++#define TARGET_SOCK_SEQPACKET 5 /* sequenced packet stream */
++
++
++/*
++ * Option flags per-socket.
++ */
++
++#define TARGET_SO_DEBUG 0x0001 /* turn on debugging info recording */
++#define TARGET_SO_ACCEPTCONN 0x0002 /* socket has had listen() */
++#define TARGET_SO_REUSEADDR 0x0004 /* allow local address reuse */
++#define TARGET_SO_KEEPALIVE 0x0008 /* keep connections alive */
++#define TARGET_SO_DONTROUTE 0x0010 /* just use interface addresses */
++#define TARGET_SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */
++#define TARGET_SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
++#define TARGET_SO_LINGER 0x0080 /* linger on close if data present */
++#define TARGET_SO_OOBINLINE 0x0100 /* leave received OOB data in line */
++#define TARGET_SO_REUSEPORT 0x0200 /* allow local address & port reuse */
++#define TARGET_SO_TIMESTAMP 0x0400 /* timestamp received dgram traffic */
++#define TARGET_SO_NOSIGPIPE 0x0800 /* no SIGPIPE from EPIPE */
++#define TARGET_SO_ACCEPTFILTER 0x1000 /* there is an accept filter */
++#define TARGET_SO_BINTIME 0x2000 /* timestamp received dgram traffic */
++#define TARGET_SO_NO_OFFLOAD 0x4000 /* socket cannot be offloaded */
++#define TARGET_SO_NO_DDP 0x8000 /* disable direct data placement */
++
++/*
++ * Additional options, not kept in so_options.
++ */
++#define TARGET_SO_SNDBUF 0x1001 /* send buffer size */
++#define TARGET_SO_RCVBUF 0x1002 /* receive buffer size */
++#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_ERROR 0x1007 /* get error status and clear */
++#define TARGET_SO_TYPE 0x1008 /* get socket type */
++#define TARGET_SO_LABEL 0x1009 /* socket's MAC label */
++#define TARGET_SO_PEERLABEL 0x1010 /* socket's peer's MAC label */
++#define TARGET_SO_LISTENQLIMIT 0x1011 /* socket's backlog limit */
++#define TARGET_SO_LISTENQLEN 0x1012 /* socket's complete queue length */
++#define TARGET_SO_LISTENINCQLEN 0x1013 /* socket's incomplete queue length */
++#define TARGET_SO_SETFIB 0x1014 /* use this FIB to route */
++#define TARGET_SO_USER_COOKIE 0x1015 /* user cookie (dummynet etc.) */
++#define TARGET_SO_PROTOCOL 0x1016 /* get socket protocol (Linux name) */
++
++/* alias for SO_PROTOCOL (SunOS name) */
++#define TARGET_SO_PROTOTYPE TARGET_SO_PROTOCOL
++
++/*
++ * Level number for (get/set)sockopt() to apply to socket itself.
++ */
++#define TARGET_SOL_SOCKET 0xffff /* options for socket level */
++
++#ifndef CMSG_ALIGN
++#define CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) )
++#endif
+diff --git a/bsd-user/sparc/target_signal.h b/bsd-user/sparc/target_signal.h
+index 5b2abba..79dfc1e 100644
+--- a/bsd-user/sparc/target_signal.h
++++ b/bsd-user/sparc/target_signal.h
+@@ -3,15 +3,6 @@
+
+ #include "cpu.h"
+
+-/* this struct defines a stack used during syscall handling */
+-
+-typedef struct target_sigaltstack {
+- abi_ulong ss_sp;
+- abi_long ss_flags;
+- abi_ulong ss_size;
+-} target_stack_t;
+-
+-
+ #ifndef UREG_I6
+ #define UREG_I6 6
+ #endif
+@@ -19,6 +10,9 @@ typedef struct target_sigaltstack {
+ #define UREG_FP UREG_I6
+ #endif
+
++#define TARGET_MINSIGSTKSZ (512 * 4)
++#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
++
+ static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
+ {
+ return state->regwptr[UREG_FP];
+diff --git a/bsd-user/sparc/target_vmparam.h b/bsd-user/sparc/target_vmparam.h
+new file mode 100644
+index 0000000..9494c46
+--- /dev/null
++++ b/bsd-user/sparc/target_vmparam.h
+@@ -0,0 +1,23 @@
++#ifndef _TARGET_VMPARAM_H_
++#define _TARGET_VMPARAM_H_
++
++#define TARGET_USRSTACK 0
++
++#ifdef __FreeBSD__
++struct target_ps_strings {
++ abi_ulong ps_argvstr;
++ uint32_t ps_nargvstr;
++ abi_ulong ps_envstr;
++ uint32_t ps_nenvstr;
++};
++
++#define TARGET_SPACE_USRSPACE 4096
++#define TARGET_ARG_MAX 262144
++
++#define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
++
++#define TARGET_SZSIGCODE 0
++#endif /* __FreeBSD__ */
++
++#endif /* _TARGET_VMPARAM_H_ */
++
+diff --git a/bsd-user/sparc64/target_signal.h b/bsd-user/sparc64/target_signal.h
+index 5b2abba..d3e58bb 100644
+--- a/bsd-user/sparc64/target_signal.h
++++ b/bsd-user/sparc64/target_signal.h
+@@ -3,15 +3,6 @@
+
+ #include "cpu.h"
+
+-/* this struct defines a stack used during syscall handling */
+-
+-typedef struct target_sigaltstack {
+- abi_ulong ss_sp;
+- abi_long ss_flags;
+- abi_ulong ss_size;
+-} target_stack_t;
+-
+-
+ #ifndef UREG_I6
+ #define UREG_I6 6
+ #endif
+@@ -19,6 +10,9 @@ typedef struct target_sigaltstack {
+ #define UREG_FP UREG_I6
+ #endif
+
++#define TARGET_MINSIGSTKSZ (1024 * 4)
++#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
++
+ static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
+ {
+ return state->regwptr[UREG_FP];
+diff --git a/bsd-user/sparc64/target_vmparam.h b/bsd-user/sparc64/target_vmparam.h
+new file mode 100644
+index 0000000..12af063
+--- /dev/null
++++ b/bsd-user/sparc64/target_vmparam.h
+@@ -0,0 +1,30 @@
++#ifndef _TARGET_VMPARAM_H_
++#define _TARGET_VMPARAM_H_
++
++#if defined(__FreeBSD__)
++#define TARGET_VM_MINUSER_ADDRESS (0x0000000000000000UL)
++#define TARGET_VM_MAXUSER_ADDRESS (0x000007fe00000000UL)
++
++#define TARGET_USRSTACK TARGET_VM_MAXUSER_ADDRESS
++
++struct target_ps_strings {
++ abi_ulong ps_argvstr;
++ uint32_t ps_nargvstr;
++ abi_ulong ps_envstr;
++ uint32_t ps_nenvstr;
++};
++
++#define TARGET_SPACE_USRSPACE 4096
++#define TARGET_ARG_MAX 262144
++
++#define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
++
++#define TARGET_SZSIGCODE 0
++
++#else
++
++#define TARGET_USRSTACK 0
++#endif
++
++#endif /* _TARGET_VMPARAM_H_ */
++
+diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
+index 443b01a..c627c62 100644
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -2,6 +2,7 @@
+ * BSD syscalls
+ *
+ * Copyright (c) 2003 - 2008 Fabrice Bellard
++ * Copyright (c) 2012 Stacey Son <sson@FreeBSD.org>
+ *
+ * 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
+@@ -21,18 +22,37 @@
+ #include <stdint.h>
+ #include <stdarg.h>
+ #include <string.h>
++#include <dirent.h>
+ #include <errno.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <time.h>
+ #include <limits.h>
++#include <poll.h>
+ #include <sys/types.h>
++#include <sys/time.h>
+ #include <sys/mman.h>
+ #include <sys/syscall.h>
+ #include <sys/param.h>
++#include <sys/resource.h>
+ #include <sys/sysctl.h>
++#include <sys/event.h>
++#include <sys/mount.h>
++#include <sys/wait.h>
++#include <sys/socket.h>
++#ifdef __FreeBSD__
++#include <sys/regression.h>
++#include <sys/procdesc.h>
++#endif
++#include <sys/un.h>
++#include <sys/ipc.h>
++#include <sys/sem.h>
++#include <sys/shm.h>
++#include <sys/msg.h>
+ #include <utime.h>
+
++#include <netinet/in.h>
++
+ #include "qemu.h"
+ #include "qemu-common.h"
+
+@@ -50,6 +70,13 @@ static inline abi_long get_errno(abi_long ret)
+ return ret;
+ }
+
++static inline int
++host_to_target_errno(int err)
++{
++ /* XXX need to translate host errnos here */
++ return (err);
++}
++
+ #define target_to_host_bitmask(x, tbl) (x)
+
+ static inline int is_error(abi_long ret)
+@@ -152,13 +179,65 @@ static abi_long do_freebsd_sysarch(CPUX86State *env, int op, abi_ulong parms)
+ #endif
+
+ #ifdef TARGET_SPARC
++struct target_sparc_sigtramp_install_args {
++ abi_ulong sia_new; /* address of sigtramp code */
++ abi_ulong sia_old; /* user address to store old sigtramp addr */
++};
++
++abi_ulong sparc_user_sigtramp = 0;
++
+ static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
+ {
+- /* XXX handle
+- * TARGET_FREEBSD_SPARC_UTRAP_INSTALL,
+- * TARGET_FREEBSD_SPARC_SIGTRAMP_INSTALL
+- */
+- return -TARGET_EINVAL;
++ int ret = 0;
++ abi_ulong val, old;
++ /*
++ struct target_sparc_sigtramp_install_args *target_sigtramp_args;
++ */
++
++
++ switch(op) {
++ case TARGET_SPARC_SIGTRAMP_INSTALL:
++ {
++
++#if 0
++ /* Sparc userland is giving us a new sigtramp code ptr. */
++ if (!(target_sigtramp_args = lock_user(VERIFY_WRITE, parms,
++ sizeof(*target_sigtramp_args), 1))) {
++ ret = -TARGET_EFAULT;
++ } else {
++ if (target_sigtramp_args->sia_old) {
++ put_user_ual(sparc_user_sigtramp,
++ target_sigtramp_args->sia_old);
++ }
++ sparc_user_sigtramp = target_sigtramp_args->sia_new;
++ unlock_user(target_sigtramp_args, parms, 0);
++
++ }
++#endif
++ val = sparc_user_sigtramp;
++ if (get_user(sparc_user_sigtramp, parms, abi_ulong)) {
++ return (-TARGET_EFAULT);
++ }
++ parms += sizeof(abi_ulong);
++ if (get_user(old, parms, abi_ulong)) {
++ return (-TARGET_EFAULT);
++ }
++ if (old) {
++ if (put_user(val, old, abi_ulong)) {
++ return (-TARGET_EFAULT);
++ }
++ }
++ }
++ break;
++
++ case TARGET_SPARC_UTRAP_INSTALL:
++ /* XXX not currently handled */
++ default:
++ ret = -TARGET_EINVAL;
++ break;
++ }
++
++ return (ret);
+ }
+ #endif
+
+@@ -168,7 +247,17 @@ static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
+ return -TARGET_EINVAL;
+ }
+ #endif
++
++#ifdef TARGET_MIPS
++static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
++{
++ return -TARGET_EINVAL;
++}
++#endif
++
+ #ifdef __FreeBSD__
++extern int _getlogin(char *, int);
++
+ /*
+ * XXX this uses the undocumented oidfmt interface to find the kind of
+ * a requested sysctl, see /sys/kern/kern_sysctl.c:sysctl_sysctl_oidfmt()
+@@ -327,92 +416,3799 @@ static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
+ return 0;
+ }
+
+-/* 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>. */
+-abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+- abi_long arg2, abi_long arg3, abi_long arg4,
+- abi_long arg5, abi_long arg6, abi_long arg7,
+- abi_long arg8)
++static inline abi_long
++target_to_host_sockaddr(struct sockaddr *addr, abi_ulong target_addr,
++ socklen_t len)
+ {
+- abi_long ret;
+- void *p;
++ const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
++ sa_family_t sa_family;
++ struct target_sockaddr *target_saddr;
+
+-#ifdef DEBUG
+- gemu_log("freebsd syscall %d\n", num);
+-#endif
+- if(do_strace)
+- print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
++ target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
++ if (!target_saddr)
++ return -TARGET_EFAULT;
+
+- switch(num) {
+- case TARGET_FREEBSD_NR_exit:
+-#ifdef TARGET_GPROF
+- _mcleanup();
++ sa_family = tswap16(target_saddr->sa_family);
++
++ /*
++ * Oops. The caller might send a incomplete sun_path; sun_path
++ * must be terminated by \0 (see the manual page), but unfortunately
++ * it is quite common to specify sockaddr_un length as
++ * "strlen(x->sun_path)" while it should be "strlen(...) + 1". We will
++ * fix that here if needed.
++ */
++ if (sa_family == AF_UNIX) {
++ if (len < unix_maxlen && len > 0) {
++ char *cp = (char*)target_saddr;
++
++ if ( cp[len-1] && !cp[len] )
++ len++;
++ }
++ if (len > unix_maxlen)
++ len = unix_maxlen;
++ }
++
++ memcpy(addr, target_saddr, len);
++ addr->sa_family = sa_family;
++ unlock_user(target_saddr, target_addr, 0);
++
++ return (0);
++}
++
++static inline abi_long
++host_to_target_sockaddr(abi_ulong target_addr, struct sockaddr *addr,
++ socklen_t len)
++{
++ struct target_sockaddr *target_saddr;
++
++ target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
++ if (!target_saddr)
++ return (-TARGET_EFAULT);
++ memcpy(target_saddr, addr, len);
++ target_saddr->sa_family = tswap16(addr->sa_family);
++ unlock_user(target_saddr, target_addr, len);
++
++ return (0);
++}
++
++static inline abi_long
++target_to_host_cmsg(struct msghdr *msgh, struct target_msghdr *target_msgh)
++{
++ struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
++ abi_long msg_controllen;
++ abi_ulong target_cmsg_addr;
++ struct target_cmsghdr *target_cmsg;
++ socklen_t space = 0;
++
++
++ msg_controllen = tswapal(target_msgh->msg_controllen);
++ if (msg_controllen < sizeof (struct target_cmsghdr))
++ goto the_end;
++ target_cmsg_addr = tswapal(target_msgh->msg_control);
++ target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr,
++ msg_controllen, 1);
++ if (!target_cmsg)
++ return (-TARGET_EFAULT);
++ while (cmsg && target_cmsg) {
++ void *data = CMSG_DATA(cmsg);
++ void *target_data = TARGET_CMSG_DATA(target_cmsg);
++ int len = tswapal(target_cmsg->cmsg_len) -
++ TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
++ space += CMSG_SPACE(len);
++ if (space > msgh->msg_controllen) {
++ space -= CMSG_SPACE(len);
++ gemu_log("Host cmsg overflow\n");
++ break;
++ }
++ cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
++ cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
++ cmsg->cmsg_len = CMSG_LEN(len);
++
++ if (cmsg->cmsg_level != TARGET_SOL_SOCKET ||
++ cmsg->cmsg_type != SCM_RIGHTS) {
++ gemu_log("Unsupported ancillary data: %d/%d\n",
++ cmsg->cmsg_level, cmsg->cmsg_type);
++ memcpy(data, target_data, len);
++ } else {
++ int *fd = (int *)data;
++ int *target_fd = (int *)target_data;
++ int i, numfds = len / sizeof(int);
++
++ for (i = 0; i < numfds; i++)
++ fd[i] = tswap32(target_fd[i]);
++ }
++ cmsg = CMSG_NXTHDR(msgh, cmsg);
++ target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
++ }
++ unlock_user(target_cmsg, target_cmsg_addr, 0);
++
++the_end:
++ msgh->msg_controllen = space;
++ return (0);
++}
++
++static inline abi_long
++host_to_target_cmsg(struct target_msghdr *target_msgh, struct msghdr *msgh)
++{
++ struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
++ abi_long msg_controllen;
++ abi_ulong target_cmsg_addr;
++ struct target_cmsghdr *target_cmsg;
++ socklen_t space = 0;
++
++ msg_controllen = tswapal(target_msgh->msg_controllen);
++ if (msg_controllen < sizeof (struct target_cmsghdr))
++ goto the_end;
++ target_cmsg_addr = tswapal(target_msgh->msg_control);
++ target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr,
++ msg_controllen, 0);
++ if (!target_cmsg)
++ return (-TARGET_EFAULT);
++ while (cmsg && target_cmsg) {
++ void *data = CMSG_DATA(cmsg);
++ void *target_data = TARGET_CMSG_DATA(target_cmsg);
++ int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
++
++ space += TARGET_CMSG_SPACE(len);
++ if (space > msg_controllen) {
++ space -= TARGET_CMSG_SPACE(len);
++ gemu_log("Target cmsg overflow\n");
++ break;
++ }
++ target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
++ target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
++ target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(len));
++ if ((cmsg->cmsg_level == TARGET_SOL_SOCKET) &&
++ (cmsg->cmsg_type == SCM_RIGHTS)) {
++ int *fd = (int *)data;
++ int *target_fd = (int *)target_data;
++ int i, numfds = len / sizeof(int);
++ for (i = 0; i < numfds; i++)
++ target_fd[i] = tswap32(fd[i]);
++ } else if ((cmsg->cmsg_level == TARGET_SOL_SOCKET) &&
++ (cmsg->cmsg_type == SO_TIMESTAMP) &&
++ (len == sizeof(struct timeval))) {
++ /* copy struct timeval to target */
++ struct timeval *tv = (struct timeval *)data;
++ struct target_timeval *target_tv =
++ (struct target_timeval *)target_data;
++ target_tv->tv_sec = tswapal(tv->tv_sec);
++ target_tv->tv_usec = tswapal(tv->tv_usec);
++ } else {
++ gemu_log("Unsupported ancillary data: %d/%d\n",
++ cmsg->cmsg_level, cmsg->cmsg_type);
++ memcpy(target_data, data, len);
++ }
++ cmsg = CMSG_NXTHDR(msgh, cmsg);
++ target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
++ }
++ unlock_user(target_cmsg, target_cmsg_addr, space);
++
++the_end:
++ target_msgh->msg_controllen = tswapal(space);
++ return (0);
++}
++
++static inline rlim_t
++target_to_host_rlim(abi_ulong target_rlim)
++{
++ abi_ulong target_rlim_swap;
++ rlim_t result;
++
++ target_rlim_swap = tswapal(target_rlim);
++ if (target_rlim_swap == TARGET_RLIM_INFINITY)
++ return (RLIM_INFINITY);
++
++ result = target_rlim_swap;
++ if (target_rlim_swap != (rlim_t)result)
++ return (RLIM_INFINITY);
++
++ return (result);
++}
++
++static inline abi_ulong
++host_to_target_rlim(rlim_t rlim)
++{
++ abi_ulong target_rlim_swap;
++ abi_ulong result;
++
++ if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
++ target_rlim_swap = TARGET_RLIM_INFINITY;
++ else
++ target_rlim_swap = rlim;
++ result = tswapal(target_rlim_swap);
++
++ return (result);
++}
++
++static inline int
++target_to_host_resource(int code)
++{
++
++ switch (code) {
++ case TARGET_RLIMIT_AS:
++ return RLIMIT_AS;
++
++ case TARGET_RLIMIT_CORE:
++ return RLIMIT_CORE;
++
++ case TARGET_RLIMIT_CPU:
++ return RLIMIT_CPU;
++
++ case TARGET_RLIMIT_DATA:
++ return RLIMIT_DATA;
++
++ case TARGET_RLIMIT_FSIZE:
++ return RLIMIT_FSIZE;
++
++ case TARGET_RLIMIT_MEMLOCK:
++ return RLIMIT_MEMLOCK;
++
++ case TARGET_RLIMIT_NOFILE:
++ return RLIMIT_NOFILE;
++
++ case TARGET_RLIMIT_NPROC:
++ return RLIMIT_NPROC;
++
++ case TARGET_RLIMIT_RSS:
++ return RLIMIT_RSS;
++
++ case TARGET_RLIMIT_SBSIZE:
++ return RLIMIT_SBSIZE;
++
++ case TARGET_RLIMIT_STACK:
++ return RLIMIT_STACK;
++
++ case TARGET_RLIMIT_SWAP:
++ return RLIMIT_SWAP;
++
++ case TARGET_RLIMIT_NPTS:
++ return RLIMIT_NPTS;
++
++ default:
++ return (code);
++ }
++}
++
++static int
++target_to_host_fcntl_cmd(int cmd)
++{
++
++ switch(cmd) {
++ case TARGET_F_DUPFD:
++ return F_DUPFD;
++
++ case TARGET_F_DUP2FD:
++ return F_DUP2FD;
++
++ case TARGET_F_GETFD:
++ return F_GETFD;
++
++ case TARGET_F_SETFD:
++ return F_SETFD;
++
++ case TARGET_F_GETFL:
++ return F_GETFL;
++
++ case TARGET_F_SETFL:
++ return F_SETFL;
++
++ case TARGET_F_GETOWN:
++ return F_GETOWN;
++
++ case TARGET_F_SETOWN:
++ return F_SETOWN;
++
++ case TARGET_F_GETLK:
++ return F_GETLK;
++
++ case TARGET_F_SETLK:
++ return F_SETLK;
++
++ case TARGET_F_SETLKW:
++ return F_SETLKW;
++
++ case TARGET_F_READAHEAD:
++ return F_READAHEAD;
++
++ case TARGET_F_RDAHEAD:
++ return F_RDAHEAD;
++
++ default:
++ return (cmd);
++ }
++}
++
++static inline abi_long
++host_to_target_rusage(abi_ulong target_addr, const struct rusage *rusage)
++{
++ struct target_rusage *target_rusage;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
++ return (-TARGET_EFAULT);
++ target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec);
++ target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec);
++ target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec);
++ target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec);
++ target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss);
++ target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss);
++ target_rusage->ru_idrss = tswapal(rusage->ru_idrss);
++ target_rusage->ru_isrss = tswapal(rusage->ru_isrss);
++ target_rusage->ru_minflt = tswapal(rusage->ru_minflt);
++ target_rusage->ru_majflt = tswapal(rusage->ru_majflt);
++ target_rusage->ru_nswap = tswapal(rusage->ru_nswap);
++ target_rusage->ru_inblock = tswapal(rusage->ru_inblock);
++ target_rusage->ru_oublock = tswapal(rusage->ru_oublock);
++ target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd);
++ target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv);
++ target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals);
++ target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw);
++ target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw);
++ unlock_user_struct(target_rusage, target_addr, 1);
++
++ return (0);
++}
++
++/*
++ * Map host to target signal numbers for the wait family of syscalls.
++ * Assume all other status bits are the same.
++ */
++static 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);
++}
++
++static inline abi_long
++copy_from_user_timeval(struct timeval *tv, abi_ulong target_tv_addr)
++{
++ struct target_freebsd_timeval *target_tv;
++
++ if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 0))
++ return -TARGET_EFAULT;
++ __get_user(tv->tv_sec, &target_tv->tv_sec);
++ __get_user(tv->tv_usec, &target_tv->tv_usec);
++ unlock_user_struct(target_tv, target_tv_addr, 1);
++ return (0);
++}
++
++static inline abi_long
++target_to_host_timespec(struct timespec *ts, abi_ulong target_ts_addr)
++{
++ struct target_freebsd_timespec *target_ts;
++
++ if (!lock_user_struct(VERIFY_READ, target_ts, target_ts_addr, 0))
++ return -TARGET_EFAULT;
++ __get_user(ts->tv_sec, &target_ts->tv_sec);
++ __get_user(ts->tv_nsec, &target_ts->tv_nsec);
++ unlock_user_struct(target_ts, target_ts_addr, 1);
++ return (0);
++}
++
++static inline abi_long
++fbsd_copy_to_user_timeval(struct timeval *tv, abi_ulong target_tv_addr)
++{
++ struct target_freebsd_timeval *target_tv;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
++ return -TARGET_EFAULT;
++ __put_user(tv->tv_sec, &target_tv->tv_sec);
++ __put_user(tv->tv_usec, &target_tv->tv_usec);
++ unlock_user_struct(target_tv, target_tv_addr, 1);
++ return (0);
++}
++
++static inline abi_long
++host_to_target_timespec(abi_ulong target_ts_addr, struct timespec *ts)
++{
++ struct target_freebsd_timespec *target_ts;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_ts, target_ts_addr, 0))
++ return -TARGET_EFAULT;
++ __put_user(ts->tv_sec, &target_ts->tv_sec);
++ __put_user(ts->tv_nsec, &target_ts->tv_nsec);
++ unlock_user_struct(target_ts, target_ts_addr, 1);
++ return (0);
++}
++static inline abi_ulong
++copy_from_user_fdset(fd_set *fds, abi_ulong target_fds_addr, int n)
++{
++ int i, nw, j, k;
++ abi_ulong b, *target_fds;
++
++ nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
++ if (!(target_fds = lock_user(VERIFY_READ, target_fds_addr,
++ sizeof(abi_ulong) * nw, 1)))
++ return (-TARGET_EFAULT);
++
++ FD_ZERO(fds);
++ k = 0;
++ for (i = 0; i < nw; i++) {
++ /* grab the abi_ulong */
++ __get_user(b, &target_fds[i]);
++ for (j = 0; j < TARGET_ABI_BITS; j++) {
++ /* check the bit inside the abi_ulong */
++ if ((b >> j) & 1)
++ FD_SET(k, fds);
++ k++;
++ }
++ }
++
++ unlock_user(target_fds, target_fds_addr, 0);
++
++ return (0);
++}
++
++static inline abi_ulong
++copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
++ abi_ulong target_fds_addr, int n)
++{
++ if (target_fds_addr) {
++ if (copy_from_user_fdset(fds, target_fds_addr, n))
++ return (-TARGET_EFAULT);
++ *fds_ptr = fds;
++ } else {
++ *fds_ptr = NULL;
++ }
++ return (0);
++}
++
++static inline abi_long
++copy_to_user_fdset(abi_ulong target_fds_addr, const fd_set *fds, int n)
++{
++ int i, nw, j, k;
++ abi_long v;
++ abi_ulong *target_fds;
++
++ nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
++ if (!(target_fds = lock_user(VERIFY_WRITE, target_fds_addr,
++ sizeof(abi_ulong) * nw, 0)))
++ return (-TARGET_EFAULT);
++
++ k = 0;
++ for (i = 0; i < nw; i++) {
++ v = 0;
++ for (j = 0; j < TARGET_ABI_BITS; j++) {
++ v |= ((FD_ISSET(k, fds) != 0) << j);
++ k++;
++ }
++ __put_user(v, &target_fds[i]);
++ }
++
++ unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
++
++ return (0);
++}
++
++#if TARGET_ABI_BITS == 32
++static inline uint64_t
++target_offset64(uint32_t word0, uint32_t word1)
++{
++#ifdef TARGET_WORDS_BIGENDIAN
++ return ((uint64_t)word0 << 32) | word1;
++#else
++ return ((uint64_t)word1 << 32) | word0;
+ #endif
+- gdb_exit(cpu_env, arg1);
+- /* XXX: should free thread stack and CPU env */
+- _exit(arg1);
+- ret = 0; /* avoid warning */
+- break;
+- case TARGET_FREEBSD_NR_read:
+- if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
+- goto efault;
+- ret = get_errno(read(arg1, p, arg3));
+- unlock_user(p, arg2, ret);
+- break;
+- case TARGET_FREEBSD_NR_write:
+- if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
+- goto efault;
+- ret = get_errno(write(arg1, p, arg3));
+- unlock_user(p, arg2, 0);
+- break;
+- case TARGET_FREEBSD_NR_writev:
+- {
+- int count = arg3;
+- struct iovec *vec;
++}
++#else /* TARGET_ABI_BITS != 32 */
++static inline uint64_t
++target_offset64(uint64_t word0, uint64_t word1)
++{
++ return (word0);
++}
++#endif /* TARGET_ABI_BITS != 32 */
+
+- vec = alloca(count * sizeof(struct iovec));
+- if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
+- goto efault;
+- ret = get_errno(writev(arg1, vec, count));
+- unlock_iovec(vec, arg2, count, 0);
+- }
+- break;
+- case TARGET_FREEBSD_NR_open:
+- if (!(p = lock_user_string(arg1)))
+- goto efault;
+- ret = get_errno(open(path(p),
+- target_to_host_bitmask(arg2, fcntl_flags_tbl),
+- arg3));
+- unlock_user(p, arg1, 0);
+- break;
+- case TARGET_FREEBSD_NR_mmap:
+- ret = get_errno(target_mmap(arg1, arg2, arg3,
+- target_to_host_bitmask(arg4, mmap_flags_tbl),
+- arg5,
+- arg6));
+- break;
+- case TARGET_FREEBSD_NR_munmap:
+- ret = get_errno(target_munmap(arg1, arg2));
+- break;
+- case TARGET_FREEBSD_NR_mprotect:
+- ret = get_errno(target_mprotect(arg1, arg2, arg3));
+- break;
+- case TARGET_FREEBSD_NR_break:
+- ret = do_obreak(arg1);
+- break;
+-#ifdef __FreeBSD__
+- case TARGET_FREEBSD_NR___sysctl:
+- ret = do_freebsd_sysctl(arg1, arg2, arg3, arg4, arg5, arg6);
+- break;
++/* ARM EABI and MIPS expect 64bit types aligned even on pairs of registers */
++#ifdef TARGET_ARM
++static inline int
++regpairs_aligned(void *cpu_env) {
++
++ return ((((CPUARMState *)cpu_env)->eabi) == 1);
++}
++#elif defined(TARGET_MIPS) && TARGET_ABI_BITS == 32
++static inline int
++regpairs_aligned(void *cpu_env) { return 1; }
++#else
++static inline int
++regpairs_aligned(void *cpu_env) { return 0; }
+ #endif
+- case TARGET_FREEBSD_NR_sysarch:
+- ret = do_freebsd_sysarch(cpu_env, arg1, arg2);
+- break;
+- case TARGET_FREEBSD_NR_syscall:
+- case TARGET_FREEBSD_NR___syscall:
+- ret = do_freebsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,arg7,arg8,0);
+- break;
++
++static inline abi_long
++unimplemented(int num)
++{
++
++ qemu_log("qemu: Unsupported syscall: %d\n", num);
++ return (-TARGET_ENOSYS);
++}
++
++/* do_bind() must return target values and target errnos. */
++static abi_long
++do_bind(int sockfd, abi_ulong target_addr, socklen_t addrlen)
++{
++ abi_long ret;
++ void *addr;
++
++ if ((int)addrlen < 0)
++ return (-TARGET_EINVAL);
++
++ addr = alloca(addrlen + 1);
++ ret = target_to_host_sockaddr(addr, target_addr, addrlen);
++ if (ret)
++ return (ret);
++
++ return get_errno(bind(sockfd, addr, addrlen));
++}
++
++/* do_connect() must return target values and target errnos. */
++static abi_long
++do_connect(int sockfd, abi_ulong target_addr, socklen_t addrlen)
++{
++ abi_long ret;
++ void *addr;
++
++ if ((int)addrlen < 0)
++ return (-TARGET_EINVAL);
++
++ addr = alloca(addrlen);
++
++ ret = target_to_host_sockaddr(addr, target_addr, addrlen);
++
++ if (ret)
++ return (ret);
++
++ return (get_errno(connect(sockfd, addr, addrlen)));
++}
++
++/* do_sendrecvmsg() must return target values and target errnos. */
++static abi_long
++do_sendrecvmsg(int fd, abi_ulong target_msg, int flags, int send)
++{
++ abi_long ret, len;
++ struct target_msghdr *msgp;
++ struct msghdr msg;
++ int count;
++ struct iovec *vec;
++ abi_ulong target_vec;
++
++ if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE, msgp,
++ target_msg, send ? 1 : 0))
++ return (-TARGET_EFAULT);
++ if (msgp->msg_name) {
++ msg.msg_namelen = tswap32(msgp->msg_namelen);
++ msg.msg_name = alloca(msg.msg_namelen);
++ ret = target_to_host_sockaddr(msg.msg_name,
++ tswapal(msgp->msg_name), msg.msg_namelen);
++
++ if (ret) {
++ unlock_user_struct(msgp, target_msg, send ? 0 : 1);
++ return (ret);
++ }
++ } else {
++ msg.msg_name = NULL;
++ msg.msg_namelen = 0;
++ }
++ msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
++ msg.msg_control = alloca(msg.msg_controllen);
++ msg.msg_flags = tswap32(msgp->msg_flags);
++
++ count = tswapal(msgp->msg_iovlen);
++ vec = alloca(count * sizeof(struct iovec));
++ target_vec = tswapal(msgp->msg_iov);
++ lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count,
++ send);
++ msg.msg_iovlen = count;
++ msg.msg_iov = vec;
++
++ if (send) {
++ ret = target_to_host_cmsg(&msg, msgp);
++ if (0 == ret)
++ ret = get_errno(sendmsg(fd, &msg, flags));
++ } else {
++ ret = get_errno(recvmsg(fd, &msg, flags));
++ if (!is_error(ret)) {
++ len = ret;
++ ret = host_to_target_cmsg(msgp, &msg);
++ if (!is_error(ret)) {
++ msgp->msg_namelen = tswap32(msg.msg_namelen);
++ if (msg.msg_name != NULL) {
++ ret = host_to_target_sockaddr(
++ tswapal(msgp->msg_name),
++ msg.msg_name, msg.msg_namelen);
++ if (ret)
++ goto out;
++ }
++ }
++ ret = len;
++ }
++ }
++out:
++ unlock_iovec(vec, target_vec, count, !send);
++ unlock_user_struct(msgp, target_msg, send ? 0 : 1);
++ return (ret);
++}
++
++/* do_accept() must return target values and target errnos. */
++static abi_long
++do_accept(int fd, abi_ulong target_addr, abi_ulong target_addrlen_addr)
++{
++ socklen_t addrlen;
++ void *addr;
++ abi_long ret;
++
++ if (target_addr == 0)
++ return get_errno(accept(fd, NULL, NULL));
++
++ /* return EINVAL if addrlen pointer is invalid */
++ if (get_user_u32(addrlen, target_addrlen_addr))
++ return (-TARGET_EINVAL);
++
++ if ((int)addrlen < 0)
++ return (-TARGET_EINVAL);
++
++ if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
++ return -TARGET_EINVAL;
++
++ addr = alloca(addrlen);
++
++ ret = get_errno(accept(fd, addr, &addrlen));
++ if (!is_error(ret)) {
++ host_to_target_sockaddr(target_addr, addr, addrlen);
++ if (put_user_u32(addrlen, target_addrlen_addr))
++ ret = (-TARGET_EFAULT);
++ }
++ return (ret);
++}
++
++/* do_getpeername() must return target values and target errnos. */
++static abi_long
++do_getpeername(int fd, abi_ulong target_addr, abi_ulong target_addrlen_addr)
++{
++ socklen_t addrlen;
++ void *addr;
++ abi_long ret;
++ if (get_user_u32(addrlen, target_addrlen_addr))
++ return (-TARGET_EFAULT);
++ if ((int)addrlen < 0) {
++ return (-TARGET_EINVAL);
++ }
++ if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
++ return (-TARGET_EFAULT);
++ addr = alloca(addrlen);
++ ret = get_errno(getpeername(fd, addr, &addrlen));
++ if (!is_error(ret)) {
++ host_to_target_sockaddr(target_addr, addr, addrlen);
++ if (put_user_u32(addrlen, target_addrlen_addr))
++ ret = (-TARGET_EFAULT);
++ }
++ return (ret);
++}
++
++/* do_getsockname() must return target values and target errnos. */
++static abi_long
++do_getsockname(int fd, abi_ulong target_addr, abi_ulong target_addrlen_addr)
++{
++ socklen_t addrlen;
++ void *addr;
++ abi_long ret;
++
++ if (get_user_u32(addrlen, target_addrlen_addr))
++ return (-TARGET_EFAULT);
++
++ if ((int)addrlen < 0)
++ return (-TARGET_EINVAL);
++
++ if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
++ return (-TARGET_EFAULT);
++
++ addr = alloca(addrlen);
++
++ ret = get_errno(getsockname(fd, addr, &addrlen));
++ if (!is_error(ret)) {
++ host_to_target_sockaddr(target_addr, addr, addrlen);
++ if (put_user_u32(addrlen, target_addrlen_addr))
++ ret = (-TARGET_EFAULT);
++ }
++ return (ret);
++}
++
++/* do_socketpair() must return target values and target errnos. */
++static abi_long
++do_socketpair(int domain, int type, int protocol, abi_ulong target_tab_addr)
++{
++ int tab[2];
++ abi_long ret;
++
++ ret = get_errno(socketpair(domain, type, protocol, tab));
++ if (!is_error(ret)) {
++ if (put_user_s32(tab[0], target_tab_addr)
++ || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
++ ret = (-TARGET_EFAULT);
++ }
++ return (ret);
++}
++
++/* do_sendto() must return target values and target errnos. */
++static abi_long
++do_sendto(int fd, abi_ulong msg, size_t len, int flags, abi_ulong target_addr,
++ socklen_t addrlen)
++{
++ void *addr;
++ void *host_msg;
++ abi_long ret;
++
++ if ((int)addrlen < 0)
++ return (-TARGET_EINVAL);
++ host_msg = lock_user(VERIFY_READ, msg, len, 1);
++ if (!host_msg)
++ return (-TARGET_EFAULT);
++ if (target_addr) {
++ addr = alloca(addrlen);
++ ret = target_to_host_sockaddr(addr, target_addr, addrlen);
++ if (ret) {
++ unlock_user(host_msg, msg, 0);
++ return (ret);
++ }
++ ret = get_errno(sendto(fd, host_msg, len, flags, addr,
++ addrlen));
++ } else {
++ ret = get_errno(send(fd, host_msg, len, flags));
++ }
++ unlock_user(host_msg, msg, 0);
++ return (ret);
++}
++
++/* do_recvfrom() must return target values and target errnos. */
++static abi_long
++do_recvfrom(int fd, abi_ulong msg, size_t len, int flags, abi_ulong target_addr,
++ abi_ulong target_addrlen)
++{
++ socklen_t addrlen;
++ void *addr;
++ void *host_msg;
++ abi_long ret;
++
++ host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
++ if (!host_msg)
++ return (-TARGET_EFAULT);
++ if (target_addr) {
++ if (get_user_u32(addrlen, target_addrlen)) {
++ ret = -TARGET_EFAULT;
++ goto fail;
++ }
++ if ((int)addrlen < 0) {
++ ret = (-TARGET_EINVAL);
++ goto fail;
++ }
++ addr = alloca(addrlen);
++ ret = get_errno(recvfrom(fd, host_msg, len, flags, addr,
++ &addrlen));
++ } else {
++ addr = NULL; /* To keep compiler quiet. */
++ ret = get_errno(qemu_recv(fd, host_msg, len, flags));
++ }
++ if (!is_error(ret)) {
++ if (target_addr) {
++ host_to_target_sockaddr(target_addr, addr, addrlen);
++ if (put_user_u32(addrlen, target_addrlen)) {
++ ret = -TARGET_EFAULT;
++ goto fail;
++ }
++ }
++ unlock_user(host_msg, msg, len);
++ } else {
++fail:
++ unlock_user(host_msg, msg, 0);
++ }
++ return (ret);
++}
++
++/* do_freebsd_select() must return target values and target errnos. */
++static abi_long
++do_freebsd_select(int n, abi_ulong rfd_addr, abi_ulong wfd_addr,
++ abi_ulong efd_addr, abi_ulong target_tv_addr)
++{
++ fd_set rfds, wfds, efds;
++ fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
++ struct timeval tv, *tv_ptr;
++ abi_long ret;
++
++ if ((ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n)) != 0)
++ return (ret);
++ if ((ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n)) != 0)
++ return (ret);
++ if ((ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n)) != 0)
++ return (ret);
++
++ if (target_tv_addr) {
++ if (copy_from_user_timeval(&tv, target_tv_addr))
++ return (-TARGET_EFAULT);
++ tv_ptr = &tv;
++ } else {
++ tv_ptr = NULL;
++ }
++
++ ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
++
++ if (!is_error(ret)) {
++ if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
++ return (-TARGET_EFAULT);
++ if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
++ return (-TARGET_EFAULT);
++ if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
++ return (-TARGET_EFAULT);
++
++ if (target_tv_addr &&
++ fbsd_copy_to_user_timeval(&tv, target_tv_addr))
++ return (-TARGET_EFAULT);
++ }
++
++ return (ret);
++}
++
++/* do_freebsd_pselect() must return target values and target errnos. */
++static abi_long
++do_freebsd_pselect(int n, abi_ulong rfd_addr, abi_ulong wfd_addr,
++ abi_ulong efd_addr, abi_ulong ts_addr, abi_ulong set_addr)
++{
++ fd_set rfds, wfds, efds;
++ fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
++ sigset_t set, *set_ptr;
++ struct timespec ts, *ts_ptr;
++ void *p;
++ abi_long ret;
++
++ ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
++ if (ret)
++ return (ret);
++ ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
++ if (ret)
++ return (ret);
++ ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
++ if (ret)
++ return (ret);
++
++ /* Unlike select(), pselect() uses struct timespec instead of timeval */
++ if (ts_addr) {
++ if (target_to_host_timespec(&ts, ts_addr))
++ return (-TARGET_EFAULT);
++ ts_ptr = &ts;
++ } else {
++ ts_ptr = NULL;
++ }
++
++ if (set_addr) {
++ if (!(p = lock_user(VERIFY_READ, set_addr,
++ sizeof(target_sigset_t), 1)))
++ return (-TARGET_EFAULT);
++ target_to_host_sigset(&set, p);
++ unlock_user(p, set_addr, 0);
++ set_ptr = &set;
++ } else {
++ set_ptr = NULL;
++ }
++
++ ret = get_errno(pselect(n, rfds_ptr, wfds_ptr, efds_ptr, ts_ptr,
++ set_ptr));
++
++ if (!is_error(ret)) {
++ if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
++ return (-TARGET_EFAULT);
++ if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
++ return (-TARGET_EFAULT);
++ if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
++ return (-TARGET_EFAULT);
++
++ if (ts_addr && host_to_target_timespec(ts_addr, &ts))
++ return (-TARGET_EFAULT);
++ }
++
++ return (ret);
++}
++
++/* do_getsockopt() must return target values and target errnos. */
++static abi_long
++do_getsockopt(int sockfd, int level, int optname, abi_ulong optval_addr,
++ abi_ulong optlen)
++{
++ abi_long ret;
++ int len, val;
++ socklen_t lv;
++
++ switch(level) {
++ case TARGET_SOL_SOCKET:
++ level = SOL_SOCKET;
++ switch (optname) {
++
++ /* These don't just return a single integer */
++ case TARGET_SO_LINGER:
++ case TARGET_SO_RCVTIMEO:
++ case TARGET_SO_SNDTIMEO:
++ case TARGET_SO_ACCEPTFILTER:
++ goto unimplemented;
++
++ /* Options with 'int' argument. */
++ case TARGET_SO_DEBUG:
++ optname = SO_DEBUG;
++ goto int_case;
++
++ case TARGET_SO_REUSEADDR:
++ optname = SO_REUSEADDR;
++ goto int_case;
++
++ case TARGET_SO_REUSEPORT:
++ optname = SO_REUSEPORT;
++ goto int_case;
++
++ case TARGET_SO_TYPE:
++ optname = SO_TYPE;
++ goto int_case;
++
++ case TARGET_SO_ERROR:
++ optname = SO_ERROR;
++ goto int_case;
++
++ case TARGET_SO_DONTROUTE:
++ optname = SO_DONTROUTE;
++ goto int_case;
++
++ case TARGET_SO_BROADCAST:
++ optname = SO_BROADCAST;
++ goto int_case;
++
++ case TARGET_SO_SNDBUF:
++ optname = SO_SNDBUF;
++ goto int_case;
++
++ case TARGET_SO_RCVBUF:
++ optname = SO_RCVBUF;
++ goto int_case;
++
++ case TARGET_SO_KEEPALIVE:
++ optname = SO_KEEPALIVE;
++ goto int_case;
++
++ case TARGET_SO_OOBINLINE:
++ optname = SO_OOBINLINE;
++ goto int_case;
++
++ case TARGET_SO_TIMESTAMP:
++ optname = SO_TIMESTAMP;
++ goto int_case;
++
++ case TARGET_SO_RCVLOWAT:
++ optname = SO_RCVLOWAT;
++ goto int_case;
++
++ case TARGET_SO_LISTENINCQLEN:
++ optname = SO_LISTENINCQLEN;
++ goto int_case;
++
++ default:
++int_case:
++ if (get_user_u32(len, optlen))
++ return (-TARGET_EFAULT);
++ if (len < 0)
++ return (-TARGET_EINVAL);
++ lv = sizeof(lv);
++ ret = get_errno(getsockopt(sockfd, level, optname,
++ &val, &lv));
++ if (ret < 0)
++ return (ret);
++ if (len > lv)
++ len = lv;
++ if (len == 4) {
++ if (put_user_u32(val, optval_addr))
++ return (-TARGET_EFAULT);
++ } else {
++ if (put_user_u8(val, optval_addr))
++ return (-TARGET_EFAULT);
++ }
++ if (put_user_u32(len, optlen))
++ return (-TARGET_EFAULT);
++ break;
++
++ }
++ break;
++
++ default:
++unimplemented:
++ gemu_log("getsockopt level=%d optname=%d not yet supported\n",
++ level, optname);
++ ret = -TARGET_EOPNOTSUPP;
++ break;
++ }
++ return (ret);
++}
++
++/* do_setsockopt() must return target values and target errnos. */
++static abi_long
++do_setsockopt(int sockfd, int level, int optname, abi_ulong optval_addr,
++ socklen_t optlen)
++{
++ int val;
++ abi_long ret;
++
++ switch(level) {
++ case TARGET_SOL_SOCKET:
++ switch (optname) {
++ /* Options with 'int' argument. */
++ case TARGET_SO_DEBUG:
++ optname = SO_DEBUG;
++ break;
++
++ case TARGET_SO_REUSEADDR:
++ optname = SO_REUSEADDR;
++ break;
++
++ case TARGET_SO_REUSEPORT:
++ optname = SO_REUSEADDR;
++ break;
++
++ case TARGET_SO_KEEPALIVE:
++ optname = SO_KEEPALIVE;
++ break;
++
++ case TARGET_SO_DONTROUTE:
++ optname = SO_DONTROUTE;
++ break;
++
++ case TARGET_SO_LINGER:
++ optname = SO_LINGER;
++ break;
++
++ case TARGET_SO_BROADCAST:
++ optname = SO_BROADCAST;
++ break;
++
++ case TARGET_SO_OOBINLINE:
++ optname = SO_OOBINLINE;
++ break;
++
++ case TARGET_SO_SNDBUF:
++ optname = SO_SNDBUF;
++ break;
++
++ case TARGET_SO_RCVBUF:
++ optname = SO_RCVBUF;
++ break;
++
++ case TARGET_SO_SNDLOWAT:
++ optname = SO_RCVLOWAT;
++ break;
++
++ case TARGET_SO_RCVLOWAT:
++ optname = SO_RCVLOWAT;
++ break;
++
++ case TARGET_SO_SNDTIMEO:
++ optname = SO_SNDTIMEO;
++ break;
++
++ case TARGET_SO_RCVTIMEO:
++ optname = SO_RCVTIMEO;
++ break;
++
++ case TARGET_SO_ACCEPTFILTER:
++ goto unimplemented;
++
++ case TARGET_SO_NOSIGPIPE:
++ optname = SO_NOSIGPIPE;
++ break;
++
++ case TARGET_SO_TIMESTAMP:
++ optname = SO_TIMESTAMP;
++ break;
++
++ case TARGET_SO_BINTIME:
++ optname = SO_BINTIME;
++ break;
++
++ case TARGET_SO_ERROR:
++ optname = SO_ERROR;
++ break;
++
++ case TARGET_SO_SETFIB:
++ optname = SO_ERROR;
++ break;
++
++ case TARGET_SO_USER_COOKIE:
++ optname = SO_USER_COOKIE;
++ break;
++
++ default:
++ goto unimplemented;
++ }
++ if (optlen < sizeof(uint32_t))
++ return (-TARGET_EINVAL);
++ if (get_user_u32(val, optval_addr))
++ return (-TARGET_EFAULT);
++ ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val,
++ sizeof(val)));
++ break;
++ default:
++unimplemented:
++ gemu_log("Unsupported setsockopt level=%d optname=%d\n",
++ level, optname);
++ ret = -TARGET_ENOPROTOOPT;
++ }
++
++ return (ret);
++}
++
++static inline abi_long
++target_to_host_sembuf(struct sembuf *host_sembuf, abi_ulong target_addr,
++ unsigned nsops)
++{
++ struct target_sembuf *target_sembuf;
++ int i;
++
++ target_sembuf = lock_user(VERIFY_READ, target_addr,
++ nsops * sizeof(struct target_sembuf), 1);
++ if (!target_sembuf)
++ return (-TARGET_EFAULT);
++
++ for(i=0; i<nsops; i++) {
++ __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
++ __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
++ __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
++ }
++
++ unlock_user(target_sembuf, target_addr, 0);
++
++ return (0);
++}
++
++static inline abi_long
++do_semop(int semid, abi_long ptr, unsigned nsops)
++{
++ struct sembuf sops[nsops];
++
++ if (target_to_host_sembuf(sops, ptr, nsops))
++ return (-TARGET_EFAULT);
++
++ return semop(semid, sops, nsops);
++}
++
++static inline abi_long
++target_to_host_semarray(int semid, unsigned short **host_array,
++ abi_ulong target_addr)
++{
++ int nsems;
++ unsigned short *array;
++ union semun semun;
++ struct semid_ds semid_ds;
++ int i, ret;
++
++ semun.buf = &semid_ds;
++ ret = semctl(semid, 0, IPC_STAT, semun);
++ if (ret == -1)
++ return (get_errno(ret));
++ nsems = semid_ds.sem_nsems;
++ *host_array = malloc(nsems * sizeof(unsigned short));
++ array = lock_user(VERIFY_READ, target_addr,
++ nsems*sizeof(unsigned short), 1);
++ if (!array)
++ return (-TARGET_EFAULT);
++ for(i=0; i<nsems; i++) {
++ __get_user((*host_array)[i], &array[i]);
++ }
++ unlock_user(array, target_addr, 0);
++
++ return (0);
++}
++
++static inline abi_long
++host_to_target_semarray(int semid, abi_ulong target_addr,
++ unsigned short **host_array)
++{
++ int nsems;
++ unsigned short *array;
++ union semun semun;
++ struct semid_ds semid_ds;
++ int i, ret;
++
++ semun.buf = &semid_ds;
++
++ ret = semctl(semid, 0, IPC_STAT, semun);
++ if (ret == -1)
++ return get_errno(ret);
++
++ nsems = semid_ds.sem_nsems;
++
++ array = lock_user(VERIFY_WRITE, target_addr,
++ nsems*sizeof(unsigned short), 0);
++ if (!array)
++ return (-TARGET_EFAULT);
++
++ for(i=0; i<nsems; i++) {
++ __put_user((*host_array)[i], &array[i]);
++ }
++ free(*host_array);
++ unlock_user(array, target_addr, 1);
++
++ return (0);
++}
++
++static inline abi_long
++target_to_host_ipc_perm(struct ipc_perm *host_ip, abi_ulong target_addr)
++{
++ struct target_ipc_perm *target_ip;
++ struct target_semid_ds *target_sd;
++
++ if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
++ return (-TARGET_EFAULT);
++ target_ip = &(target_sd->sem_perm);
++ host_ip->cuid = tswapal(target_ip->cuid);
++ host_ip->cgid = tswapal(target_ip->cgid);
++ host_ip->uid = tswapal(target_ip->uid);
++ host_ip->gid = tswapal(target_ip->gid);
++ host_ip->mode = tswap16(target_ip->mode);
++ host_ip->seq = tswap16(target_ip->seq);
++ host_ip->key = tswapal(target_ip->key);
++ unlock_user_struct(target_sd, target_addr, 0);
++
++ return (0);
++}
++
++static inline abi_long
++host_to_target_ipc_perm(abi_ulong target_addr, struct ipc_perm *host_ip)
++{
++ struct target_ipc_perm *target_ip;
++ struct target_semid_ds *target_sd;
++ if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
++ return (-TARGET_EFAULT);
++ target_ip = &(target_sd->sem_perm);
++ target_ip->cuid = tswapal(host_ip->cuid);
++ target_ip->cgid = tswapal(host_ip->cgid);
++ target_ip->uid = tswapal(host_ip->uid);
++ target_ip->gid = tswapal(host_ip->gid);
++ target_ip->mode = tswap16(host_ip->mode);
++ target_ip->seq = tswap16(host_ip->seq);
++ target_ip->key = tswapal(host_ip->key);
++ unlock_user_struct(target_sd, target_addr, 1);
++ return (0);
++}
++
++static inline abi_long
++target_to_host_semid_ds(struct semid_ds *host_sd, abi_ulong target_addr)
++{
++ struct target_semid_ds *target_sd;
++
++ if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
++ return (-TARGET_EFAULT);
++ if (target_to_host_ipc_perm(&(host_sd->sem_perm), target_addr))
++ return (-TARGET_EFAULT);
++ /* sem_base is not used by kernel for IPC_STAT/IPC_SET */
++ host_sd->sem_base = NULL;
++ host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
++ host_sd->sem_otime = tswapal(target_sd->sem_otime);
++ host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
++ unlock_user_struct(target_sd, target_addr, 0);
++ return (0);
++}
++
++static inline abi_long
++host_to_target_semid_ds(abi_ulong target_addr, struct semid_ds *host_sd)
++{
++ struct target_semid_ds *target_sd;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
++ return (-TARGET_EFAULT);
++ if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
++ return (-TARGET_EFAULT);
++ /* sem_base is not used by kernel for IPC_STAT/IPC_SET */
++ target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
++ target_sd->sem_otime = tswapal(host_sd->sem_otime);
++ target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
++ unlock_user_struct(target_sd, target_addr, 1);
++
++ return (0);
++}
++
++static inline abi_long
++do_semctl(int semid, int semnum, int cmd, union target_semun target_su)
++{
++ union semun arg;
++ struct semid_ds dsarg;
++ unsigned short *array = NULL;
++ abi_long ret = -TARGET_EINVAL;
++ abi_long err;
++
++ cmd &= 0xff;
++
++ switch( cmd ) {
++ case GETVAL:
++ case SETVAL:
++ arg.val = tswap32(target_su.val);
++ ret = get_errno(semctl(semid, semnum, cmd, arg));
++ target_su.val = tswap32(arg.val);
++ break;
++
++ case GETALL:
++ case SETALL:
++ err = target_to_host_semarray(semid, &array, target_su.array);
++ if (err)
++ return (err);
++ arg.array = array;
++ ret = get_errno(semctl(semid, semnum, cmd, arg));
++ err = host_to_target_semarray(semid, target_su.array, &array);
++ if (err)
++ return (err);
++ break;
++
++ case IPC_STAT:
++ case IPC_SET:
++ err = target_to_host_semid_ds(&dsarg, target_su.buf);
++ if (err)
++ return (err);
++ arg.buf = &dsarg;
++ ret = get_errno(semctl(semid, semnum, cmd, arg));
++ err = host_to_target_semid_ds(target_su.buf, &dsarg);
++ if (err)
++ return (err);
++ break;
++
++ case IPC_RMID:
++ case GETPID:
++ case GETNCNT:
++ case GETZCNT:
++ ret = get_errno(semctl(semid, semnum, cmd, NULL));
++ break;
++
++ default:
++ ret = -TARGET_EINVAL;
++ break;
++ }
++ return (ret);
++}
++
++#define N_SHM_REGIONS 32
++
++static struct shm_regions {
++ abi_long start;
++ abi_long size;
++} shm_regions[N_SHM_REGIONS];
++
++static inline abi_ulong
++do_shmat(int shmid, abi_ulong shmaddr, int shmflg)
++{
++ abi_long raddr;
++ void *host_raddr;
++ struct shmid_ds shm_info;
++ int i,ret;
++
++ /* Find out the length of the shared memory segment. */
++ ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
++ if (is_error(ret)) {
++ /* Can't get the length */
++ return (ret);
++ }
++
++ mmap_lock();
++
++ if (shmaddr) {
++ host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
++ } else {
++ abi_ulong mmap_start;
++
++ mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
++
++ if (mmap_start == -1) {
++ errno = ENOMEM;
++ host_raddr = (void *)-1;
++ } else {
++ host_raddr = shmat(shmid, g2h(mmap_start),
++ shmflg /* | SHM_REMAP */);
++ }
++ }
++
++ if (host_raddr == (void *)-1) {
++ mmap_unlock();
++ return get_errno((long)host_raddr);
++ }
++ raddr=h2g((unsigned long)host_raddr);
++
++ page_set_flags(raddr, raddr + shm_info.shm_segsz,
++ PAGE_VALID | PAGE_READ | ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
++
++ for (i = 0; i < N_SHM_REGIONS; i++) {
++ if (shm_regions[i].start == 0) {
++ shm_regions[i].start = raddr;
++ shm_regions[i].size = shm_info.shm_segsz;
++ break;
++ }
++ }
++
++ mmap_unlock();
++ return (raddr);
++}
++
++static inline abi_long
++do_shmdt(abi_ulong shmaddr)
++{
++ int i;
++
++ for (i = 0; i < N_SHM_REGIONS; ++i) {
++ if (shm_regions[i].start == shmaddr) {
++ shm_regions[i].start = 0;
++ page_set_flags(shmaddr,
++ shmaddr + shm_regions[i].size, 0);
++ break;
++ }
++ }
++
++ return ( get_errno(shmdt(g2h(shmaddr))) );
++}
++
++static inline abi_long
++target_to_host_shmid_ds(struct shmid_ds *host_sd, abi_ulong target_addr)
++{
++ struct target_shmid_ds *target_sd;
++
++ if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
++ return (-TARGET_EFAULT);
++ if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
++ return (-TARGET_EFAULT);
++ __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
++ __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
++ __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
++ __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
++ __get_user(host_sd->shm_atime, &target_sd->shm_atime);
++ __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
++ __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
++ unlock_user_struct(target_sd, target_addr, 0);
++ return (0);
++}
++
++static inline abi_long
++host_to_target_shmid_ds(abi_ulong target_addr, struct shmid_ds *host_sd)
++{
++ struct target_shmid_ds *target_sd;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
++ return (-TARGET_EFAULT);
++ if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
++ return (-TARGET_EFAULT);
++ __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
++ __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
++ __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
++ __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
++ __put_user(host_sd->shm_atime, &target_sd->shm_atime);
++ __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
++ __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
++ unlock_user_struct(target_sd, target_addr, 1);
++ return (0);
++}
++
++static inline abi_long
++do_shmctl(int shmid, int cmd, abi_long buff)
++{
++ struct shmid_ds dsarg;
++ abi_long ret = -TARGET_EINVAL;
++
++ cmd &= 0xff;
++
++ switch(cmd) {
++ case IPC_STAT:
++ case IPC_SET:
++ if (target_to_host_shmid_ds(&dsarg, buff))
++ return (-TARGET_EFAULT);
++ ret = get_errno(shmctl(shmid, cmd, &dsarg));
++ if (host_to_target_shmid_ds(buff, &dsarg))
++ return (-TARGET_EFAULT);
++ break;
++
++ case IPC_RMID:
++ ret = get_errno(shmctl(shmid, cmd, NULL));
++ break;
++
++ default:
++ ret = -TARGET_EINVAL;
++ break;
++ }
++
++ return (ret);
++}
++
++static inline abi_long
++target_to_host_msqid_ds(struct msqid_ds *host_md, abi_ulong target_addr)
++{
++ struct target_msqid_ds *target_md;
++
++ if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
++ return (-TARGET_EFAULT);
++ if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
++ return (-TARGET_EFAULT);
++
++ /* msg_first and msg_last are not used by IPC_SET/IPC_STAT in kernel. */
++ host_md->msg_first = host_md->msg_last = NULL;
++
++ host_md->msg_cbytes = tswapal(target_md->msg_cbytes);
++ host_md->msg_qnum = tswapal(target_md->msg_qnum);
++ host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
++ host_md->msg_lspid = tswapal(target_md->msg_lspid);
++ host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
++ host_md->msg_stime = tswapal(target_md->msg_stime);
++ host_md->msg_rtime = tswapal(target_md->msg_rtime);
++ host_md->msg_ctime = tswapal(target_md->msg_ctime);
++ unlock_user_struct(target_md, target_addr, 0);
++
++ return (0);
++}
++
++static inline abi_long
++host_to_target_msqid_ds(abi_ulong target_addr, struct msqid_ds *host_md)
++{
++ struct target_msqid_ds *target_md;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
++ return (-TARGET_EFAULT);
++ if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
++ return (-TARGET_EFAULT);
++
++ /* msg_first and msg_last are not used by IPC_SET/IPC_STAT in kernel. */
++ target_md->msg_cbytes = tswapal(host_md->msg_cbytes);
++ target_md->msg_qnum = tswapal(host_md->msg_qnum);
++ target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
++ target_md->msg_lspid = tswapal(host_md->msg_lspid);
++ target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
++ target_md->msg_stime = tswapal(host_md->msg_stime);
++ target_md->msg_rtime = tswapal(host_md->msg_rtime);
++ target_md->msg_ctime = tswapal(host_md->msg_ctime);
++ unlock_user_struct(target_md, target_addr, 1);
++
++ return (0);
++}
++
++static inline abi_long
++do_msgctl(int msgid, int cmd, abi_long ptr)
++{
++ struct msqid_ds dsarg;
++ abi_long ret = -TARGET_EINVAL;
++
++ cmd &= 0xff;
++
++ switch (cmd) {
++ case IPC_STAT:
++ case IPC_SET:
++ if (target_to_host_msqid_ds(&dsarg,ptr))
++ return -TARGET_EFAULT;
++ ret = get_errno(msgctl(msgid, cmd, &dsarg));
++ if (host_to_target_msqid_ds(ptr,&dsarg))
++ return -TARGET_EFAULT;
++ break;
++
++ case IPC_RMID:
++ ret = get_errno(msgctl(msgid, cmd, NULL));
++ break;
++
++ default:
++ ret = -TARGET_EINVAL;
++ break;
++ }
++ return (ret);
++}
++
++static inline abi_long
++do_msgsnd(int msqid, abi_long msgp, unsigned int msgsz, int msgflg)
++{
++ struct target_msgbuf *target_mb;
++ struct mymsg *host_mb;
++ abi_long ret = 0;
++
++ if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
++ return (-TARGET_EFAULT);
++
++ host_mb = malloc(msgsz+sizeof(long));
++ host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
++ memcpy(host_mb->mtext, target_mb->mtext, msgsz);
++ ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
++ free(host_mb);
++ unlock_user_struct(target_mb, msgp, 0);
++
++ return (ret);
++}
++
++static inline abi_long
++do_msgrcv(int msqid, abi_long msgp, unsigned int msgsz, abi_long msgtyp,
++ int msgflg)
++{
++ struct target_msgbuf *target_mb;
++ char *target_mtext;
++ struct mymsg *host_mb;
++ abi_long ret = 0;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
++ return (-TARGET_EFAULT);
++
++ host_mb = g_malloc(msgsz+sizeof(long));
++ ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapal(msgtyp), msgflg));
++ if (ret > 0) {
++ abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
++ target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr,
++ ret, 0);
++ if (!target_mtext) {
++ ret = -TARGET_EFAULT;
++ goto end;
++ }
++ memcpy(target_mb->mtext, host_mb->mtext, ret);
++ unlock_user(target_mtext, target_mtext_addr, ret);
++ }
++ target_mb->mtype = tswapal(host_mb->mtype);
++end:
++ if (target_mb)
++ unlock_user_struct(target_mb, msgp, 1);
++ g_free(host_mb);
++ return (ret);
++}
++
++static void
++set_second_rval(CPUArchState *env, abi_ulong retval2)
++{
++#if defined(TARGET_ALPHA)
++ ((CPUAlphaState *)env)->ir[IR_A4] = retval2;
++#elif defined(TARGET_ARM)
++ ((CPUARMState *)env)->regs[1] = retval2;
++#elif defined(TARGET_MIPS)
++ ((CPUMIPSState*)env)->active_tc.gpr[3] = retval2;
++#elif defined(TARGET_SH4)
++ ((CPUSH4State*)env)->gregs[1] = retval2;
++#elif defined(TARGET_X86_64) || defined(TARGET_I386)
++ ((CPUX86State*)env)->regs[R_EDX] = retval2;
++#elif defined(TARGET_SPARC64) || defined(TARGET_SPARC)
++ ((CPUSPARCState*)env)->regwptr[1] = retval2;
++#else
++#warning Arch not supported for returning multiple values from syscall.
++#endif
++}
++
++/*
++ * do_fock() must return host values and target errnos (unlike most do_*()
++ * functions.
++ */
++static int
++do_fork(CPUArchState *env, int num, int flags, int *fdp)
++{
++ int ret, fd;
++ abi_ulong child_flag = 0;
++
++ fork_start();
++ switch(num) {
++ case TARGET_FREEBSD_NR_fork:
++ case TARGET_FREEBSD_NR_vfork:
++ ret = fork();
++ break;
++
++ case TARGET_FREEBSD_NR_rfork:
++ ret = rfork(flags);
++ break;
++
++ case TARGET_FREEBSD_NR_pdfork:
++ ret = pdfork(&fd, flags);
++ break;
++
++ default:
++ ret = -TARGET_ENOSYS;
++ break;
++ }
++ if (0 == ret) {
++ /* Child */
++ child_flag = 1;
++ cpu_clone_regs(env, 0);
++ } else {
++ /* Parent */
++ fork_end(0);
++ }
++ if (fdp != NULL)
++ *fdp = fd;
++
++ /*
++ * The fork() syscall sets a child flag in 2nd return value:
++ * 0 for parent process, 1 for child process
++ */
++ set_second_rval(env, child_flag);
++
++ return (ret);
++}
++
++/* 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>. */
++abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
++ abi_long arg2, abi_long arg3, abi_long arg4,
++ abi_long arg5, abi_long arg6, abi_long arg7,
++ abi_long arg8)
++{
++ abi_long ret;
++ void *p;
++ struct stat st;
++
++#ifdef DEBUG
++ gemu_log("freebsd syscall %d\n", num);
++#endif
++ if(do_strace)
++ print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
++
++ switch(num) {
++ case TARGET_FREEBSD_NR_exit:
++#ifdef TARGET_GPROF
++ _mcleanup();
++#endif
++ gdb_exit(cpu_env, arg1);
++ /* XXX: should free thread stack and CPU env */
++ _exit(arg1);
++ ret = 0; /* avoid warning */
++ break;
++ case TARGET_FREEBSD_NR_read:
++ if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
++ goto efault;
++ ret = get_errno(read(arg1, p, arg3));
++ unlock_user(p, arg2, ret);
++ break;
++
++ case TARGET_FREEBSD_NR_readv:
++ {
++ int count = arg3;
++ struct iovec *vec;
++
++ vec = alloca(count * sizeof(struct iovec));
++ if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
++ goto efault;
++ ret = get_errno(readv(arg1, vec, count));
++ unlock_iovec(vec, arg2, count, 1);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_pread:
++ if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
++ goto efault;
++ ret = get_errno(pread(arg1, p, arg3, target_offset64(arg4, arg5)));
++ unlock_user(p, arg2, ret);
++ break;
++
++ case TARGET_FREEBSD_NR_preadv:
++ {
++ int count = arg3;
++ struct iovec *vec;
++
++ vec = alloca(count * sizeof(struct iovec));
++ if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
++ goto efault;
++ ret = get_errno(preadv(arg1, vec, count,
++ target_offset64(arg4, arg5)));
++ unlock_iovec(vec, arg2, count, 1);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_write:
++ if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
++ goto efault;
++ ret = get_errno(write(arg1, p, arg3));
++ unlock_user(p, arg2, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_writev:
++ {
++ int count = arg3;
++ struct iovec *vec;
++
++ vec = alloca(count * sizeof(struct iovec));
++ if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
++ goto efault;
++ ret = get_errno(writev(arg1, vec, count));
++ unlock_iovec(vec, arg2, count, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_pwrite:
++ if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
++ goto efault;
++ ret = get_errno(pwrite(arg1, p, arg3, target_offset64(arg4, arg5)));
++ unlock_user(p, arg2, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_pwritev:
++ {
++ int count = arg3;
++ struct iovec *vec;
++
++ vec = alloca(count * sizeof(struct iovec));
++ if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
++ goto efault;
++ ret = get_errno(pwritev(arg1, vec, count,
++ target_offset64(arg4, arg5)));
++ unlock_iovec(vec, arg2, count, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_open:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(open(path(p),
++ target_to_host_bitmask(arg2, fcntl_flags_tbl),
++ arg3));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_openat:
++ if (!(p = lock_user_string(arg2)))
++ goto efault;
++ ret = get_errno(openat(arg1, path(p),
++ target_to_host_bitmask(arg3, fcntl_flags_tbl),
++ arg4));
++ unlock_user(p, arg2, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_close:
++ ret = get_errno(close(arg1));
++ break;
++
++ case TARGET_FREEBSD_NR_closefrom:
++ ret = 0;
++ closefrom(arg1);
++ break;
++
++#ifdef TARGET_FREEBSD_NR_creat
++ case TARGET_FREEBSD_NR_creat:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(creat(p, arg2));
++ unlock_user(p, arg1, 0);
++ break;
++#endif
++
++ case TARGET_FREEBSD_NR_mmap:
++ ret = get_errno(target_mmap(arg1, arg2, arg3,
++ target_to_host_bitmask(arg4, mmap_flags_tbl),
++ arg5,
++ arg6));
++ break;
++
++ case TARGET_FREEBSD_NR_munmap:
++ ret = get_errno(target_munmap(arg1, arg2));
++ break;
++
++ case TARGET_FREEBSD_NR_mprotect:
++ ret = get_errno(target_mprotect(arg1, arg2, arg3));
++ break;
++
++ case TARGET_FREEBSD_NR_msync:
++ ret = get_errno(msync(g2h(arg1), arg2, arg3));
++ break;
++
++ case TARGET_FREEBSD_NR_mlock:
++ ret = get_errno(mlock(g2h(arg1), arg2));
++ break;
++
++ case TARGET_FREEBSD_NR_munlock:
++ ret = get_errno(munlock(g2h(arg1), arg2));
++ break;
++
++ case TARGET_FREEBSD_NR_mlockall:
++ ret = get_errno(mlockall(arg1));
++ break;
++
++ case TARGET_FREEBSD_NR_munlockall:
++ ret = get_errno(munlockall());
++ break;
++
++ case TARGET_FREEBSD_NR_madvise:
++ /*
++ * A straight passthrough may not be safe because qemu sometimes
++ * turns private file-backed mapping into anonymous mappings. This
++ * will break MADV_DONTNEED. This is a hint, so ignoring and returing
++ * success is ok.
++ */
++ ret = get_errno(0);
++ break;
++
++ case TARGET_FREEBSD_NR_break:
++ ret = do_obreak(arg1);
++ break;
++#ifdef __FreeBSD__
++ case TARGET_FREEBSD_NR___sysctl:
++ ret = do_freebsd_sysctl(arg1, arg2, arg3, arg4, arg5, arg6);
++ break;
++#endif
++ case TARGET_FREEBSD_NR_sysarch:
++ ret = do_freebsd_sysarch(cpu_env, arg1, arg2);
++ break;
++ case TARGET_FREEBSD_NR_syscall:
++ case TARGET_FREEBSD_NR___syscall:
++ ret = do_freebsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,arg7,arg8,0);
++ break;
++
++ case TARGET_FREEBSD_NR_stat:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(stat(path(p), &st));
++ unlock_user(p, arg1, 0);
++ goto do_stat;
++
++ case TARGET_FREEBSD_NR_lstat:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(lstat(path(p), &st));
++ unlock_user(p, arg1, 0);
++ goto do_stat;
++
++ case TARGET_FREEBSD_NR_nstat:
++ case TARGET_FREEBSD_NR_nfstat:
++ case TARGET_FREEBSD_NR_nlstat:
++ ret = unimplemented(num);
++ break;
++
++ case TARGET_FREEBSD_NR_fstat:
++ {
++ ret = get_errno(fstat(arg1, &st));
++
++do_stat:
++ if (!is_error(ret)) {
++ struct target_freebsd_stat *target_st;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
++ goto efault;
++ memset(target_st, 0, sizeof(*target_st));
++ __put_user(st.st_dev, &target_st->st_dev);
++ __put_user(st.st_ino, &target_st->st_ino);
++ __put_user(st.st_mode, &target_st->st_mode);
++ __put_user(st.st_nlink, &target_st->st_nlink);
++ __put_user(st.st_uid, &target_st->st_uid);
++ __put_user(st.st_gid, &target_st->st_gid);
++ __put_user(st.st_rdev, &target_st->st_rdev);
++ __put_user(st.st_atim.tv_sec, &target_st->st_atim.tv_sec);
++ __put_user(st.st_atim.tv_nsec, &target_st->st_atim.tv_nsec);
++ __put_user(st.st_mtim.tv_sec, &target_st->st_mtim.tv_sec);
++ __put_user(st.st_mtim.tv_nsec, &target_st->st_mtim.tv_nsec);
++ __put_user(st.st_ctim.tv_sec, &target_st->st_ctim.tv_sec);
++ __put_user(st.st_ctim.tv_nsec, &target_st->st_ctim.tv_nsec);
++ __put_user(st.st_size, &target_st->st_size);
++ __put_user(st.st_blocks, &target_st->st_blocks);
++ __put_user(st.st_blksize, &target_st->st_blksize);
++ __put_user(st.st_flags, &target_st->st_flags);
++ __put_user(st.st_gen, &target_st->st_gen);
++ /* st_lspare not used */
++ __put_user(st.st_birthtim.tv_sec,
++ &target_st->st_birthtim.tv_sec);
++ __put_user(st.st_birthtim.tv_nsec,
++ &target_st->st_birthtim.tv_nsec);
++ unlock_user_struct(target_st, arg2, 1);
++ }
++
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_nanosleep:
++ {
++ struct timespec req, rem;
++
++ target_to_host_timespec(&req, arg1);
++ ret = get_errno(nanosleep(&req, &rem));
++ if (is_error(ret) && arg2)
++ host_to_target_timespec(arg2, &rem);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_clock_gettime:
++ {
++ struct timespec ts;
++
++ ret = get_errno(clock_gettime(arg1, &ts));
++ if (!is_error(ret)) {
++ if (host_to_target_timespec(arg2, &ts))
++ goto efault;
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_clock_getres:
++ {
++ struct timespec ts;
++
++ ret = get_errno(clock_getres(arg1, &ts));
++ if (!is_error(ret)) {
++ if (host_to_target_timespec(arg2, &ts))
++ goto efault;
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_clock_settime:
++ {
++ struct timespec ts;
++
++ if (target_to_host_timespec(&ts, arg2) != 0)
++ goto efault;
++ ret = get_errno(clock_settime(arg1, &ts));
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_gettimeofday:
++ {
++ struct timeval tv;
++ struct timezone tz, *target_tz;
++ if (arg2 != 0) {
++ if (!lock_user_struct(VERIFY_READ, target_tz, arg2, 0))
++ goto efault;
++ __get_user(tz.tz_minuteswest,
++ &target_tz->tz_minuteswest);
++ __get_user(tz.tz_dsttime, &target_tz->tz_dsttime);
++ unlock_user_struct(target_tz, arg2, 1);
++ }
++ ret = get_errno(gettimeofday(&tv, arg2 != 0 ? &tz : NULL));
++ if (!is_error(ret)) {
++ if (fbsd_copy_to_user_timeval(&tv, arg1))
++ goto efault;
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_settimeofday:
++ {
++ struct timeval tv;
++ struct timezone tz, *target_tz;
++
++ if (arg2 != 0) {
++ if (!lock_user_struct(VERIFY_READ, target_tz, arg2, 0))
++ goto efault;
++ __get_user(tz.tz_minuteswest,
++ &target_tz->tz_minuteswest);
++ __get_user(tz.tz_dsttime, &target_tz->tz_dsttime);
++ unlock_user_struct(target_tz, arg2, 1);
++ }
++ if (copy_from_user_timeval(&tv, arg1))
++ goto efault;
++ ret = get_errno(settimeofday(&tv, arg2 != 0 ? & tz : NULL));
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_ktimer_create:
++ case TARGET_FREEBSD_NR_ktimer_delete:
++ case TARGET_FREEBSD_NR_ktimer_settime:
++ case TARGET_FREEBSD_NR_ktimer_gettime:
++ case TARGET_FREEBSD_NR_ktimer_getoverrun:
++ case TARGET_FREEBSD_NR_minherit:
++ ret = unimplemented(num);
++ break;
++
++ case TARGET_FREEBSD_NR_kqueue:
++ ret = get_errno(kqueue());
++ break;
++
++#ifdef __FreeBSD__
++ case TARGET_FREEBSD_NR_kevent:
++ {
++ struct kevent *changelist = NULL, *eventlist = NULL;
++ struct target_kevent *target_changelist, *target_eventlist;
++ struct timespec ts;
++ int i;
++
++ if (arg3 != 0) {
++ if (!(target_changelist = lock_user(VERIFY_READ, arg2,
++ sizeof(struct target_kevent) * arg3, 1)))
++ goto efault;
++ changelist = alloca(sizeof(struct kevent) * arg3);
++
++ for (i = 0; i < arg3; i++) {
++ __get_user(changelist[i].ident, &target_changelist[i].ident);
++ __get_user(changelist[i].filter, &target_changelist[i].filter);
++ __get_user(changelist[i].flags, &target_changelist[i].flags);
++ __get_user(changelist[i].fflags, &target_changelist[i].fflags);
++ __get_user(changelist[i].data, &target_changelist[i].data);
++ /* XXX: This is broken when running a 64bits target on a 32bits host */
++ /* __get_user(changelist[i].udata, &target_changelist[i].udata); */
++#if TARGET_ABI_BITS == 32
++ changelist[i].udata = (void *)(uintptr_t)target_changelist[i].udata;
++ tswap32s((uint32_t *)&changelist[i].udata);
++#else
++ changelist[i].udata = (void *)(uintptr_t)target_changelist[i].udata;
++ tswap64s((uint64_t *)&changelist[i].udata);
++#endif
++ }
++ unlock_user(target_changelist, arg2, 0);
++ }
++
++ if (arg5 != 0)
++ eventlist = alloca(sizeof(struct kevent) * arg5);
++ if (arg6 != 0)
++ if (target_to_host_timespec(&ts, arg6))
++ goto efault;
++ ret = get_errno(kevent(arg1, changelist, arg3, eventlist, arg5,
++ arg6 != 0 ? &ts : NULL));
++ if (!is_error(ret)) {
++ if (!(target_eventlist = lock_user(VERIFY_WRITE, arg4,
++ sizeof(struct target_kevent) * arg5, 0)))
++ goto efault;
++ for (i = 0; i < arg5; i++) {
++ __put_user(eventlist[i].ident, &target_eventlist[i].ident);
++ __put_user(eventlist[i].filter, &target_eventlist[i].filter);
++ __put_user(eventlist[i].flags, &target_eventlist[i].flags);
++ __put_user(eventlist[i].fflags, &target_eventlist[i].fflags);
++ __put_user(eventlist[i].data, &target_eventlist[i].data);
++ /* __put_user(eventlist[i].udata, &target_eventlist[i].udata); */
++#if TARGET_ABI_BITS == 32
++ tswap32s((uint32_t *)&eventlist[i].data);
++ target_eventlist[i].data = (uintptr_t)eventlist[i].data;
++#else
++ tswap64s((uint64_t *)&eventlist[i].data);
++ target_eventlist[i].data = (uintptr_t)eventlist[i].data;
++#endif
++ }
++ unlock_user(target_eventlist, arg4, sizeof(struct target_kevent) * arg5);
++
++
++ }
++ }
++ break;
++#endif
++
++ case TARGET_FREEBSD_NR_execve:
++ {
++ char **argp, **envp;
++ int argc, envc;
++ abi_ulong gp;
++ abi_ulong guest_argp;
++ abi_ulong guest_envp;
++ abi_ulong addr;
++ char **q;
++ int total_size = 0;
++
++ argc = 0;
++ guest_argp = arg2;
++ for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
++ if (get_user_ual(addr, gp))
++ goto efault;
++ if (!addr)
++ break;
++ argc++;
++ }
++ envc = 0;
++ guest_envp = arg3;
++ for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
++ if (get_user_ual(addr, gp))
++ goto efault;
++ if (!addr)
++ break;
++ envc++;
++ }
++
++ argp = alloca((argc + 1) * sizeof(void *));
++ envp = alloca((envc + 1) * sizeof(void *));
++
++ for (gp = guest_argp, q = argp; gp;
++ gp += sizeof(abi_ulong), q++) {
++ if (get_user_ual(addr, gp))
++ goto execve_efault;
++ if (!addr)
++ break;
++ if (!(*q = lock_user_string(addr)))
++ goto execve_efault;
++ total_size += strlen(*q) + 1;
++ }
++ *q = NULL;
++
++ for (gp = guest_envp, q = envp; gp;
++ gp += sizeof(abi_ulong), q++) {
++ if (get_user_ual(addr, gp))
++ goto execve_efault;
++ if (!addr)
++ break;
++ if (!(*q = lock_user_string(addr)))
++ goto execve_efault;
++ total_size += strlen(*q) + 1;
++ }
++ *q = NULL;
++
++ /* This case will not be caught by the host's execve() if its
++ page size is bigger than the target's. */
++ if (total_size > MAX_ARG_PAGES * TARGET_PAGE_SIZE) {
++ ret = -TARGET_E2BIG;
++ goto execve_end;
++ }
++ if (!(p = lock_user_string(arg1)))
++ goto execve_efault;
++ ret = get_errno(execve(p, argp, envp));
++ unlock_user(p, arg1, 0);
++
++ goto execve_end;
++
++ execve_efault:
++ ret = -TARGET_EFAULT;
++
++ execve_end:
++ 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;
++ unlock_user(*q, addr, 0);
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_pipe:
++ {
++ int host_pipe[2];
++ int host_ret = pipe(host_pipe);
++
++ if (!is_error(host_ret)) {
++ set_second_rval(cpu_env, host_pipe[1]);
++ ret = host_pipe[0];
++ } else
++ ret = get_errno(host_ret);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_lseek:
++ {
++#if defined(TARGET_MIPS) && TARGET_ABI_BITS == 32
++ /* 32-bit MIPS uses two 32 registers for 64 bit arguments */
++ int64_t res = lseek(arg1, target_offset64(arg2, arg3), arg4);
++
++ if (res == -1) {
++ ret = get_errno(res);
++ } else {
++ ret = res & 0xFFFFFFFF;
++ ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] =
++ (res >> 32) & 0xFFFFFFFF;
++ }
++#else
++ ret = get_errno(lseek(arg1, arg2, arg3));
++#endif
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_select:
++ ret = do_freebsd_select(arg1, arg2, arg3, arg4, arg5);
++ break;
++
++ case TARGET_FREEBSD_NR_pselect:
++ ret = do_freebsd_pselect(arg1, arg2, arg3, arg4, arg5, arg6);
++ break;
++
++ case TARGET_FREEBSD_NR_poll:
++ {
++ nfds_t i, nfds = arg2;
++ int timeout = arg3;
++ struct pollfd *pfd;
++ struct target_pollfd *target_pfd = lock_user(VERIFY_WRITE, arg1,
++ sizeof(struct target_pollfd) * nfds, 1);
++
++ if (!target_pfd)
++ goto efault;
++
++ pfd = alloca(sizeof(struct pollfd) * nfds);
++ for(i = 0; i < nfds; i++) {
++ pfd[i].fd = tswap32(target_pfd[i].fd);
++ pfd[i].events = tswap16(target_pfd[i].events);
++ }
++ ret = get_errno(poll(pfd, nfds, timeout));
++
++ if (!is_error(ret)) {
++ for(i = 0; i < nfds; i++) {
++ target_pfd[i].revents = tswap16(pfd[i].revents);
++ }
++ }
++ unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) *
++ nfds);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_openbsd_poll:
++ ret = unimplemented(num);
++ break;
++
++ case TARGET_FREEBSD_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))
++ goto 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);
++ ret = get_errno(setrlimit(resource, &rlim));
++ }
++ break;
++
++
++ case TARGET_FREEBSD_NR_getrlimit:
++ {
++ int resource = target_to_host_resource(arg1);
++ struct target_rlimit *target_rlim;
++ struct rlimit rlim;
++
++ ret = get_errno(getrlimit(resource, &rlim));
++ if (!is_error(ret)) {
++ if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2,
++ 0))
++ goto 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);
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_setitimer:
++ {
++ struct itimerval value, ovalue, *pvalue;
++
++ if (arg2) {
++ pvalue = &value;
++ if (copy_from_user_timeval(&pvalue->it_interval,
++ arg2) || copy_from_user_timeval(
++ &pvalue->it_value, arg2 +
++ sizeof(struct target_timeval)))
++ goto efault;
++ } else {
++ pvalue = NULL;
++ }
++ ret = get_errno(setitimer(arg1, pvalue, &ovalue));
++ if (!is_error(ret) && arg3) {
++ if (fbsd_copy_to_user_timeval(&ovalue.it_interval, arg3)
++ || fbsd_copy_to_user_timeval(&ovalue.it_value,
++ arg3 + sizeof(struct target_timeval)))
++ goto efault;
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_getitimer:
++ {
++ struct itimerval value;
++
++ ret = get_errno(getitimer(arg1, &value));
++ if (!is_error(ret) && arg2) {
++ if (fbsd_copy_to_user_timeval(&value.it_interval, arg2)
++ || fbsd_copy_to_user_timeval(&value.it_value,
++ arg2 + sizeof(struct target_timeval)))
++ goto efault;
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_utimes:
++ {
++ struct timeval *tvp, tv[2];
++
++ if (arg2) {
++ if (copy_from_user_timeval(&tv[0], arg2)
++ || copy_from_user_timeval(&tv[1],
++ arg2 + sizeof(struct target_timeval)))
++
++ goto efault;
++ tvp = tv;
++ } else {
++ tvp = NULL;
++ }
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(utimes(p, tvp));
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_lutimes:
++ {
++ struct timeval *tvp, tv[2];
++
++ if (arg2) {
++ if (copy_from_user_timeval(&tv[0], arg2)
++ || copy_from_user_timeval(&tv[1],
++ arg2 + sizeof(struct target_timeval)))
++
++ goto efault;
++ tvp = tv;
++ } else {
++ tvp = NULL;
++ }
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(lutimes(p, tvp));
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_futimes:
++ {
++ struct timeval *tvp, tv[2];
++
++ if (arg2) {
++ if (copy_from_user_timeval(&tv[0], arg2)
++ || copy_from_user_timeval(&tv[1],
++ arg2 + sizeof(struct target_timeval)))
++ goto efault;
++ tvp = tv;
++ } else {
++ tvp = NULL;
++ }
++ ret = get_errno(futimes(arg1, tvp));
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_futimesat:
++ {
++ struct timeval *tvp, tv[2];
++
++ if (arg3) {
++ if (copy_from_user_timeval(&tv[0], arg3)
++ || copy_from_user_timeval(&tv[1],
++ arg3 + sizeof(struct target_timeval)))
++ goto efault;
++ tvp = tv;
++ } else {
++ tvp = NULL;
++ }
++ if (!(p = lock_user_string(arg2)))
++ goto efault;
++ ret = get_errno(futimesat(arg1, path(p), tvp));
++ unlock_user(p, arg2, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_access:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(access(path(p), arg2));
++ unlock_user(p, arg1, 0);
++
++ case TARGET_FREEBSD_NR_eaccess:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(eaccess(path(p), arg2));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_faccessat:
++ if (!(p = lock_user_string(arg2)))
++ goto efault;
++ ret = get_errno(faccessat(arg1, p, arg3, arg4));
++ unlock_user(p, arg2, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_chdir:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(chdir(p));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_fchdir:
++ ret = get_errno(fchdir(arg1));
++ break;
++
++ case TARGET_FREEBSD_NR_rename:
++ {
++ void *p2;
++
++ p = lock_user_string(arg1);
++ p2 = lock_user_string(arg2);
++ if (!p || !p2)
++ ret = -TARGET_EFAULT;
++ else
++ ret = get_errno(rename(p, p2));
++ unlock_user(p2, arg2, 0);
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_renameat:
++ {
++ void *p2;
++
++ p = lock_user_string(arg2);
++ p2 = lock_user_string(arg4);
++ if (!p || !p2)
++ ret = -TARGET_EFAULT;
++ else
++ ret = get_errno(renameat(arg1, p, arg3, p2));
++ unlock_user(p2, arg4, 0);
++ unlock_user(p, arg2, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_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);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_linkat:
++ {
++ void * p2 = NULL;
++
++ if (!arg2 || !arg4)
++ goto 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);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_unlink:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(unlink(p));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_unlinkat:
++ if (!(p = lock_user_string(arg2)))
++ goto efault;
++ ret = get_errno(unlinkat(arg1, p, arg3));
++ unlock_user(p, arg2, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_mkdir:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(mkdir(p, arg2));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_mkdirat:
++ if (!(p = lock_user_string(arg2)))
++ goto efault;
++ ret = get_errno(mkdirat(arg1, p, arg3));
++ unlock_user(p, arg2, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_rmdir:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(rmdir(p));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR___getcwd:
++ if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
++ goto efault;
++ ret = get_errno(__getcwd(p, arg2));
++ unlock_user(p, arg1, ret);
++ break;
++
++ case TARGET_FREEBSD_NR_dup:
++ ret = get_errno(dup(arg1));
++ break;
++
++ case TARGET_FREEBSD_NR_dup2:
++ ret = get_errno(dup2(arg1, arg2));
++ break;
++
++ case TARGET_FREEBSD_NR_truncate:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ if (regpairs_aligned(cpu_env)) {
++ arg2 = arg3;
++ arg3 = arg4;
++ }
++ ret = get_errno(truncate(p, target_offset64(arg2, arg3)));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_ftruncate:
++ if (regpairs_aligned(cpu_env)) {
++ arg2 = arg3;
++ arg3 = arg4;
++ }
++ ret = get_errno(ftruncate(arg1, target_offset64(arg2, arg3)));
++ break;
++
++ case TARGET_FREEBSD_NR_acct:
++ if (arg1 == 0) {
++ ret = get_errno(acct(NULL));
++ } else {
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(acct(path(p)));
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_sync:
++ sync();
++ ret = 0;
++ break;
++
++ case TARGET_FREEBSD_NR_mount:
++ {
++ void *p2;
++
++ /* We need to look at the data field. */
++ p = lock_user_string(arg1); /* type */
++ p2 = lock_user_string(arg2); /* dir */
++ if (!p || !p2)
++ ret = -TARGET_EFAULT;
++ else {
++ /*
++ * XXX arg5 should be locked, but it isn't clear
++ * how to do that since it's it may be not be a
++ * NULL-terminated string.
++ */
++ if ( ! arg5 )
++ ret = get_errno(mount(p, p2, arg3, NULL));
++ else
++ ret = get_errno(mount(p, p2, arg3, g2h(arg5)));
++ }
++ unlock_user(p, arg1, 0);
++ unlock_user(p2, arg1, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_unmount:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(unmount(p, arg2));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_nmount:
++ {
++ int count = arg2;
++ struct iovec *vec;
++
++ vec = alloca(count * sizeof(struct iovec));
++ if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
++ goto efault;
++ ret = get_errno(nmount(vec, count, arg3));
++ unlock_iovec(vec, arg2, count, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_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);
++ }
++ break;
++
++ case TARGET_FREEBSD_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);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_readlink:
++ {
++ void *p2;
++
++ p = lock_user_string(arg1);
++ p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
++ if (!p || !p2)
++ ret = -TARGET_EFAULT;
++ else
++ ret = get_errno(readlink(path(p), p2, arg3));
++ unlock_user(p2, arg2, ret);
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_readlinkat:
++ {
++ void *p2;
++ p = lock_user_string(arg2);
++ p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
++
++ if (!p || !p2)
++ ret = -TARGET_EFAULT;
++ else
++ ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
++ unlock_user(p2, arg3, ret);
++ unlock_user(p, arg2, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_chmod:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(chmod(p, arg2));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_fchmod:
++ ret = get_errno(fchmod(arg1, arg2));
++ break;
++
++ case TARGET_FREEBSD_NR_lchmod:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(lchmod(p, arg2));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_fchmodat:
++ if (!(p = lock_user_string(arg2)))
++ goto efault;
++ ret = get_errno(fchmodat(arg1, p, arg3, arg4));
++ unlock_user(p, arg2, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_mknod:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(mknod(p, arg2, arg3));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_mknodat:
++ if (!(p = lock_user_string(arg2)))
++ goto efault;
++ ret = get_errno(mknodat(arg1, p, arg3, arg4));
++ unlock_user(p, arg2, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_chown:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(chown(p, arg2, arg3));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_fchown:
++ ret = get_errno(fchown(arg1, arg2, arg3));
++ break;
++
++ case TARGET_FREEBSD_NR_lchown:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(lchown(p, arg2, arg3));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_fchownat:
++ if (!(p = lock_user_string(arg2)))
++ goto efault;
++ ret = get_errno(fchownat(arg1, p, arg3, arg4, arg5));
++ unlock_user(p, arg2, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_chflags:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(chflags(p, arg2));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_lchflags:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(lchflags(p, arg2));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_fchflags:
++ ret = get_errno(fchflags(arg1, arg2));
++ break;
++
++ case TARGET_FREEBSD_NR_getgroups:
++ {
++ int gidsetsize = arg1;
++ uint32_t *target_grouplist;
++ gid_t *grouplist;
++ int i;
++
++ grouplist = alloca(gidsetsize * sizeof(gid_t));
++ ret = get_errno(getgroups(gidsetsize, grouplist));
++ if (gidsetsize == 0)
++ break;
++ if (!is_error(ret)) {
++ target_grouplist = lock_user(VERIFY_WRITE, arg2,
++ gidsetsize * 2, 0);
++ if (!target_grouplist)
++ goto efault;
++ for (i = 0;i < ret; i++)
++ target_grouplist[i] = tswap32(grouplist[i]);
++ unlock_user(target_grouplist, arg2, gidsetsize * 2);
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_setgroups:
++ {
++ int gidsetsize = arg1;
++ uint32_t *target_grouplist;
++ gid_t *grouplist;
++ int i;
++
++ grouplist = alloca(gidsetsize * sizeof(gid_t));
++ target_grouplist = lock_user(VERIFY_READ, arg2,
++ gidsetsize * 2, 1);
++ if (!target_grouplist) {
++ ret = -TARGET_EFAULT;
++ goto fail;
++ }
++ for(i = 0;i < gidsetsize; i++)
++ grouplist[i] = tswap32(target_grouplist[i]);
++ unlock_user(target_grouplist, arg2, 0);
++ ret = get_errno(setgroups(gidsetsize, grouplist));
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_umask:
++ ret = get_errno(umask(arg1));
++ break;
++
++ case TARGET_FREEBSD_NR_fcntl:
++ {
++ int host_cmd;
++ struct flock fl;
++ struct target_flock *target_fl;
++
++ host_cmd = target_to_host_fcntl_cmd(arg2);
++ if (-TARGET_EINVAL == host_cmd) {
++ ret = host_cmd;
++ break;
++ }
++
++ switch(arg2) {
++ case TARGET_F_GETLK:
++ if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
++ return (-TARGET_EFAULT);
++ fl.l_type = tswap16(target_fl->l_type);
++ fl.l_whence = tswap16(target_fl->l_whence);
++ fl.l_start = tswapal(target_fl->l_start);
++ fl.l_len = tswapal(target_fl->l_len);
++ fl.l_pid = tswap32(target_fl->l_pid);
++ fl.l_sysid = tswap32(target_fl->l_sysid);
++ unlock_user_struct(target_fl, arg3, 0);
++ ret = get_errno(fcntl(arg1, host_cmd, &fl));
++ if (0 == ret) {
++ if (!lock_user_struct(VERIFY_WRITE, target_fl,
++ arg3, 0))
++ return (-TARGET_EFAULT);
++ target_fl->l_type = tswap16(fl.l_type);
++ target_fl->l_whence = tswap16(fl.l_whence);
++ target_fl->l_start = tswapal(fl.l_start);
++ target_fl->l_len = tswapal(fl.l_len);
++ target_fl->l_pid = tswap32(fl.l_pid);
++ target_fl->l_sysid = tswap32(fl.l_sysid);
++ unlock_user_struct(target_fl, arg3, 1);
++ }
++ break;
++
++ case TARGET_F_SETLK:
++ case TARGET_F_SETLKW:
++ if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
++ return (-TARGET_EFAULT);
++ fl.l_type = tswap16(target_fl->l_type);
++ fl.l_whence = tswap16(target_fl->l_whence);
++ fl.l_start = tswapal(target_fl->l_start);
++ fl.l_len = tswapal(target_fl->l_len);
++ fl.l_pid = tswap32(target_fl->l_pid);
++ fl.l_sysid = tswap32(target_fl->l_sysid);
++ unlock_user_struct(target_fl, arg3, 0);
++ ret = get_errno(fcntl(arg1, host_cmd, &fl));
++ break;
++
++ case TARGET_F_DUPFD:
++ case TARGET_F_DUP2FD:
++ case TARGET_F_GETOWN:
++ case TARGET_F_SETOWN:
++ case TARGET_F_GETFD:
++ case TARGET_F_SETFD:
++ case TARGET_F_GETFL:
++ case TARGET_F_SETFL:
++ case TARGET_F_READAHEAD:
++ case TARGET_F_RDAHEAD:
++ default:
++ ret = get_errno(fcntl(arg1, host_cmd, arg3));
++ break;
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_getdents:
++ {
++ struct dirent *dirp;
++ int32_t nbytes = arg3;
++
++ if (!(dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0)))
++ goto efault;
++ ret = get_errno(getdents(arg1, (char *)dirp, nbytes));
++ if (!is_error(ret)) {
++ struct dirent *de;
++ int len = ret;
++ int reclen;
++
++ de = dirp;
++ while (len > 0) {
++ reclen = de->d_reclen;
++ if (reclen > len)
++ break;
++ de->d_reclen = tswap16(reclen);
++ len -= reclen;
++ }
++ }
++ unlock_user(dirp, arg2, ret);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_getdirentries:
++ {
++ struct dirent *dirp;
++ int32_t nbytes = arg3;
++ long basep;
++
++ if (!(dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0)))
++ goto efault;
++ ret = get_errno(getdirentries(arg1, (char *)dirp, nbytes,
++ &basep));
++ if (!is_error(ret)) {
++ struct dirent *de;
++ int len = ret;
++ int reclen;
++
++ de = dirp;
++ while (len > 0) {
++ reclen = de->d_reclen;
++ if (reclen > len)
++ break;
++ de->d_reclen = tswap16(reclen);
++ len -= reclen;
++ }
++ }
++ unlock_user(dirp, arg2, ret);
++ if (arg4)
++ if (put_user(nbytes, arg4, abi_ulong))
++ ret = -TARGET_EFAULT;
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_chroot:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(chroot(p));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_flock:
++ ret = get_errno(flock(arg1, arg2));
++ break;
++
++ case TARGET_FREEBSD_NR_mkfifo:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(mkfifo(p, arg2));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_mkfifoat:
++ if (!(p = lock_user_string(arg2)))
++ goto efault;
++ ret = get_errno(mkfifoat(arg1, p, arg2));
++ unlock_user(p, arg2, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_pathconf:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(pathconf(p, arg2));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_lpathconf:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(lpathconf(p, arg2));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_fpathconf:
++ ret = get_errno(fpathconf(arg1, arg2));
++ break;
++
++ case TARGET_FREEBSD_NR_undelete:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(undelete(p));
++ unlock_user(p, arg1, 0);
++ break;
++
++
++ case TARGET_FREEBSD_NR___acl_get_file:
++ case TARGET_FREEBSD_NR___acl_set_file:
++ case TARGET_FREEBSD_NR___acl_get_fd:
++ case TARGET_FREEBSD_NR___acl_set_fd:
++ case TARGET_FREEBSD_NR___acl_delete_file:
++ case TARGET_FREEBSD_NR___acl_delete_fd:
++ case TARGET_FREEBSD_NR___acl_aclcheck_file:
++ case TARGET_FREEBSD_NR___acl_aclcheck_fd:
++ case TARGET_FREEBSD_NR___acl_get_link:
++ case TARGET_FREEBSD_NR___acl_set_link:
++ case TARGET_FREEBSD_NR___acl_delete_link:
++ case TARGET_FREEBSD_NR___acl_aclcheck_link:
++ case TARGET_FREEBSD_NR_extattrctl:
++ case TARGET_FREEBSD_NR_extattr_set_file:
++ case TARGET_FREEBSD_NR_extattr_get_file:
++ case TARGET_FREEBSD_NR_extattr_delete_file:
++ case TARGET_FREEBSD_NR_extattr_set_fd:
++ case TARGET_FREEBSD_NR_extattr_get_fd:
++ case TARGET_FREEBSD_NR_extattr_delete_fd:
++ case TARGET_FREEBSD_NR_extattr_get_link:
++ case TARGET_FREEBSD_NR_extattr_set_link:
++ case TARGET_FREEBSD_NR_extattr_delete_link:
++ case TARGET_FREEBSD_NR_extattr_list_fd:
++ case TARGET_FREEBSD_NR_extattr_list_file:
++ case TARGET_FREEBSD_NR_extattr_list_link:
++ ret = unimplemented(num);
++ break;
++
++ case TARGET_FREEBSD_NR_setlogin:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(setlogin(p));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_getlogin:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(_getlogin(p, arg2));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_setloginclass:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(setloginclass(p));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_getloginclass:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(getloginclass(p, arg2));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_getrusage:
++ {
++ struct rusage rusage;
++ ret = get_errno(getrusage(arg1, &rusage));
++ if (!is_error(ret))
++ host_to_target_rusage(arg2, &rusage);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_wait4:
++ {
++ int status;
++ abi_long status_ptr = arg2;
++ struct rusage rusage, *rusage_ptr;
++ abi_ulong target_rusage = arg4;
++
++ if (target_rusage)
++ rusage_ptr = &rusage;
++ else
++ rusage_ptr = NULL;
++ ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
++ if (!is_error(ret)) {
++ status = host_to_target_waitstatus(status);
++ if (put_user_s32(status, status_ptr))
++ goto efault;
++ if (target_rusage)
++ host_to_target_rusage(target_rusage, &rusage);
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_accept:
++ ret = do_accept(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_bind:
++ ret = do_bind(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_connect:
++ ret = do_connect(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_getpeername:
++ ret = do_getpeername(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_getsockname:
++ ret = do_getsockname(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_getsockopt:
++ ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
++ break;
++
++ case TARGET_FREEBSD_NR_setsockopt:
++ ret = do_setsockopt(arg1, arg2, arg3, arg4, arg5);
++ break;
++
++ case TARGET_FREEBSD_NR_listen:
++ ret = get_errno(listen(arg1, arg2));
++ break;
++
++ case TARGET_FREEBSD_NR_recvfrom:
++ ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
++ break;
++
++ case TARGET_FREEBSD_NR_recvmsg:
++ ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_sendmsg:
++ ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
++ break;
++
++ case TARGET_FREEBSD_NR_sendto:
++ ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
++ break;
++
++ case TARGET_FREEBSD_NR_socket:
++ ret = get_errno(socket(arg1, arg2, arg3));
++ break;
++
++ case TARGET_FREEBSD_NR_socketpair:
++ ret = do_socketpair(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_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) {
++ ret = -host_to_target_errno(errno);
++ break;
++ }
++ /* Return value is a biased priority to avoid negative numbers. */
++ ret = 20 - ret;
++ break;
++
++ case TARGET_FREEBSD_NR_setpriority:
++ ret = get_errno(setpriority(arg1, arg2, arg3));
++ break;
++
++ case TARGET_FREEBSD_NR_semget:
++ ret = get_errno(semget(arg1, arg2, arg3));
++ break;
++
++ case TARGET_FREEBSD_NR_semop:
++ ret = get_errno(do_semop(arg1, arg2, arg3));
++ break;
++
++ case TARGET_FREEBSD_NR___semctl:
++ ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_msgctl:
++ ret = do_msgctl(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_msgrcv:
++ ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
++ break;
++
++ case TARGET_FREEBSD_NR_msgsnd:
++ ret = do_msgsnd(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_shmget:
++ ret = get_errno(shmget(arg1, arg2, arg3));
++ break;
++
++ case TARGET_FREEBSD_NR_shmctl:
++ ret = do_shmctl(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_shmat:
++ ret = do_shmat(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_shmdt:
++ ret = do_shmdt(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_shm_open:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(shm_open(path(p),
++ target_to_host_bitmask(arg2, fcntl_flags_tbl),
++ arg3));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_shm_unlink:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(shm_unlink(p));
++ break;
++
++ case TARGET_FREEBSD_NR_getpid:
++ ret = get_errno(getpid());
++ break;
++
++ case TARGET_FREEBSD_NR_getppid:
++ ret = get_errno(getppid());
++ break;
++
++ case TARGET_FREEBSD_NR_getuid:
++ ret = get_errno(getuid());
++ break;
++
++ case TARGET_FREEBSD_NR_geteuid:
++ ret = get_errno(geteuid());
++ break;
++
++ case TARGET_FREEBSD_NR_getgid:
++ ret = get_errno(getgid());
++ break;
++
++ case TARGET_FREEBSD_NR_getegid:
++ ret = get_errno(getegid());
++ break;
++
++ case TARGET_FREEBSD_NR_setuid:
++ ret = get_errno(setuid(arg1));
++ break;
++
++ case TARGET_FREEBSD_NR_setgid:
++ ret = get_errno(setgid(arg1));
++ break;
++
++ case TARGET_FREEBSD_NR_setegid:
++ ret = get_errno(setegid(arg1));
++ break;
++
++ case TARGET_FREEBSD_NR_seteuid:
++ ret = get_errno(setegid(arg1));
++ break;
++
++ case TARGET_FREEBSD_NR_getpgrp:
++ ret = get_errno(getpgrp());
++ break;
++
++#ifdef TARGET_FREEBSD_NR_setpgrp
++ case TARGET_FREEBSD_NR_setpgrp:
++ ret = get_errno(setpgrp(arg1, arg2));
++ break;
++#endif
++
++ case TARGET_FREEBSD_NR_setreuid:
++ ret = get_errno(setreuid(arg1, arg2));
++ break;
++
++ case TARGET_FREEBSD_NR_setregid:
++ ret = get_errno(setregid(arg1, arg2));
++ break;
++
++ case TARGET_FREEBSD_NR_setresuid:
++ ret = get_errno(setresuid(arg1, arg2, arg3));
++ break;
++
++ case TARGET_FREEBSD_NR_setresgid:
++ ret = get_errno(setresgid(arg1, arg2, arg3));
++ break;
++
++ case TARGET_FREEBSD_NR_getresuid:
++ case TARGET_FREEBSD_NR_getresgid:
++ ret = unimplemented(num);
++ break;
++
++ case TARGET_FREEBSD_NR_setsid:
++ ret = get_errno(setsid());
++ break;
++
++ case TARGET_FREEBSD_NR_getsid:
++ ret = get_errno(getsid(arg1));
++ break;
++
++ case TARGET_FREEBSD_NR_setfib:
++ ret = get_errno(setfib(arg1));
++ break;
++
++ case TARGET_FREEBSD_NR___setugid:
++ ret = get_errno(__setugid(arg1));
++ break;
++
++ case TARGET_FREEBSD_NR_issetugid:
++ ret = get_errno(issetugid());
++ break;
++
++#ifdef TARGET_FREEBSD_NR_wait
++ case TARGET_FREEBSD_NR_wait:
++ ret = get_errno(wait());
++ break;
++#endif
++
++ case TARGET_FREEBSD_NR_fork:
++ ret = get_errno(do_fork(cpu_env, num, 0, NULL));
++ break;
++
++ case TARGET_FREEBSD_NR_rfork:
++ ret = get_errno(do_fork(cpu_env, num, arg1, NULL));
++ break;
++
++ case TARGET_FREEBSD_NR_vfork:
++ ret = get_errno(do_fork(cpu_env, num, 0, NULL));
++ break;
++
++ case TARGET_FREEBSD_NR_pdfork:
++ {
++ int pd;
++
++ ret = get_errno(do_fork(cpu_env, num, arg2, &pd));
++ if (put_user_s32(pd, arg1))
++ goto efault;
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_kill:
++ ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
++ break;
++
++#ifdef TARGET_FREEBSD_NR_killpg
++ case TARGET_FREEBSD_NR_killpg:
++ ret = get_errno(killpg(arg1, target_to_host_signal(arg2)));
++ break;
++#endif
++
++ case TARGET_FREEBSD_NR_sigaction:
++ {
++ struct target_sigaction *old_act, act, oact, *pact;
++
++ if (arg2) {
++ if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
++ goto efault;
++ act._sa_handler = old_act->_sa_handler;
++ act.sa_flags = old_act->sa_flags;
++ memcpy(&act.sa_mask, &old_act->sa_mask,
++ sizeof(target_sigset_t));
++ unlock_user_struct(old_act, arg2, 0);
++ pact = &act;
++ } else {
++ pact = NULL;
++ }
++ ret = get_errno(do_sigaction(arg1, pact, &oact));
++ if (!is_error(ret) && arg3) {
++ if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
++ goto efault;
++ old_act->_sa_handler = oact._sa_handler;
++ old_act->sa_flags = oact.sa_flags;
++ memcpy(&old_act->sa_mask, &oact.sa_mask,
++ sizeof(target_sigset_t));
++ unlock_user_struct(old_act, arg3, 1);
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_sigprocmask:
++ {
++ sigset_t set, oldset, *set_ptr;
++ int how;
++
++ 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:
++ ret = -TARGET_EINVAL;
++ goto fail;
++ }
++ if (!(p = lock_user(VERIFY_READ, arg2,
++ sizeof(target_sigset_t), 1)))
++ goto efault;
++ target_to_host_sigset(&set, p);
++ unlock_user(p, arg2, 0);
++ set_ptr = &set;
++ } else {
++ how = 0;
++ set_ptr = NULL;
++ }
++ ret = get_errno(sigprocmask(how, set_ptr, &oldset));
++ if (!is_error(ret) && arg3) {
++ if (!(p = lock_user(VERIFY_WRITE, arg3,
++ sizeof(target_sigset_t), 0)))
++ goto efault;
++ host_to_target_sigset(p, &oldset);
++ unlock_user(p, arg3, sizeof(target_sigset_t));
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_sigpending:
++ {
++ sigset_t set;
++
++ ret = get_errno(sigpending(&set));
++ if (!is_error(ret)) {
++ if (!(p = lock_user(VERIFY_WRITE, arg1,
++ sizeof(target_sigset_t), 0)))
++ goto efault;
++ host_to_target_sigset(p, &set);
++ unlock_user(p, arg1, sizeof(target_sigset_t));
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_sigsuspend:
++ {
++ sigset_t set;
++
++ if (!(p = lock_user(VERIFY_READ, arg1,
++ sizeof(target_sigset_t), 1)))
++ goto efault;
++ target_to_host_sigset(&set, p);
++ unlock_user(p, arg1, 0);
++ ret = get_errno(sigsuspend(&set));
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_sigreturn:
++ ret = do_sigreturn(cpu_env, arg1);
++ break;
++
++#ifdef TARGET_FREEBSD_NR_sigvec
++ case TARGET_FREEBSD_NR_sigvec:
++ ret = unimplemented(num);
++ break;
++#endif
++#ifdef TARGET_FREEBSD_NR_sigblock
++ case TARGET_FREEBSD_NR_sigblock:
++ ret = unimplemented(num);
++ break;
++#endif
++#ifdef TARGET_FREEBSD_NR_sigsetmask
++ case TARGET_FREEBSD_NR_sigsetmask:
++ ret = unimplemented(num);
++ break;
++#endif
++#ifdef TARGET_FREEBSD_NR_sigstack
++ case TARGET_FREEBSD_NR_sigstack:
++ ret = unimplemented(num);
++ break;
++#endif
++
++ case TARGET_FREEBSD_NR_sigwait:
++ {
++ sigset_t set;
++ int sig;
++
++ if (!(p = lock_user(VERIFY_READ, arg1,
++ sizeof(target_sigset_t), 1)))
++ goto efault;
++ target_to_host_sigset(&set, p);
++ unlock_user(p, arg1, 0);
++ ret = get_errno(sigwait(&set, &sig));
++ if (!is_error(ret) && arg2) {
++ /* XXX */
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_sigtimedwait:
++ {
++ sigset_t set;
++ struct timespec uts, *puts;
++ siginfo_t uinfo;
++
++ if (!(p = lock_user(VERIFY_READ, arg1,
++ sizeof(target_sigset_t), 1)))
++ goto efault;
++ target_to_host_sigset(&set, p);
++ unlock_user(p, arg1, 0);
++ if (arg3) {
++ puts = &uts;
++ target_to_host_timespec(puts, arg3);
++ } else {
++ puts = NULL;
++ }
++ ret = get_errno(sigtimedwait(&set, &uinfo, puts));
++ if (!is_error(ret) && arg2) {
++ if (!(p = lock_user(VERIFY_WRITE, arg2,
++ sizeof(target_siginfo_t), 0)))
++ goto efault;
++ host_to_target_siginfo(p, &uinfo);
++ unlock_user(p, arg2, sizeof(target_siginfo_t));
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_sigwaitinfo:
++ {
++ sigset_t set;
++ siginfo_t uinfo;
++
++ if (!(p = lock_user(VERIFY_READ, arg1,
++ sizeof(target_sigset_t), 1)))
++ goto efault;
++ target_to_host_sigset(&set, p);
++ unlock_user(p, arg1, 0);
++ ret = get_errno(sigwaitinfo(&set, &uinfo));
++ if (!is_error(ret) && arg2) {
++ if (!(p = lock_user(VERIFY_WRITE, arg2,
++ sizeof(target_siginfo_t), 0)))
++ goto efault;
++ host_to_target_siginfo(p, &uinfo);
++ unlock_user(p, arg2, sizeof(target_siginfo_t));
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_sigqueue:
++ {
++ union sigval value;
++
++ value.sival_ptr = (void *)(uintptr_t)arg3;
++ ret = get_errno(sigqueue(arg1, target_to_host_signal(arg2),
++ value));
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_sigaltstack:
++ {
++
++ ret = do_sigaltstack(arg1, arg2,
++ get_sp_from_cpustate((CPUArchState *)cpu_env));
++ }
++
++#ifdef TARGET_FREEBSD_NR_aio_read
++ case TARGET_FREEBSD_NR_aio_read:
++#endif
++#ifdef TARGET_FREEBSD_NR_aio_write
++ case TARGET_FREEBSD_NR_aio_write:
++#endif
++#ifdef TARGET_FREEBSD_NR_aio_return
++ case TARGET_FREEBSD_NR_aio_return:
++#endif
++#ifdef TARGET_FREEBSD_NR_aio_suspend
++ case TARGET_FREEBSD_NR_aio_suspend:
++#endif
++#ifdef TARGET_FREEBSD_NR_aio_cancel
++ case TARGET_FREEBSD_NR_aio_cancel:
++#endif
++#ifdef TARGET_FREEBSD_NR_aio_error
++ case TARGET_FREEBSD_NR_aio_error:
++#endif
++#ifdef TARGET_FREEBSD_NR_aio_waitcomplete
++ case TARGET_FREEBSD_NR_aio_waitcomplete:
++#endif
++#ifdef TARGET_FREEBSD_NR_lio_listio
++ case TARGET_FREEBSD_NR_lio_listio:
++#endif
++
++ case TARGET_FREEBSD_NR_yield:
++ case TARGET_FREEBSD_NR_sched_setparam:
++ case TARGET_FREEBSD_NR_sched_getparam:
++ case TARGET_FREEBSD_NR_sched_setscheduler:
++ case TARGET_FREEBSD_NR_sched_getscheduler:
++ case TARGET_FREEBSD_NR_sched_yield:
++ case TARGET_FREEBSD_NR_sched_get_priority_max:
++ case TARGET_FREEBSD_NR_sched_get_priority_min:
++ case TARGET_FREEBSD_NR_sched_rr_get_interval:
++
++
++ case TARGET_FREEBSD_NR_reboot:
++ case TARGET_FREEBSD_NR_shutdown:
++
++ case TARGET_FREEBSD_NR_swapon:
++ case TARGET_FREEBSD_NR_swapoff:
++
++ case TARGET_FREEBSD_NR_pdkill:
++ case TARGET_FREEBSD_NR_pdgetpid:
++
++ case TARGET_FREEBSD_NR_thr_create:
++ case TARGET_FREEBSD_NR_thr_exit:
++ case TARGET_FREEBSD_NR_thr_self:
++ case TARGET_FREEBSD_NR_thr_suspend:
++ case TARGET_FREEBSD_NR_thr_wake:
++ case TARGET_FREEBSD_NR_thr_new:
++ case TARGET_FREEBSD_NR_thr_set_name:
++ case TARGET_FREEBSD_NR_thr_kill2:
++
++ case TARGET_FREEBSD_NR_getcontext:
++ case TARGET_FREEBSD_NR_setcontext:
++ case TARGET_FREEBSD_NR_swapcontext:
++
++ case TARGET_FREEBSD_NR_rtprio_thread:
++ case TARGET_FREEBSD_NR_cpuset:
++ case TARGET_FREEBSD_NR_cpuset_getid:
++ case TARGET_FREEBSD_NR_cpuset_setid:
++ case TARGET_FREEBSD_NR_cpuset_getaffinity:
++ case TARGET_FREEBSD_NR_cpuset_setaffinity:
++
++ case TARGET_FREEBSD_NR__umtx_lock:
++ case TARGET_FREEBSD_NR__umtx_unlock:
++
++ case TARGET_FREEBSD_NR_posix_fadvise:
++ case TARGET_FREEBSD_NR_posix_fallocate:
++
++ case TARGET_FREEBSD_NR_rctl_get_racct:
++ case TARGET_FREEBSD_NR_rctl_get_rules:
++ case TARGET_FREEBSD_NR_rctl_add_rule:
++ case TARGET_FREEBSD_NR_rctl_remove_rule:
++ case TARGET_FREEBSD_NR_rctl_get_limits:
++
++ case TARGET_FREEBSD_NR_ntp_adjtime:
++ case TARGET_FREEBSD_NR_ntp_gettime:
++
++#ifdef TARGET_FREEBSD_NR_getdomainname
++ case TARGET_FREEBSD_NR_getdomainname:
++#endif
++#ifdef TARGET_FREEBSD_NR_setdomainname
++ case TARGET_FREEBSD_NR_setdomainname:
++#endif
++#ifdef TARGET_FREEBSD_NR_uname
++ case TARGET_FREEBSD_NR_uname:
++#endif
++
++ case TARGET_FREEBSD_NR_sctp_peeloff:
++ case TARGET_FREEBSD_NR_sctp_generic_sendmsg:
++ case TARGET_FREEBSD_NR_sctp_generic_recvmsg:
++
++ case TARGET_FREEBSD_NR_getfh:
++ case TARGET_FREEBSD_NR_lgetfh:
++ case TARGET_FREEBSD_NR_fhstatfs:
++ case TARGET_FREEBSD_NR_fhopen:
++ case TARGET_FREEBSD_NR_fhstat:
++
++ case TARGET_FREEBSD_NR_getfsstat:
++ case TARGET_FREEBSD_NR_fstatfs:
++
++ case TARGET_FREEBSD_NR_modfnext:
++ case TARGET_FREEBSD_NR_modfind:
++ case TARGET_FREEBSD_NR_kldload:
++ case TARGET_FREEBSD_NR_kldunload:
++ case TARGET_FREEBSD_NR_kldunloadf:
++ case TARGET_FREEBSD_NR_kldfind:
++ case TARGET_FREEBSD_NR_kldnext:
++ case TARGET_FREEBSD_NR_kldstat:
++ case TARGET_FREEBSD_NR_kldfirstmod:
++ case TARGET_FREEBSD_NR_kldsym:
++
++ case TARGET_FREEBSD_NR_quotactl:
++#ifdef TARGET_FREEBSD_NR_quota
++ case TARGET_FREEBSD_NR_quota:
++#endif
++
++ case TARGET_FREEBSD_NR_adjtime:
++
++#ifdef TARGET_FREEBSD_NR_gethostid
++ case TARGET_FREEBSD_NR_gethostid:
++#endif
++#ifdef TARGET_FREEBSD_NR_gethostname
++ case TARGET_FREEBSD_NR_gethostname:
++#endif
++#ifdef TARGET_FREEBSD_NR_sethostname
++ case TARGET_FREEBSD_NR_sethostname:
++#endif
++
++ case TARGET_FREEBSD_NR_mincore:
++
++ case TARGET_FREEBSD_NR_vadvise:
++
++ case TARGET_FREEBSD_NR_sbrk:
++ case TARGET_FREEBSD_NR_sstk:
++
++#ifdef TARGET_FREEBSD_NR_getkerninfo
++ case TARGET_FREEBSD_NR_getkerninfo:
++#endif
++#ifdef TARGET_FREEBSD_NR_getpagesize
++ case TARGET_FREEBSD_NR_getpagesize:
++#endif
++
++ case TARGET_FREEBSD_NR_revoke:
++
++ case TARGET_FREEBSD_NR_profil:
++ case TARGET_FREEBSD_NR_ktrace:
++
++ case TARGET_FREEBSD_NR_jail:
++ case TARGET_FREEBSD_NR_jail_attach:
++ case TARGET_FREEBSD_NR_jail_get:
++ case TARGET_FREEBSD_NR_jail_set:
++ case TARGET_FREEBSD_NR_jail_remove:
++
++ case TARGET_FREEBSD_NR_cap_enter:
++ case TARGET_FREEBSD_NR_cap_getmode:
++
++ case TARGET_FREEBSD_NR_kenv:
++ case TARGET_FREEBSD_NR_uuidgen:
++
++ case TARGET_FREEBSD_NR___mac_get_proc:
++ case TARGET_FREEBSD_NR___mac_set_proc:
++ case TARGET_FREEBSD_NR___mac_get_fd:
++ case TARGET_FREEBSD_NR___mac_set_fd:
++ case TARGET_FREEBSD_NR___mac_get_file:
++ case TARGET_FREEBSD_NR___mac_set_file:
++ case TARGET_FREEBSD_NR___mac_get_link:
++ case TARGET_FREEBSD_NR___mac_set_link:
++ case TARGET_FREEBSD_NR_mac_syscall:
++
++ case TARGET_FREEBSD_NR_audit:
++ case TARGET_FREEBSD_NR_auditon:
++ case TARGET_FREEBSD_NR_getaudit:
++ case TARGET_FREEBSD_NR_setaudit:
++ case TARGET_FREEBSD_NR_getaudit_addr:
++ case TARGET_FREEBSD_NR_setaudit_addr:
++ case TARGET_FREEBSD_NR_auditctl:
++
++
++#ifdef TARGET_FREEBSD_NR_obreak
++ case TARGET_FREEBSD_NR_obreak:
++#endif
++ case TARGET_FREEBSD_NR_freebsd6_pread:
++ case TARGET_FREEBSD_NR_freebsd6_pwrite:
++ case TARGET_FREEBSD_NR_freebsd6_lseek:
++ case TARGET_FREEBSD_NR_freebsd6_truncate:
++ case TARGET_FREEBSD_NR_freebsd6_ftruncate:
++ case TARGET_FREEBSD_NR_sendfile:
++ case TARGET_FREEBSD_NR_ptrace:
++ case TARGET_FREEBSD_NR_utrace:
++ case TARGET_FREEBSD_NR_ioctl:
++ ret = unimplemented(num);
++ break;
++
++
+ default:
+ ret = get_errno(syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8));
+ break;
+diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h
+index 207ddee..ea1d25d 100644
+--- a/bsd-user/syscall_defs.h
++++ b/bsd-user/syscall_defs.h
+@@ -37,8 +37,6 @@
+ * @(#)signal.h 8.2 (Berkeley) 1/21/94
+ */
+
+-#define TARGET_NSIG 32 /* counting 0; could be 33 (mask is 1-32) */
+-
+ #define TARGET_SIGHUP 1 /* hangup */
+ #define TARGET_SIGINT 2 /* interrupt */
+ #define TARGET_SIGQUIT 3 /* quit */
+@@ -71,14 +69,21 @@
+ #define TARGET_SIGINFO 29 /* information request */
+ #define TARGET_SIGUSR1 30 /* user defined signal 1 */
+ #define TARGET_SIGUSR2 31 /* user defined signal 2 */
++#define TARGET_SIGTHR 32 /* reserved by thread library */
++#define TARGET_SIGLWP SIGTHR /* compatibility */
++#define TARGET_SIGLIBRT 33 /* reserved by the real-time library */
++#define TARGET_SIGRTMIN 65
++#define TARGET_SIGRTMAX 126
++#define TARGET_QEMU_ESIGRETURN 255 /* fake errno value for use by sigreturn */
++
+
+ /*
+ * Language spec says we must list exactly one parameter, even though we
+ * actually supply three. Ugh!
+ */
+-#define TARGET_SIG_DFL (void (*)(int))0
+-#define TARGET_SIG_IGN (void (*)(int))1
+-#define TARGET_SIG_ERR (void (*)(int))-1
++#define TARGET_SIG_DFL ((abi_long)0) /* default signal handling */
++#define TARGET_SIG_IGN ((abi_long)1) /* ignore signal */
++#define TARGET_SIG_ERR ((abi_long)-1) /* error return from signal */
+
+ #define TARGET_SA_ONSTACK 0x0001 /* take signal on signal stack */
+ #define TARGET_SA_RESTART 0x0002 /* restart system on signal return */
+@@ -98,17 +103,503 @@
+
+ #define TARGET_BADSIG SIG_ERR
+
++/*
++ * sigaltstack controls
++ */
+ #define TARGET_SS_ONSTACK 0x0001 /* take signals on alternate stack */
+-#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate stack */
++#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate
++ stack */
++
++#define TARGET_NSIG 128
++#define TARGET_NSIG_BPW (sizeof(uint32_t) * 8)
++#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
++
++/*
++ * si_code values
++ * Digital reserves positive values for kernel-generated signals.
++ */
++
++/*
++ * SIGSEGV si_codes
++ */
++#define TARGET_SEGV_MAPERR (1) /* address not mapped to object */
++#define TARGET_SEGV_ACCERR (2) /* invalid permissions for mapped
++ object */
++/*
++ * SIGTRAP si_codes
++ */
++#define TARGET_TRAP_BRKPT (1) /* process beakpoint */
++#define TARGET_TRAP_TRACE (2) /* process trace trap */
+
++struct target_rlimit {
++ abi_ulong rlim_cur;
++ abi_ulong rlim_max;
++};
++
++#if defined(TARGET_ALPHA)
++#define TARGET_RLIM_INFINITY 0x7fffffffffffffffull
++#elif defined(TARGET_MIPS) || (defined(TARGET_SPARC) && TARGET_ABI_BITS == 32)
++#define TARGET_RLIM_INFINITY 0x7fffffffUL
++#else
++#define TARGET_RLIM_INFINITY ((abi_ulong)-1)
++#endif
++
++#define TARGET_RLIMIT_CPU 0
++#define TARGET_RLIMIT_FSIZE 1
++#define TARGET_RLIMIT_DATA 2
++#define TARGET_RLIMIT_STACK 3
++#define TARGET_RLIMIT_CORE 4
++#define TARGET_RLIMIT_RSS 5
++#define TARGET_RLIMIT_MEMLOCK 6
++#define TARGET_RLIMIT_NPROC 7
++#define TARGET_RLIMIT_NOFILE 8
++#define TARGET_RLIMIT_SBSIZE 9
++#define TARGET_RLIMIT_AS 10
++#define TARGET_RLIMIT_NPTS 11
++#define TARGET_RLIMIT_SWAP 12
++
++struct target_pollfd {
++ int fd; /* file descriptor */
++ short events; /* requested events */
++ short revents; /* returned events */
++};
++
++/*
++ * Constants used for fcntl(2).
++ */
++
++/* command values */
++#define TARGET_F_DUPFD 0
++#define TARGET_F_GETFD 1
++#define TARGET_F_SETFD 2
++#define TARGET_F_GETFL 3
++#define TARGET_F_SETFL 4
++#define TARGET_F_GETOWN 5
++#define TARGET_F_SETOWN 6
++#define TARGET_F_OGETLK 7
++#define TARGET_F_OSETLK 8
++#define TARGET_F_OSETLKW 9
++#define TARGET_F_DUP2FD 10
++#define TARGET_F_GETLK 11
++#define TARGET_F_SETLK 12
++#define TARGET_F_SETLKW 13
++#define TARGET_F_SETLK_REMOTE 14
++#define TARGET_F_READAHEAD 15
++#define TARGET_F_RDAHEAD 16
++
++#define TARGET_O_NONBLOCK 0x00000004
++#define TARGET_O_APPEND 0x00000008
++#define TARGET_O_ASYNC 0x00000040
++#define TARGET_O_DIRECT 0x00010000
++
++#define TARGET_SPARC_UTRAP_INSTALL 1
++#define TARGET_SPARC_SIGTRAMP_INSTALL 2
++
++#include "socket.h"
+ #include "errno_defs.h"
+
+ #include "freebsd/syscall_nr.h"
+ #include "netbsd/syscall_nr.h"
+ #include "openbsd/syscall_nr.h"
+
++struct target_flock {
++ unsigned long long l_start;
++ unsigned long long l_len;
++ int l_pid;
++ int l_sysid;
++ short l_type;
++ short l_whence;
++} QEMU_PACKED;
++
+ struct target_iovec {
+ abi_long iov_base; /* Starting address */
+ abi_long iov_len; /* Number of bytes */
+ };
+
++struct target_msghdr {
++ abi_long msg_name; /* Socket name */
++ int msg_namelen; /* Length of name */
++ abi_long msg_iov; /* Data blocks */
++ abi_long msg_iovlen; /* Number of blocks */
++ abi_long msg_control; /* Per protocol magic
++ (eg BSD file descriptor passing) */
++ abi_long msg_controllen; /* Length of cmsg list */
++ int msg_flags; /* flags on received message */
++};
++
++struct target_cmsghdr {
++ abi_long cmsg_len;
++ int cmsg_level;
++ int cmsg_type;
++};
++
++#define TARGET_CMSG_DATA(cmsg) \
++ ((unsigned char *) ((struct target_cmsghdr *) (cmsg) + 1))
++#define TARGET_CMSG_NXTHDR(mhdr, cmsg) __target_cmsg_nxthdr (mhdr, cmsg)
++#define TARGET_CMSG_ALIGN(len) (((len) + sizeof (abi_long) - 1) \
++ & (size_t) ~(sizeof (abi_long) - 1))
++#define TARGET_CMSG_SPACE(len) (TARGET_CMSG_ALIGN (len) \
++ + TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr)))
++#define TARGET_CMSG_LEN(len) \
++ (TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr)) + (len))
++
++static __inline__ struct target_cmsghdr *
++__target_cmsg_nxthdr (struct target_msghdr *__mhdr,
++ struct target_cmsghdr *__cmsg)
++{
++ struct target_cmsghdr *__ptr;
++
++ __ptr = (struct target_cmsghdr *)((unsigned char *) __cmsg +
++ TARGET_CMSG_ALIGN (tswapal(__cmsg->cmsg_len)));
++ if ((unsigned long)((char *)(__ptr+1) -
++ (char *)(size_t)tswapal(__mhdr->msg_control)) >
++ tswapal(__mhdr->msg_controllen))
++ /* No more entries. */
++ return ((struct target_cmsghdr *)0);
++ return (__cmsg);
++}
++
++struct target_sockaddr {
++ uint16_t sa_family;
++ uint8_t sa_data[14];
++};
++
++struct target_in_addr {
++ uint32_t s_addr; /* big endian */
++};
++
++
++struct target_timeval {
++ abi_long tv_sec;
++ abi_long tv_usec;
++};
++
++typedef abi_long target_clock_t;
++
++struct target_rusage {
++ struct target_timeval ru_utime; /* user time used */
++ struct target_timeval ru_stime; /* system time used */
++ abi_long ru_maxrss; /* maximum resident set size */
++ abi_long ru_ixrss; /* integral shared memory size */
++ abi_long ru_idrss; /* integral unshared data size */
++ abi_long ru_isrss; /* integral unshared stack size */
++ abi_long ru_minflt; /* page reclaims */
++ abi_long ru_majflt; /* page faults */
++ abi_long ru_nswap; /* swaps */
++ abi_long ru_inblock; /* block input operations */
++ abi_long ru_oublock; /* block output operations */
++ abi_long ru_msgsnd; /* messages sent */
++ abi_long ru_msgrcv; /* messages received */
++ abi_long ru_nsignals; /* signals received */
++ abi_long ru_nvcsw; /* voluntary context switches */
++ abi_long ru_nivcsw; /* involuntary context switches */
++};
++
++struct target_kevent {
++ abi_ulong ident;
++ short filter;
++ u_short flags;
++ u_int fflags;
++ abi_long data;
++ abi_ulong udata;
++} __packed;
++
++/*
++ * FreeBSD/arm uses a 64bits time_t, even in 32bits mode, so we have to
++ * add a special case here.
++ */
++#if defined(TARGET_ARM)
++typedef uint64_t target_freebsd_time_t;
++#else
++typedef long target_freebsd_time_t;
++#endif
++
++struct target_freebsd_timespec {
++ target_freebsd_time_t tv_sec; /* seconds */
++ abi_long tv_nsec; /* and nanoseconds */
++} __packed;
++
++struct target_freebsd_timeval {
++ target_freebsd_time_t tv_sec;
++ abi_long tv_usec;
++} __packed;
++
++struct target_freebsd_stat {
++ uint32_t st_dev; /* inode's device */
++ uint32_t st_ino; /* inode's number */
++ int16_t st_mode; /* inode protection mode */
++ int16_t st_nlink; /* number of hard links */
++ uint32_t st_uid; /* user ID of the file's owner */
++ uint32_t st_gid; /* group ID of the file's group */
++ uint32_t st_rdev; /* device type */
++ struct target_freebsd_timespec st_atim; /* time of last access */
++ struct target_freebsd_timespec st_mtim; /* time of last data modification */
++ struct target_freebsd_timespec st_ctim; /* time of last file status change */
++ int64_t st_size; /* file size, in bytes */
++ int64_t st_blocks; /* blocks allocated for file */
++ uint32_t st_blksize; /* optimal blocksize for I/O */
++ uint32_t st_flags; /* user defined flags for file */
++ __uint32_t st_gen; /* file generation number */
++ __int32_t st_lspare;
++ struct target_freebsd_timespec st_birthtim; /* time of file creation */
++ /*
++ * Explicitly pad st_birthtim to 16 bytes so that the size of
++ * struct stat is backwards compatible. We use bitfields instead
++ * of an array of chars so that this doesn't require a C99 compiler
++ * to compile if the size of the padding is 0. We use 2 bitfields
++ * to cover up to 64 bits on 32-bit machines. We assume that
++ * CHAR_BIT is 8...
++ */
++ unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec));
++ unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec));
++} __packed;
++
++int __getcwd(char *, size_t);
++
++struct target_sembuf {
++ unsigned short sem_num; /* semaphore # */
++ short sem_op; /* semaphore operation */
++ short sem_flg; /* operation flags */
++};
++
++union target_semun {
++ int val; /* value for SETVAL */
++ abi_ulong buf; /* buffer for IPC_STAT & IPC_SET */
++ abi_ulong array; /* array for GETALL & SETALL */
++};
++
++struct target_ipc_perm {
++ uint32_t cuid; /* creator user id */
++ uint32_t cgid; /* creator group id */
++ uint32_t uid; /* user id */
++ uint32_t gid; /* group id */
++ uint16_t mode; /* r/w permission */
++ uint16_t seq; /* sequence # */
++ abi_long key; /* user specified msg/sem/shm key */
++};
++
++struct target_msqid_ds {
++ struct target_ipc_perm msg_perm; /* msg queue permission bits */
++ abi_ulong msg_first; /* first message in the queue */
++ abi_ulong msg_last; /* last message in the queue */
++ abi_ulong msg_cbytes; /* # of bytes in use on the queue */
++ abi_ulong msg_qnum; /* number of msgs in the queue */
++ abi_ulong msg_qbytes; /* max # of bytes on the queue */
++ int32_t msg_lspid; /* pid of last msgsnd() */
++ int32_t msg_lrpid; /* pid of last msgrcv() */
++ abi_ulong msg_stime; /* time of last msgsnd() */
++ abi_ulong msg_rtime; /* time of last msgrcv() */
++ abi_ulong msg_ctime; /* time of last msgctl() */
++};
++
++struct target_msgbuf {
++ abi_long mtype; /* message type */
++ char mtext[1]; /* body of message */
++};
++
++struct target_semid_ds {
++ struct target_ipc_perm sem_perm; /* operation permission struct */
++ abi_ulong sem_base; /* pointer to first semaphore in set */
++ uint16_t sem_nsems; /* number of sems in set */
++ abi_ulong sem_otime; /* last operation time */
++ abi_ulong sem_ctime; /* times measured in secs */
++};
++
++struct target_shmid_ds {
++ struct target_ipc_perm shm_perm; /* peration permission structure */
++ abi_ulong shm_segsz; /* size of segment in bytes */
++ int32_t shm_lpid; /* process ID of last shared memory op */
++ int32_t shm_cpid; /* process ID of creator */
++ int32_t shm_nattch; /* number of current attaches */
++ abi_ulong shm_atime; /* time of last shmat() */
++ abi_ulong shm_dtime; /* time of last shmdt() */
++ abi_ulong shm_ctime; /* time of last change by shmctl() */
++};
++
++/* this struct defines a stack used during syscall handling */
++typedef struct target_sigaltstack {
++ abi_long ss_sp;
++ abi_ulong ss_size;
++ abi_long ss_flags;
++} target_stack_t;
++
++typedef struct {
++ uint32_t __bits[TARGET_NSIG_WORDS];
++} target_sigset_t;
++
++struct target_sigaction {
++ abi_ulong _sa_handler;
++ int32_t sa_flags;
++ target_sigset_t sa_mask;
++};
++
++union target_sigval {
++ int32_t sival_int;
++ abi_ulong sival_ptr;
++ int32_t sigval_int;
++ abi_ulong sigval_ptr;
++};
++
++typedef struct target_siginfo {
++ int32_t si_signo; /* signal number */
++ int32_t si_errno; /* errno association */
++ int32_t si_code; /* signal code */
++ int32_t si_pid; /* sending process */
++ int32_t si_uid; /* sender's ruid */
++ abi_ulong si_addr; /* faulting instruction */
++
++ union target_sigval si_value; /* signal value */
++
++ union {
++ struct {
++ int32_t _trapno; /* machine specific trap code */
++ } _fault;
++
++ /* POSIX.1b timers */
++ struct {
++ int32_t _timerid;
++ int32_t _overrun;
++ } _timer;
++
++ struct {
++ int32_t _mqd;
++ } _mesgp;
++
++ /* SIGPOLL */
++ struct {
++ int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
++ } _poll;
++
++ struct {
++ abi_long __spare1__;
++ int32_t __spare2_[7];
++ } __spare__;
++ } _reason;
++} target_siginfo_t;
++
++#if defined(TARGET_MIPS)
++
++struct target_sigcontext {
++ target_sigset_t sc_mask; /* signal mask to retstore */
++ int32_t sc_onstack; /* sigstack state to restore */
++ abi_long sc_pc; /* pc at time of signal */
++ abi_long sc_reg[32]; /* processor regs 0 to 31 */
++ abi_long mullo, mulhi; /* mullo and mulhi registers */
++ int32_t sc_fpused; /* fp has been used */
++ abi_long sc_fpregs[33]; /* fp regs 0 to 31 & csr */
++ abi_long sc_fpc_eir; /* fp exception instr reg */
++ /* int32_t reserved[8]; */
++};
++
++typedef struct target_mcontext {
++ int32_t mc_onstack; /* sigstack state to restore */
++ abi_long mc_pc; /* pc at time of signal */
++ abi_long mc_regs[32]; /* process regs 0 to 31 */
++ abi_long sr; /* status register */
++ abi_long mullo, mulhi;
++ int32_t mc_fpused; /* fp has been used */
++ abi_long mc_fpregs[33]; /* fp regs 0 to 32 & csr */
++ abi_long mc_fpc_eir; /* fp exception instr reg */
++ abi_ulong mc_tls; /* pointer to TLS area */
++} target_mcontext_t;
++
++typedef struct target_ucontext {
++ target_sigset_t uc_sigmask;
++ target_mcontext_t uc_mcontext;
++ target_ulong uc_link;
++ target_stack_t uc_stack;
++ int32_t uc_flags;
++ int32_t __space__[8];
++} target_ucontext_t;
++
++struct target_sigframe {
++ abi_ulong sf_signum;
++ abi_ulong sf_siginfo; /* code or pointer to sf_si */
++ abi_ulong sf_ucontext; /* points to sf_uc */
++ abi_ulong sf_addr; /* undocumented 4th arg */
++ target_ucontext_t sf_uc; /* = *sf_uncontext */
++ target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/
++ uint32_t __spare__[2];
++};
++
++#elif defined(TARGET_SPARC64)
++
++struct target_mcontext {
++ uint64_t mc_global[8];
++ uint64_t mc_out[8];
++ uint64_t mc_local[8];
++ uint64_t mc_in[8];
++ uint32_t mc_fp[64];
++} __aligned(64);
++
++typedef struct target_mcontext target_mcontext_t;
++
++typedef struct target_ucontext {
++ target_sigset_t uc_sigmask;
++ target_mcontext_t uc_mcontext;
++ target_ulong uc_link;
++ target_stack_t uc_stack;
++ int32_t uc_flags;
++ int32_t __space__[8];
++} target_ucontext_t;
++
++struct target_sigframe {
++ target_ucontext_t sf_uc;
++ target_siginfo_t sf_si;
++};
++
++#else
++
++typedef target_ulong target_mcontext_t; /* dummy */
++
++#endif
++
++/* XXX where did this come from?
++typedef struct target_ucontext {
++ target_ulong uc_flags;
++ target_ulong uc_link;
++ target_stack_t uc_stack;
++ target_mcontext_t uc_mcontext;
++ target_ulong uc_filer[80];
++ target_sigset_t uc_sigmask;
++} target_ucontext_t;
++*/
++
++
++#ifdef BSWAP_NEEDED
++static inline void
++tswap_sigset(target_sigset_t *d, const target_sigset_t *s)
++{
++ int i;
++
++ for(i = 0;i < TARGET_NSIG_WORDS; i++)
++ d->__bits[i] = tswapal(s->__bits[i]);
++}
++
++#else
++static inline void
++tswap_sigset(target_sigset_t *d, const target_sigset_t *s)
++{
++
++ *d = *s;
++}
++#endif
++
++/* XXX
++static inline void
++target_siginitset(target_sigset_t *d, abi_ulong set)
++{
++ int i;
++
++ d->sig[0] = set;
++ for(i = 1;i < TARGET_NSIG_WORDS; i++)
++ d->sig[i] = 0;
++}
++*/
++
++void host_to_target_sigset(target_sigset_t *d, const sigset_t *s);
++void target_to_host_sigset(sigset_t *d, const target_sigset_t *s);
++void host_to_target_old_sigset(abi_ulong *old_sigset, const sigset_t *sigset);
++void target_to_host_old_sigset(sigset_t *sigset, const abi_ulong *old_sigset);
++int do_sigaction(int sig, const struct target_sigaction *act,
++ struct target_sigaction *oact);
+diff --git a/bsd-user/x86_64/target_signal.h b/bsd-user/x86_64/target_signal.h
+index 659cd40..ea89f5a 100644
+--- a/bsd-user/x86_64/target_signal.h
++++ b/bsd-user/x86_64/target_signal.h
+@@ -3,17 +3,16 @@
+
+ #include "cpu.h"
+
+-/* this struct defines a stack used during syscall handling */
+-
+-typedef struct target_sigaltstack {
+- abi_ulong ss_sp;
+- abi_long ss_flags;
+- abi_ulong ss_size;
+-} target_stack_t;
+-
+ static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
+ {
+ return state->regs[R_ESP];
+ }
+
++#define TARGET_SS_ONSTACK 0x0001 /* take signal on alternate stack */
++#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on
++ alternate stack */
++
++#define TARGET_MINSIGSTKSZ (512 * 4)
++#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/x86_64/target_vmparam.h b/bsd-user/x86_64/target_vmparam.h
+new file mode 100644
+index 0000000..aa5e0e0
+--- /dev/null
++++ b/bsd-user/x86_64/target_vmparam.h
+@@ -0,0 +1,28 @@
++#ifndef _TARGET_VMPARAM_H_
++#define _TARGET_VMPARAM_H_
++
++#if defined(__FreeBSD__)
++#define TARGET_VM_MAXUSER_ADDRESS (0x0000800000000000UL)
++
++#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
++
++struct target_ps_strings {
++ abi_ulong ps_argvstr;
++ uint32_t ps_nargvstr;
++ abi_ulong ps_envstr;
++ uint32_t ps_nenvstr;
++};
++
++#define TARGET_SPACE_USRSPACE 4096
++#define TARGET_ARG_MAX 262144
++
++#define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
++
++#define TARGET_SZSIGCODE 0
++
++#else
++
++#define TARGET_USRSTACK 0
++#endif
++
++#endif /* _TARGET_VMPARAM_H_ */
+diff --git a/configure b/configure
+index 169b9bd..34eca43 100755
+--- a/configure
++++ b/configure
+@@ -1018,6 +1018,10 @@ x86_64-bsd-user \
+ sparc-bsd-user \
+ sparc64-bsd-user \
+ arm-bsd-user \
++armeb-bsd-user \
++mips-bsd-user \
++mipsel-bsd-user \
++mips64-bsd-user \
+ "
+ fi
+
+diff --git a/default-configs/armeb-bsd-user.mak b/default-configs/armeb-bsd-user.mak
+new file mode 100644
+index 0000000..1b6fe65
+--- /dev/null
++++ b/default-configs/armeb-bsd-user.mak
+@@ -0,0 +1,3 @@
++# Default configuration for armeb-bsd-user
++
++CONFIG_GDBSTUB_XML=y
+diff --git a/default-configs/mips-bsd-user.mak b/default-configs/mips-bsd-user.mak
+new file mode 100644
+index 0000000..3fb129a
+--- /dev/null
++++ b/default-configs/mips-bsd-user.mak
+@@ -0,0 +1 @@
++# Default configuration for mips-bsd-user
+diff --git a/default-configs/mips64-bsd-user.mak b/default-configs/mips64-bsd-user.mak
+new file mode 100644
+index 0000000..d4e72a6
+--- /dev/null
++++ b/default-configs/mips64-bsd-user.mak
+@@ -0,0 +1 @@
++# Default configuration for mips64-bsd-user
+diff --git a/default-configs/mipsel-bsd-user.mak b/default-configs/mipsel-bsd-user.mak
+new file mode 100644
+index 0000000..312b9d5
+--- /dev/null
++++ b/default-configs/mipsel-bsd-user.mak
+@@ -0,0 +1 @@
++# Default configuration for mipsel-bsd-user
+diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h
+index bf094a3..030937c 100644
+--- a/target-mips/mips-defs.h
++++ b/target-mips/mips-defs.h
+@@ -10,8 +10,14 @@
+
+ #if defined(TARGET_MIPS64)
+ #define TARGET_LONG_BITS 64
+-#define TARGET_PHYS_ADDR_SPACE_BITS 36
+-#define TARGET_VIRT_ADDR_SPACE_BITS 42
++//#define TARGET_PHYS_ADDR_SPACE_BITS 36
++#define TARGET_PHYS_ADDR_SPACE_BITS 59
++# ifdef TARGET_ABI32
++# define TARGET_VIRT_ADDR_SPACE_BITS 32
++# else
++//# define TARGET_VIRT_ADDR_SPACE_BITS 42
++# define TARGET_VIRT_ADDR_SPACE_BITS 62
++# endif
+ #else
+ #define TARGET_LONG_BITS 32
+ #define TARGET_PHYS_ADDR_SPACE_BITS 36
+diff --git a/user-exec.c b/user-exec.c
+index b9ea9dd..9ad4858 100644
+--- a/user-exec.c
++++ b/user-exec.c
+@@ -34,11 +34,11 @@
+ #undef EDI
+ #undef EIP
+ #include <signal.h>
+-#ifdef __linux__
++#if defined(__linux__) || defined(__FreeBSD__)
+ #include <sys/ucontext.h>
+ #endif
+
+-//#define DEBUG_SIGNAL
++#define DEBUG_SIGNAL
+
+ static void exception_action(CPUArchState *env1)
+ {
+@@ -58,6 +58,8 @@ void cpu_resume_from_signal(CPUArchState *env1, void *puc)
+ struct ucontext *uc = puc;
+ #elif defined(__OpenBSD__)
+ struct sigcontext *uc = puc;
++#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
++ ucontext_t *uc = puc;
+ #endif
+
+ #ifndef CONFIG_TCG_PASS_AREG0
+@@ -76,6 +78,8 @@ void cpu_resume_from_signal(CPUArchState *env1, void *puc)
+ #endif
+ #elif defined(__OpenBSD__)
+ sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
++#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
++ sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
+ #endif
+ }
+ env1->exception_index = -1;
diff --git a/emulators/qemu-devel/files/patch-z2b-bsd-user-sson-002b b/emulators/qemu-devel/files/patch-z2b-bsd-user-sson-002b
new file mode 100644
index 000000000000..799c6e75ee23
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z2b-bsd-user-sson-002b
@@ -0,0 +1,217 @@
+diff --git a/bsd-user/signal.c b/bsd-user/signal.c
+index 0502a6a..52441c4 100644
+--- a/bsd-user/signal.c
++++ b/bsd-user/signal.c
+@@ -31,7 +31,7 @@
+ #include "qemu.h"
+ #include "target_signal.h"
+
+-// #define DEBUG_SIGNAL
++//#define DEBUG_SIGNAL
+
+ #ifndef _NSIG
+ #define _NSIG 128
+@@ -441,7 +441,7 @@ host_signal_handler(int host_signum, siginfo_t *info, void *puc)
+ * we forward to it some signals.
+ */
+ if ((host_signum == SIGSEGV || host_signum == SIGBUS) &&
+- info->si_code > 0) {
++ info->si_code < 0x10000) {
+ if (cpu_signal_handler(host_signum, info, puc))
+ return;
+ }
+@@ -1099,6 +1099,7 @@ signal_init(void)
+
+ sigfillset(&act.sa_mask);
+ act.sa_sigaction = host_signal_handler;
++ act.sa_flags = SA_SIGINFO;
+
+ for (i = 1; i <= TARGET_NSIG; i++) {
+ host_sig = target_to_host_signal(i);
+diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
+index c627c62..625c3cf 100644
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -3544,6 +3544,30 @@ do_stat:
+ }
+ break;
+
++#ifdef TARGET_FREEBSD_NR_pdwait4
++ case TARGET_FREEBSD_NR_pdwait4:
++ {
++ int status;
++ abi_long status_ptr = arg2;
++ struct rusage rusage, *rusage_ptr;
++ abi_long target_rusage = arg4;
++
++ if (target_rusage)
++ rusage_ptr = &rusage;
++ else
++ rusage_ptr = NULL;
++ ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
++ if (!is_error(ret)) {
++ status = host_to_target_waitstatus(status);
++ if (put_user_s32(status, status_ptr))
++ goto efault;
++ if (target_rusage)
++ host_to_target_rusage(target_rusage, &rusage);
++ }
++ }
++ break;
++#endif /* TARGET_FREEBSD_NR_pdwait4 */
++
+ case TARGET_FREEBSD_NR_accept:
+ ret = do_accept(arg1, arg2, arg3);
+ break;
+@@ -3803,6 +3827,20 @@ do_stat:
+ break;
+ #endif
+
++ case TARGET_FREEBSD_NR_pdkill:
++ ret = get_errno(pdkill(arg1, target_to_host_signal(arg2)));
++ break;
++
++ case TARGET_FREEBSD_NR_pdgetpid:
++ {
++ pid_t pid;
++
++ ret = get_errno(pdgetpid(arg1, &pid));
++ if (put_user_u32(pid, arg2))
++ goto efault;
++ }
++ break;
++
+ case TARGET_FREEBSD_NR_sigaction:
+ {
+ struct target_sigaction *old_act, act, oact, *pact;
+@@ -4014,27 +4052,88 @@ do_stat:
+
+ #ifdef TARGET_FREEBSD_NR_aio_read
+ case TARGET_FREEBSD_NR_aio_read:
++ ret = unimplemented(num);
++ break;
+ #endif
+ #ifdef TARGET_FREEBSD_NR_aio_write
+ case TARGET_FREEBSD_NR_aio_write:
++ ret = unimplemented(num);
++ break;
+ #endif
+ #ifdef TARGET_FREEBSD_NR_aio_return
+ case TARGET_FREEBSD_NR_aio_return:
++ ret = unimplemented(num);
++ break;
+ #endif
+ #ifdef TARGET_FREEBSD_NR_aio_suspend
+ case TARGET_FREEBSD_NR_aio_suspend:
++ ret = unimplemented(num);
++ break;
+ #endif
+ #ifdef TARGET_FREEBSD_NR_aio_cancel
+ case TARGET_FREEBSD_NR_aio_cancel:
++ ret = unimplemented(num);
++ break;
+ #endif
+ #ifdef TARGET_FREEBSD_NR_aio_error
+ case TARGET_FREEBSD_NR_aio_error:
++ ret = unimplemented(num);
++ break;
+ #endif
+ #ifdef TARGET_FREEBSD_NR_aio_waitcomplete
+ case TARGET_FREEBSD_NR_aio_waitcomplete:
++ ret = unimplemented(num);
++ break;
+ #endif
+ #ifdef TARGET_FREEBSD_NR_lio_listio
+ case TARGET_FREEBSD_NR_lio_listio:
++ ret = unimplemented(num);
++ break;
++#endif
++
++#if 0 /* XXX not supported in libc yet, it seems (10.0 addition). */
++ case TARGET_FREEBSD_NR_posix_fadvise:
++ {
++ off_t offset = arg2, len = arg3;
++ int advice = arg4;
++
++#if TARGET_ABI_BITS == 32
++ if (regpairs_aligned(cpu_env)) {
++ offset = target_offset64(arg3, arg4);
++ len = target_offset64(arg5, arg6);
++ advice = arg7;
++ } else {
++ offset = target_offset64(arg2, arg3);
++ len = target_offset64(arg4, arg5);
++ advice = arg6;
++ }
++#endif
++ ret = get_errno(posix_fadvise(arg1, offset, len, advice));
++ }
++ break;
++#endif
++
++ case TARGET_FREEBSD_NR_posix_fallocate:
++ {
++ off_t offset = arg2, len = arg3;
++
++#if TARGET_ABI_BITS == 32
++ if (regpairs_aligned(cpu_env)) {
++ offset = target_offset64(arg3, arg4);
++ len = target_offset64(arg5, arg6);
++ } else {
++ offset = target_offset64(arg2, arg3);
++ len = target_offset64(arg4, arg5);
++ }
++#endif
++ ret = get_errno(posix_fallocate(arg1, offset, len));
++ }
++ break;
++
++#ifdef TARGET_FREEBSD_posix_openpt
++ case TARGET_FREEBSD_posix_openpt:
++ ret = get_errno(posix_openpt(arg1));
++ break;
+ #endif
+
+ case TARGET_FREEBSD_NR_yield:
+@@ -4054,9 +4153,6 @@ do_stat:
+ case TARGET_FREEBSD_NR_swapon:
+ case TARGET_FREEBSD_NR_swapoff:
+
+- case TARGET_FREEBSD_NR_pdkill:
+- case TARGET_FREEBSD_NR_pdgetpid:
+-
+ case TARGET_FREEBSD_NR_thr_create:
+ case TARGET_FREEBSD_NR_thr_exit:
+ case TARGET_FREEBSD_NR_thr_self:
+@@ -4080,9 +4176,6 @@ do_stat:
+ case TARGET_FREEBSD_NR__umtx_lock:
+ case TARGET_FREEBSD_NR__umtx_unlock:
+
+- case TARGET_FREEBSD_NR_posix_fadvise:
+- case TARGET_FREEBSD_NR_posix_fallocate:
+-
+ case TARGET_FREEBSD_NR_rctl_get_racct:
+ case TARGET_FREEBSD_NR_rctl_get_rules:
+ case TARGET_FREEBSD_NR_rctl_add_rule:
+diff --git a/user-exec.c b/user-exec.c
+index 9ad4858..bf29e84 100644
+--- a/user-exec.c
++++ b/user-exec.c
+@@ -38,7 +38,7 @@
+ #include <sys/ucontext.h>
+ #endif
+
+-#define DEBUG_SIGNAL
++//#define DEBUG_SIGNAL
+
+ static void exception_action(CPUArchState *env1)
+ {
+@@ -103,7 +103,7 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
+ }
+ #endif
+ #if defined(DEBUG_SIGNAL)
+- qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
++ qemu_printf("qemu: SIGSEGV pc=0x%08lx address=0x%08lx w=%d oldset=0x%08lx\n",
+ pc, address, is_write, *(unsigned long *)old_set);
+ #endif
+ /* XXX: locking issue */
diff --git a/emulators/qemu-devel/files/patch-z2c-bsd-user-sson-002c b/emulators/qemu-devel/files/patch-z2c-bsd-user-sson-002c
new file mode 100644
index 000000000000..e0f024151e70
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z2c-bsd-user-sson-002c
@@ -0,0 +1,2301 @@
+diff --git a/bsd-user/arm/target_signal.h b/bsd-user/arm/target_signal.h
+index 19cc188..6b7bb67 100644
+--- a/bsd-user/arm/target_signal.h
++++ b/bsd-user/arm/target_signal.h
+@@ -11,4 +11,29 @@ static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
+ #define TARGET_MINSIGSTKSZ (1024 * 4)
+ #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
+
++typedef target_ulong target_mcontext_t; /* dummy */
++
++typedef struct target_ucontext {
++ target_sigset_t uc_sigmask;
++ target_mcontext_t uc_mcontext;
++ abi_ulong uc_link;
++ target_stack_t uc_stack;
++ int32_t uc_flags;
++ int32_t __spare__[4];
++} target_ucontext_t;
++
++static inline int
++get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
++{
++ fprintf(stderr, "ARM doesn't have support for get_mcontext()\n");
++ return (-TARGET_ENOSYS);
++}
++
++static inline int
++set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
++{
++ fprintf(stderr, "ARM doesn't have support for set_mcontext()\n");
++ return (-TARGET_ENOSYS);
++}
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/freebsd/strace.list b/bsd-user/freebsd/strace.list
+index 1edf412..b09f766 100644
+--- a/bsd-user/freebsd/strace.list
++++ b/bsd-user/freebsd/strace.list
+@@ -38,6 +38,7 @@
+ { TARGET_FREEBSD_NR_fsync, "fsync", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_ftruncate, "ftruncate", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_futimes, "futimes", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_getcontext, "getcontext", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_getdirentries, "getdirentries", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_freebsd6_mmap, "freebsd6_mmap", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_getegid, "getegid", "%s()", NULL, NULL },
+@@ -123,6 +124,7 @@
+ { TARGET_FREEBSD_NR_semop, "semop", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_sendmsg, "sendmsg", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_sendto, "sendto", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_setcontext, "setcontext", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_setegid, "setegid", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_seteuid, "seteuid", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_setgid, "setgid", NULL, NULL, NULL },
+@@ -160,6 +162,15 @@
+ { TARGET_FREEBSD_NR_sync, "sync", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_sysarch, "sysarch", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_syscall, "syscall", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_thr_create, "thr_create", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_thr_exit, "thr_exit", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_thr_kill, "thr_kill", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_thr_kill2, "thr_kill2", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_thr_new, "thr_new", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_thr_self, "thr_self", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_thr_set_name, "thr_set_name", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_thr_suspend, "thr_suspend", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_thr_wake, "thr_wake", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_truncate, "truncate", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_umask, "umask", "%s(%#o)", NULL, NULL },
+ { TARGET_FREEBSD_NR_unlink, "unlink", "%s(\"%s\")", NULL, NULL },
+diff --git a/bsd-user/i386/target_signal.h b/bsd-user/i386/target_signal.h
+index 285e7f9..28481ce 100644
+--- a/bsd-user/i386/target_signal.h
++++ b/bsd-user/i386/target_signal.h
+@@ -11,4 +11,29 @@ static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
+ #define TARGET_MINSIGSTKSZ (512 * 4)
+ #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
+
++typedef target_ulong target_mcontext_t; /* dummy */
++
++typedef struct target_ucontext {
++ target_sigset_t uc_sigmask;
++ target_mcontext_t uc_mcontext;
++ abi_ulong uc_link;
++ target_stack_t uc_stack;
++ int32_t uc_flags;
++ int32_t __spare__[4];
++} target_ucontext_t;
++
++static inline int
++get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
++{
++ fprintf(stderr, "i386 doesn't have support for get_mcontext()\n");
++ return (-TARGET_ENOSYS);
++}
++
++static inline int
++set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
++{
++ fprintf(stderr, "i386 doesn't have support for set_mcontext()\n");
++ return (-TARGET_ENOSYS);
++}
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/main.c b/bsd-user/main.c
+index 146f022..7a99537 100644
+--- a/bsd-user/main.c
++++ b/bsd-user/main.c
+@@ -34,6 +34,10 @@
+ #include "qemu-timer.h"
+ #include "envlist.h"
+
++#if defined(CONFIG_USE_NPTL) && defined(__FreeBSD__)
++#include <sys/thr.h>
++#endif
++
+ #define DEBUG_LOGFILE "/tmp/qemu.log"
+
+ int singlestep;
+@@ -70,42 +74,186 @@ int cpu_get_pic_interrupt(CPUX86State *env)
+ }
+ #endif
+
+-/* These are no-ops because we are not threadsafe. */
+-static inline void cpu_exec_start(CPUArchState *env)
++#if defined(CONFIG_USE_NPTL)
++/* Helper routines for implementing atomic operations. */
++
++/*
++ * To implement exclusive operations we force all cpus to synchronize.
++ * We don't require a full sync, only that no cpus are executing guest code.
++ * The alternative is to map target atomic ops onto host eqivalents,
++ * which requires quite a lot of per host/target work.
++ */
++static pthread_mutex_t cpu_list_mutex = PTHREAD_MUTEX_INITIALIZER;
++static pthread_mutex_t exclusive_lock = PTHREAD_MUTEX_INITIALIZER;
++static pthread_cond_t exclusive_cond = PTHREAD_COND_INITIALIZER;
++static pthread_cond_t exclusive_resume = PTHREAD_COND_INITIALIZER;
++static int pending_cpus;
++
++/* Make sure everything is in a consistent state for calling fork(). */
++void fork_start(void)
+ {
++ pthread_mutex_lock(&tb_lock);
++ pthread_mutex_lock(&exclusive_lock);
++ mmap_fork_start();
+ }
+
+-static inline void cpu_exec_end(CPUArchState *env)
++void fork_end(int child)
+ {
++ mmap_fork_end(child);
++ if (child) {
++ /*
++ * Child processes created by fork() only have a single thread.
++ * Discard information about the parent threads.
++ */
++ first_cpu = thread_env;
++ thread_env->next_cpu = NULL;
++ pending_cpus = 0;
++ pthread_mutex_init(&exclusive_lock, NULL);
++ pthread_mutex_init(&cpu_list_mutex, NULL);
++ pthread_cond_init(&exclusive_cond, NULL);
++ pthread_cond_init(&exclusive_resume, NULL);
++ pthread_mutex_init(&tb_lock, NULL);
++ gdbserver_fork(thread_env);
++ } else {
++ pthread_mutex_unlock(&exclusive_lock);
++ pthread_mutex_unlock(&tb_lock);
++ }
+ }
+
+-static inline void start_exclusive(void)
++/*
++ * Wait for pending exclusive operations to complete. The exclusive lock
++ * must be held.
++ */
++static inline void
++exclusive_idle(void)
+ {
++ while (pending_cpus) {
++ pthread_cond_wait(&exclusive_resume, &exclusive_lock);
++ }
+ }
+
+-static inline void end_exclusive(void)
++/* Start an exclusive operation. Must only be called outside of cpu_exec. */
++static inline void
++start_exclusive(void)
+ {
++ CPUArchState *other;
++
++ pthread_mutex_lock(&exclusive_lock);
++ exclusive_idle();
++
++ pending_cpus = 1;
++ /* Make all other cpus stop executing. */
++ for (other = first_cpu; other; other = other->next_cpu) {
++ if (other->running) {
++ pending_cpus++;
++ cpu_exit(other);
++ }
++ }
++ if (pending_cpus > 1) {
++ pthread_cond_wait(&exclusive_cond, &exclusive_lock);
++ }
+ }
+
+-void fork_start(void)
++/* Finish an exclusive operation. */
++static inline void
++end_exclusive(void)
+ {
++ pending_cpus = 0;
++ pthread_cond_broadcast(&exclusive_resume);
++ pthread_mutex_unlock(&exclusive_lock);
+ }
+
+-void fork_end(int child)
++/* Wait for exclusive ops to finish, and begin cpu execution. */
++static inline void
++cpu_exec_start(CPUArchState *env)
++{
++ pthread_mutex_lock(&exclusive_lock);
++ exclusive_idle();
++ env->running = 1;
++ pthread_mutex_unlock(&exclusive_lock);
++}
++
++/* Mark cpu as not excuting, and release pending exclusive ops. */
++static inline void
++cpu_exec_end(CPUArchState *env)
++{
++ pthread_mutex_lock(&exclusive_lock);
++ env->running = 0;
++ if (pending_cpus > 1) {
++ pending_cpus--;
++ if (pending_cpus == 1) {
++ pthread_cond_signal(&exclusive_cond);
++ }
++ }
++ exclusive_idle();
++ pthread_mutex_unlock(&exclusive_lock);
++}
++
++void
++cpu_list_lock(void)
++{
++ pthread_mutex_lock(&cpu_list_mutex);
++}
++
++void
++cpu_list_unlock(void)
++{
++ pthread_mutex_unlock(&cpu_list_mutex);
++}
++
++#else /* ! CONFIG_USE_NPTL */
++
++/* These are no-ops because we are not threadsafe. */
++void
++fork_start(void)
++{
++}
++
++void
++fork_end(int child)
+ {
+ if (child) {
+ gdbserver_fork(thread_env);
+ }
+ }
+
+-void cpu_list_lock(void)
++static inline void
++exclusive_idle(void)
++{
++}
++
++static inline void
++start_exclusive(void)
+ {
+ }
+
+-void cpu_list_unlock(void)
++static inline void
++end_exclusive(void)
+ {
+ }
+
++static inline void
++cpu_exec_start(CPUArchState *env)
++{
++}
++
++
++static inline void
++cpu_exec_end(CPUArchState *env)
++{
++}
++
++void
++cpu_list_lock(void)
++{
++}
++
++void
++cpu_list_unlock(void)
++{
++}
++#endif /* CONFIG_USE_NPTL */
++
+ #ifdef TARGET_I386
+ /***********************************************************/
+ /* CPUX86 core interface */
+@@ -740,7 +888,10 @@ void cpu_loop(CPUMIPSState *env)
+
+ for(;;) {
+ cpu_exec_start(env);
++ /* XXX there is a concurrency problem - giant lock for now */
++ pthread_mutex_lock(&exclusive_lock); /* XXX */
+ trapnr = cpu_mips_exec(env);
++ pthread_mutex_unlock(&exclusive_lock); /* XXX */
+ cpu_exec_end(env);
+ switch(trapnr) {
+ case EXCP_SYSCALL: /* syscall exception */
+@@ -1206,6 +1357,18 @@ static void usage(void)
+
+ THREAD CPUArchState *thread_env;
+
++void task_settid(TaskState *ts)
++{
++ if (0 == ts->ts_tid) {
++#ifdef CONFIG_USE_NPTL
++ (void)thr_self(&ts->ts_tid);
++#else
++ /* When no threads then just use PID */
++ ts->ts_tid = getpid();
++#endif
++ }
++}
++
+ void stop_all_tasks(void)
+ {
+ /*
+diff --git a/bsd-user/mips/target_signal.h b/bsd-user/mips/target_signal.h
+index 28871c3..484cfd8 100644
+--- a/bsd-user/mips/target_signal.h
++++ b/bsd-user/mips/target_signal.h
+@@ -6,9 +6,187 @@
+ #define TARGET_MINSIGSTKSZ (512 * 4)
+ #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
+
+-static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state)
++struct target_sigcontext {
++ target_sigset_t sc_mask; /* signal mask to retstore */
++ int32_t sc_onstack; /* sigstack state to restore */
++ abi_long sc_pc; /* pc at time of signal */
++ abi_long sc_reg[32]; /* processor regs 0 to 31 */
++ abi_long mullo, mulhi; /* mullo and mulhi registers */
++ int32_t sc_fpused; /* fp has been used */
++ abi_long sc_fpregs[33]; /* fp regs 0 to 31 & csr */
++ abi_long sc_fpc_eir; /* fp exception instr reg */
++ /* int32_t reserved[8]; */
++};
++
++typedef struct target_mcontext {
++ int32_t mc_onstack; /* sigstack state to restore */
++ abi_long mc_pc; /* pc at time of signal */
++ abi_long mc_regs[32]; /* process regs 0 to 31 */
++ abi_long sr; /* status register */
++ abi_long mullo, mulhi;
++ int32_t mc_fpused; /* fp has been used */
++ abi_long mc_fpregs[33]; /* fp regs 0 to 32 & csr */
++ abi_long mc_fpc_eir; /* fp exception instr reg */
++ abi_ulong mc_tls; /* pointer to TLS area */
++} target_mcontext_t;
++
++typedef struct target_ucontext {
++ target_sigset_t uc_sigmask;
++ target_mcontext_t uc_mcontext;
++ abi_ulong uc_link;
++ target_stack_t uc_stack;
++ int32_t uc_flags;
++ int32_t __spare__[4];
++} target_ucontext_t;
++
++struct target_sigframe {
++ abi_ulong sf_signum;
++ abi_ulong sf_siginfo; /* code or pointer to sf_si */
++ abi_ulong sf_ucontext; /* points to sf_uc */
++ abi_ulong sf_addr; /* undocumented 4th arg */
++ target_ucontext_t sf_uc; /* = *sf_uncontext */
++ target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/
++ uint32_t __spare__[2];
++};
++
++
++/* Get the stack pointer. */
++static inline abi_ulong
++get_sp_from_cpustate(CPUMIPSState *state)
+ {
+ return state->active_tc.gpr[29];
+ }
+
++/*
++ * Compare to mips/mips/pm_machdep.c sendsig()
++ * Assumes that "frame" memory is locked.
++ */
++static inline int
++set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
++ abi_ulong frame_addr, struct target_sigaction *ka)
++{
++
++ frame->sf_signum = sig;
++ frame->sf_siginfo = 0;
++ frame->sf_ucontext = 0;
++
++ frame->sf_si.si_signo = sig;
++ frame->sf_si.si_code = TARGET_SA_SIGINFO;
++ frame->sf_si.si_addr = regs->CP0_BadVAddr;
++
++ /*
++ * Arguments to signal handler:
++ * a0 ($4) = signal number
++ * a1 ($5) = siginfo pointer
++ * a2 ($6) = ucontext pointer
++ * PC = signal handler pointer
++ * t9 ($25) = signal handler pointer
++ * $29 = point to sigframe struct
++ * ra ($31) = sigtramp at base of user stack
++ */
++ regs->active_tc.gpr[ 4] = sig;
++ regs->active_tc.gpr[ 5] = frame_addr +
++ offsetof(struct target_sigframe, sf_si);
++ regs->active_tc.gpr[25] = regs->active_tc.PC = ka->_sa_handler;
++ regs->active_tc.gpr[29] = frame_addr;
++ regs->active_tc.gpr[31] = TARGET_PS_STRINGS - TARGET_SZSIGCODE;
++
++ return (0);
++}
++
++/*
++ * Compare to mips/mips/pm_machdep.c get_mcontext()
++ * Assumes that the memory is locked if mcp points to user memory.
++ */
++static inline int
++get_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
++{
++ int i, err = 0;
++
++ if (flags & TARGET_MC_ADD_MAGIC) {
++ mcp->mc_regs[0] = tswapal(TARGET_UCONTEXT_MAGIC);
++ } else {
++ mcp->mc_regs[0] = 0;
++ }
++
++ if (flags & TARGET_MC_SET_ONSTACK) {
++ mcp->mc_onstack = tswapal(1);
++ } else {
++ mcp->mc_onstack = 0;
++ }
++
++ for(i = 1; i < 32; i++)
++ mcp->mc_regs[i] = tswapal(regs->active_tc.gpr[i]);
++
++#if 0 /* XXX FP is not used right now. */
++ abi_ulong used_fp = used_math() ? TARGET_MDTD_FPUSED : 0;
++
++ mcp->mc_fpused = used_fp;
++ if (used_fp) {
++ preempt_disable();
++ if (!is_fpu_owner()) {
++ own_fpu();
++ for(i = 0; i < 33; i++)
++ mcp->mc_fpregs[i] = tswapal(regs->active_fpu.fpr[i]);
++ }
++ preempt_enable();
++ }
++#else
++ mcp->mc_fpused = 0;
++#endif
++
++ if (flags & TARGET_MC_GET_CLEAR_RET) {
++ mcp->mc_regs[2] = 0; /* v0 = 0 */
++ mcp->mc_regs[3] = 0; /* v1 = 0 */
++ mcp->mc_regs[7] = 0; /* a3 = 0 */
++ }
++
++ mcp->mc_pc = tswapal(regs->active_tc.PC);
++ mcp->mullo = tswapal(regs->active_tc.LO[0]);
++ mcp->mulhi = tswapal(regs->active_tc.HI[0]);
++ mcp->mc_tls = tswapal(regs->tls_value);
++
++ /* Don't do any of the status and cause registers. */
++
++ return (err);
++}
++
++/* Compare to mips/mips/pm_machdep.c set_mcontext() */
++static inline int
++set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
++{
++ int i, err = 0;
++
++ for(i = 1; i < 32; i++)
++ regs->active_tc.gpr[i] = tswapal(mcp->mc_regs[i]);
++
++#if 0 /* XXX FP is not used right now */
++ abi_ulong used_fp = 0;
++
++ used_fp = tswapal(mcp->mc_fpused)
++ conditional_used_math(used_fp);
++
++ preempt_disabled();
++ if (used_math()) {
++ /* restore fpu context if we have used it before */
++ own_fpu();
++ for (i = 0; i < 32; i++)
++ regs->active_fpu.fpr[i] = tswapal(mcp->mc_fpregs[i]);
++ } else {
++ /* Signal handler may have used FPU. Give it up. */
++ lose_fpu();
++ }
++ preempt_enable();
++#endif
++
++ regs->CP0_EPC = tswapal(mcp->mc_pc);
++ regs->active_tc.LO[0] = tswapal(mcp->mullo);
++ regs->active_tc.HI[0] = tswapal(mcp->mulhi);
++ regs->tls_value = tswapal(mcp->mc_tls);
++
++ /* Don't do any of the status and cause registers. */
++
++ return (err);
++}
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/mips64/target_signal.h b/bsd-user/mips64/target_signal.h
+index d671f4e..e9c8a9f 100644
+--- a/bsd-user/mips64/target_signal.h
++++ b/bsd-user/mips64/target_signal.h
+@@ -7,11 +7,186 @@
+ #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
+ #define TARGET_SZSIGCODE 16
+
+-#define TARGET_UCONTEXT_MAGIC 0xACEDBADE
++struct target_sigcontext {
++ target_sigset_t sc_mask; /* signal mask to retstore */
++ int32_t sc_onstack; /* sigstack state to restore */
++ abi_long sc_pc; /* pc at time of signal */
++ abi_long sc_reg[32]; /* processor regs 0 to 31 */
++ abi_long mullo, mulhi; /* mullo and mulhi registers */
++ int32_t sc_fpused; /* fp has been used */
++ abi_long sc_fpregs[33]; /* fp regs 0 to 31 & csr */
++ abi_long sc_fpc_eir; /* fp exception instr reg */
++ /* int32_t reserved[8]; */
++};
+
+-static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state)
++typedef struct target_mcontext {
++ int32_t mc_onstack; /* sigstack state to restore */
++ abi_long mc_pc; /* pc at time of signal */
++ abi_long mc_regs[32]; /* process regs 0 to 31 */
++ abi_long sr; /* status register */
++ abi_long mullo, mulhi;
++ int32_t mc_fpused; /* fp has been used */
++ abi_long mc_fpregs[33]; /* fp regs 0 to 32 & csr */
++ abi_long mc_fpc_eir; /* fp exception instr reg */
++ abi_ulong mc_tls; /* pointer to TLS area */
++} target_mcontext_t;
++
++typedef struct target_ucontext {
++ target_sigset_t uc_sigmask;
++ target_mcontext_t uc_mcontext;
++ abi_ulong uc_link;
++ target_stack_t uc_stack;
++ int32_t uc_flags;
++ int32_t __spare__[4];
++} target_ucontext_t;
++
++struct target_sigframe {
++ abi_ulong sf_signum;
++ abi_ulong sf_siginfo; /* code or pointer to sf_si */
++ abi_ulong sf_ucontext; /* points to sf_uc */
++ abi_ulong sf_addr; /* undocumented 4th arg */
++ target_ucontext_t sf_uc; /* = *sf_uncontext */
++ target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/
++ uint32_t __spare__[2];
++};
++
++static inline abi_ulong
++get_sp_from_cpustate(CPUMIPSState *state)
+ {
+ return state->active_tc.gpr[29];
+ }
+
++/*
++ * Compare to mips/mips/pm_machdep.c sendsig()
++ * Assumes that "frame" memory is locked.
++ */
++static inline int
++set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
++ abi_ulong frame_addr, struct target_sigaction *ka)
++{
++
++ frame->sf_signum = sig;
++ frame->sf_siginfo = 0;
++ frame->sf_ucontext = 0;
++
++ frame->sf_si.si_signo = sig;
++ frame->sf_si.si_code = TARGET_SA_SIGINFO;
++ frame->sf_si.si_addr = regs->CP0_BadVAddr;
++
++ /*
++ * Arguments to signal handler:
++ * a0 ($4) = signal number
++ * a1 ($5) = siginfo pointer
++ * a2 ($6) = ucontext pointer
++ * PC = signal handler pointer
++ * t9 ($25) = signal handler pointer
++ * $29 = point to sigframe struct
++ * ra ($31) = sigtramp at base of user stack
++ */
++ regs->active_tc.gpr[ 4] = sig;
++ regs->active_tc.gpr[ 5] = frame_addr +
++ offsetof(struct target_sigframe, sf_si);
++ regs->active_tc.gpr[25] = regs->active_tc.PC = ka->_sa_handler;
++ regs->active_tc.gpr[29] = frame_addr;
++ regs->active_tc.gpr[31] = TARGET_PS_STRINGS - TARGET_SZSIGCODE;
++
++ return (0);
++}
++
++/*
++ * Compare to mips/mips/pm_machdep.c get_mcontext()
++ * Assumes that the memory is locked if mcp points to user memory.
++ */
++static inline int
++get_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
++{
++ int i, err = 0;
++
++ if (flags & TARGET_MC_ADD_MAGIC) {
++ mcp->mc_regs[0] = tswapal(TARGET_UCONTEXT_MAGIC);
++ } else {
++ mcp->mc_regs[0] = 0;
++ }
++
++ if (flags & TARGET_MC_SET_ONSTACK) {
++ mcp->mc_onstack = tswapal(1);
++ } else {
++ mcp->mc_onstack = 0;
++ }
++
++ for(i = 1; i < 32; i++)
++ mcp->mc_regs[i] = tswapal(regs->active_tc.gpr[i]);
++
++#if 0 /* XXX FP is not used right now */
++ abi_ulong used_fp = used_math() ? TARGET_MDTD_FPUSED : 0;
++
++ mcp->mc_fpused = used_fp;
++ if (used_fp) {
++ preempt_disable();
++ if (!is_fpu_owner()) {
++ own_fpu();
++ for(i = 0; i < 33; i++)
++ mcp->mc_fpregs[i] = tswapal(regs->active_fpu.fpr[i]);
++ }
++ preempt_enable();
++ }
++#else
++ mcp->mc_fpused = 0;
++#endif
++
++ if (flags & TARGET_MC_GET_CLEAR_RET) {
++ mcp->mc_regs[2] = 0; /* v0 = 0 */
++ mcp->mc_regs[3] = 0; /* v1 = 0 */
++ mcp->mc_regs[7] = 0; /* a3 = 0 */
++ }
++
++ mcp->mc_pc = tswapal(regs->active_tc.PC);
++ mcp->mullo = tswapal(regs->active_tc.LO[0]);
++ mcp->mulhi = tswapal(regs->active_tc.HI[0]);
++ mcp->mc_tls = tswapal(regs->tls_value);
++
++ /* Don't do any of the status and cause registers. */
++
++ return (err);
++}
++
++/* Compare to mips/mips/pm_machdep.c set_mcontext() */
++static inline int
++set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
++{
++ int i, err = 0;
++
++ for(i = 1; i < 32; i++)
++ regs->active_tc.gpr[i] = tswapal(mcp->mc_regs[i]);
++
++#if 0 /* XXX FP is not used right now */
++ abi_ulong used_fp = 0;
++
++ used_fp = tswapal(mcp->mc_fpused)
++ conditional_used_math(used_fp);
++
++ preempt_disabled();
++ if (used_math()) {
++ /* restore fpu context if we have used it before */
++ own_fpu();
++ for (i = 0; i < 32; i++)
++ regs->active_fpu.fpr[i] = tswapal(mcp->mc_fpregs[i]);
++ } else {
++ /* Signal handler may have used FPU. Give it up. */
++ lose_fpu();
++ }
++ preempt_enable();
++#endif
++
++ regs->CP0_EPC = tswapal(mcp->mc_pc);
++ regs->active_tc.LO[0] = tswapal(mcp->mullo);
++ regs->active_tc.HI[0] = tswapal(mcp->mulhi);
++ regs->tls_value = tswapal(mcp->mc_tls);
++
++ /* Don't do any of the status and cause registers. */
++
++ return (err);
++}
++
+ #endif /* TARGET_SIGNAL_H */
++
+diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
+--- a/bsd-user/mmap.c
++++ b/bsd-user/mmap.c
+@@ -74,6 +74,8 @@ void mmap_unlock(void)
+ }
+ #endif
+
++#if 0 /* XXX not sure why we need our own g_malloc() and friends.
++ g_strdup(), however, has serious problems with this g_malloc/g_free */
+ static void *bsd_vmalloc(size_t size)
+ {
+ void *p;
+@@ -133,6 +135,7 @@ void *g_realloc(void *ptr, size_t size)
+ g_free(ptr);
+ return new_ptr;
+ }
++#endif
+
+ /* NOTE: all the constants are the HOST ones, but addresses are target. */
+ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
+diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
+index ab7e18c..9d4edbf 100644
+--- a/bsd-user/qemu.h
++++ b/bsd-user/qemu.h
+@@ -80,7 +80,7 @@ struct emulated_sigtable {
+ typedef struct TaskState {
+ struct TaskState *next;
+ int used; /* non zero if used */
+-#if 1
++ long ts_tid; /* tid (or pid) of this task */
+ #ifdef TARGET_ARM
+ int swi_errno;
+ #endif
+@@ -90,7 +90,6 @@ typedef struct TaskState {
+ uint32_t heap_limit;
+ #endif
+ uint32_t stack_base;
+-#endif
+ struct image_info *info;
+ struct bsd_binprm *bprm;
+
+diff --git a/bsd-user/signal.c b/bsd-user/signal.c
+index 52441c4..d56837b 100644
+--- a/bsd-user/signal.c
++++ b/bsd-user/signal.c
+@@ -31,7 +31,7 @@
+ #include "qemu.h"
+ #include "target_signal.h"
+
+-//#define DEBUG_SIGNAL
++// #define DEBUG_SIGNAL
+
+ #ifndef _NSIG
+ #define _NSIG 128
+@@ -606,101 +606,31 @@ do_sigaction(int sig, const struct target_sigaction *act,
+ return (ret);
+ }
+
+-#if defined(TARGET_MIPS64)
+-static inline int
+-restore_sigmcontext(CPUMIPSState *regs, target_mcontext_t *mc)
+-{
+- int i, err = 0;
+-
+- for(i = 1; i < 32; i++)
+- err |= __get_user(regs->active_tc.gpr[i],
+- &mc->mc_regs[i]);
+- err |= __get_user(regs->CP0_EPC, &mc->mc_pc);
+- err |= __get_user(regs->active_tc.LO[0], &mc->mullo);
+- err |= __get_user(regs->active_tc.HI[0], &mc->mulhi);
+- err |= __get_user(regs->tls_value, &mc->mc_tls); /* XXX thread tls */
+-
+-#if 0 /* XXX */
+- int used_fp = 0;
+-
+- err |= __get_user(used_fp, &mc->mc_fpused);
+- conditional_used_math(used_fp);
+-
+- preempt_disabled();
+- if (used_math()) {
+- /* restore fpu context if we have used it before */
+- own_fpu();
+- err |= restore_fp_context(mc);
+- } else {
+- /* signal handler may have used FPU. Give it up. */
+- lose_fpu();
+- }
+- preempt_enable();
+-#endif
+-
+- return (err);
+-}
+-
+-static inline int
+-setup_sigmcontext(CPUMIPSState *regs, target_mcontext_t *mc, int32_t oonstack)
+-{
+- int i, err = 0;
+- abi_long ucontext_magic = TARGET_UCONTEXT_MAGIC;
+-
+- err = __put_user(oonstack ? 1 : 0, &mc->mc_onstack);
+- err |= __put_user(regs->active_tc.PC, &mc->mc_pc);
+- err |= __put_user(regs->active_tc.LO[0], &mc->mullo);
+- err |= __put_user(regs->active_tc.HI[0], &mc->mulhi);
+- err |= __put_user(regs->tls_value, &mc->mc_tls); /* XXX thread tls */
+-
+- err |= __put_user(ucontext_magic, &mc->mc_regs[0]);
+- for(i = 1; i < 32; i++)
+- err |= __put_user(regs->active_tc.gpr[i], &mc->mc_regs[i]);
+-
+- err |= __put_user(0, &mc->mc_fpused);
+-
+-#if 0 /* XXX */
+- err |= __put_user(used_math(), &mc->mc_fpused);
+- if (used_math())
+- goto out;
+-
+- /*
+- * Save FPU state to signal context. Signal handler will "inherit"
+- * current FPU state.
+- */
+- preempt_disable();
+-
+- if (!is_fpu_owner()) {
+- own_fpu();
+- for(i = 0; i < 33; i++)
+- err |= __put_user(regs->active_tc.fpregs[i], &mc->mc_fpregs[i]);
+- }
+- err |= save_fp_context(fg);
+-
+- preempt_enable();
+-out:
+-#endif
+- return (err);
+-}
++#if defined(TARGET_MIPS) || defined(TARGET_SPARC64)
+
+ static inline abi_ulong
+-get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
++get_sigframe(struct target_sigaction *ka, CPUArchState *regs, size_t frame_size)
+ {
+ abi_ulong sp;
+
+ /* Use default user stack */
+- sp = regs->active_tc.gpr[29];
++ sp = get_sp_from_cpustate(regs);
+
+ if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
+- sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
++ sp = target_sigaltstack_used.ss_sp +
++ target_sigaltstack_used.ss_size;
+ }
+
++#if defined(TARGET_MIPS)
+ return ((sp - frame_size) & ~7);
++#else
++ return (sp - frame_size);
++#endif
+ }
+
+-/* compare to mips/mips/pm_machdep.c sendsig() */
++/* compare to mips/mips/pm_machdep.c and sparc64/sparc64/machdep.c sendsig() */
+ static void setup_frame(int sig, struct target_sigaction *ka,
+- target_sigset_t *set, CPUMIPSState *regs)
++ target_sigset_t *set, CPUArchState *regs)
+ {
+ struct target_sigframe *frame;
+ abi_ulong frame_addr;
+@@ -709,54 +639,36 @@ static void setup_frame(int sig, struct target_sigaction *ka,
+ #ifdef DEBUG_SIGNAL
+ fprintf(stderr, "setup_frame()\n");
+ #endif
++#if defined(TARGET_SPARC64)
++ if (!sparc_user_sigtramp) {
++ /* No signal trampoline... kill the process. */
++ fprintf(stderr, "setup_frame(): no sigtramp\n");
++ force_sig(TARGET_SIGKILL);
++ }
++#endif
+
+ frame_addr = get_sigframe(ka, regs, sizeof(*frame));
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
+ goto give_sigsegv;
+
+- if (setup_sigmcontext(regs, &frame->sf_uc.uc_mcontext,
+- ! on_sig_stack(frame_addr)))
++#if defined(TARGET_MIPS)
++ int mflags = on_sig_stack(frame_addr) ? TARGET_MC_ADD_MAGIC :
++ TARGET_MC_SET_ONSTACK | TARGET_MC_ADD_MAGIC;
++#else
++ int mflags = 0;
++#endif
++ if (get_mcontext(regs, &frame->sf_uc.uc_mcontext, mflags))
+ goto give_sigsegv;
+
+ for(i = 0; i < TARGET_NSIG_WORDS; i++) {
+- if (__put_user(set->__bits[i], &frame->sf_uc.uc_sigmask.__bits[i]))
++ if (__put_user(set->__bits[i],
++ &frame->sf_uc.uc_sigmask.__bits[i]))
+ goto give_sigsegv;
+ }
+
+- /* fill in sigframe structure */
+- if (__put_user(sig, &frame->sf_signum))
+- goto give_sigsegv;
+- if (__put_user(0, &frame->sf_siginfo))
+- goto give_sigsegv;
+- if (__put_user(0, &frame->sf_ucontext))
++ if (set_sigtramp_args(regs, sig, frame, frame_addr, ka))
+ goto give_sigsegv;
+
+- /* fill in siginfo structure */
+- if (__put_user(sig, &frame->sf_si.si_signo))
+- goto give_sigsegv;
+- if (__put_user(TARGET_SA_SIGINFO, &frame->sf_si.si_code))
+- goto give_sigsegv;
+- if (__put_user(regs->CP0_BadVAddr, &frame->sf_si.si_addr))
+- goto give_sigsegv;
+-
+- /*
+- * Arguments to signal handler:
+- * a0 ($4) = signal number
+- * a1 ($5) = siginfo pointer
+- * a2 ($6) = ucontext pointer
+- * PC = signal handler pointer
+- * t9 ($25) = signal handler pointer
+- * $29 = point to sigframe struct
+- * ra ($31) = sigtramp at base of user stack
+- */
+- regs->active_tc.gpr[ 4] = sig;
+- regs->active_tc.gpr[ 5] = frame_addr +
+- offsetof(struct target_sigframe, sf_si);
+- regs->active_tc.gpr[ 6] = frame_addr +
+- offsetof(struct target_sigframe, sf_uc);
+- regs->active_tc.gpr[25] = regs->active_tc.PC = ka->_sa_handler;
+- regs->active_tc.gpr[29] = frame_addr;
+- regs->active_tc.gpr[31] = TARGET_PS_STRINGS - TARGET_SZSIGCODE;
+ unlock_user_struct(frame, frame_addr, 1);
+ return;
+
+@@ -766,7 +678,7 @@ give_sigsegv:
+ }
+
+ long
+-do_sigreturn(CPUMIPSState *regs, abi_ulong uc_addr)
++do_sigreturn(CPUArchState *regs, abi_ulong uc_addr)
+ {
+ target_ucontext_t *ucontext;
+ sigset_t blocked;
+@@ -784,14 +696,17 @@ do_sigreturn(CPUMIPSState *regs, abi_ulong uc_addr)
+ goto badframe;
+ }
+
+- if (restore_sigmcontext(regs, &ucontext->uc_mcontext))
++ if (set_mcontext(regs, &ucontext->uc_mcontext, 0))
+ goto badframe;
+
+ target_to_host_sigset_internal(&blocked, &target_set);
+ sigprocmask(SIG_SETMASK, &blocked, NULL);
+
+- regs->active_tc.PC = regs->CP0_EPC;
+- regs->CP0_EPC = 0; /* XXX for nested signals ? */
++#if defined(TARGET_MIPS)
++ CPUMIPSState *mips_regs = (CPUMIPSState *)regs;
++ mips_regs->active_tc.PC = mips_regs->CP0_EPC;
++ mips_regs->CP0_EPC = 0; /* XXX for nested signals ? */
++#endif
+ return (-TARGET_QEMU_ESIGRETURN);
+
+ badframe:
+@@ -799,9 +714,10 @@ badframe:
+ return (0);
+ }
+
+-#elif defined(TARGET_SPARC64)
+
+-extern abi_ulong sparc_user_sigtramp;
++
++/* #elif defined(TARGET_SPARC64) */
++#if 0
+
+ #define mc_flags mc_global[0]
+ #define mc_sp mc_out[6]
+@@ -1039,6 +955,7 @@ badframe:
+ force_sig(TARGET_SIGSEGV);
+ return (0);
+ }
++#endif
+
+ #else
+
+diff --git a/bsd-user/sparc/target_signal.h b/bsd-user/sparc/target_signal.h
+index 79dfc1e..e2fe79c 100644
+--- a/bsd-user/sparc/target_signal.h
++++ b/bsd-user/sparc/target_signal.h
+@@ -13,9 +13,34 @@
+ #define TARGET_MINSIGSTKSZ (512 * 4)
+ #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
+
++typedef target_ulong target_mcontext_t; /* dummy */
++
++typedef struct target_ucontext {
++ target_sigset_t uc_sigmask;
++ target_mcontext_t uc_mcontext;
++ abi_ulong uc_link;
++ target_stack_t uc_stack;
++ int32_t uc_flags;
++ int32_t __spare__[4];
++} target_ucontext_t;
++
+ static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
+ {
+ return state->regwptr[UREG_FP];
+ }
+
++static inline int
++get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
++{
++ fprintf(stderr, "SPARC doesn't have support for get_mcontext()\n");
++ return (-TARGET_ENOSYS);
++}
++
++static inline int
++set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
++{
++ fprintf(stderr, "SPARC doesn't have support for set_mcontext()\n");
++ return (-TARGET_ENOSYS);
++}
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/sparc64/target_signal.h b/bsd-user/sparc64/target_signal.h
+index d3e58bb..1bc7c96 100644
+--- a/bsd-user/sparc64/target_signal.h
++++ b/bsd-user/sparc64/target_signal.h
+@@ -10,12 +10,239 @@
+ #define UREG_FP UREG_I6
+ #endif
+
++#define mc_flags mc_global[0]
++#define mc_sp mc_out[6]
++#define mc_fprs mc_local[0]
++#define mc_fsr mc_local[1]
++#define mc_gsr mc_local[2]
++#define mc_tnpc mc_in[0]
++#define mc_tpc mc_in[1]
++#define mc_tstate mc_in[2]
++#define mc_y mc_in[4]
++#define mc_wstate mc_in[5]
++
++#define ureg_i0 regwptr[0 ]
++#define ureg_i1 regwptr[1 ]
++#define ureg_i2 regwptr[2 ]
++#define ureg_i3 regwptr[3 ]
++#define ureg_i4 regwptr[4 ]
++#define ureg_i5 regwptr[5 ]
++#define ureg_i6 regwptr[6 ]
++#define ureg_i7 regwptr[7 ]
++#define ureg_l0 regwptr[8 ]
++#define ureg_l1 regwptr[9 ]
++#define ureg_l2 regwptr[10]
++#define ureg_l3 regwptr[11]
++#define ureg_l4 regwptr[12]
++#define ureg_l5 regwptr[13]
++#define ureg_l6 regwptr[14]
++#define ureg_l7 regwptr[15]
++#define ureg_o0 regwptr[16]
++#define ureg_o1 regwptr[17]
++#define ureg_o2 regwptr[18]
++#define ureg_o3 regwptr[19]
++#define ureg_o4 regwptr[20]
++#define ureg_o5 regwptr[21]
++#define ureg_o6 regwptr[22]
++#define ureg_o7 regwptr[23]
++#define ureg_fp ureg_i6
++#define ureg_sp ureg_o6
++#define ureg_fprs fprs
++#define ureg_fsr fsr
++#define ureg_gsr gsr
++#define ureg_tnpc npc
++#define ureg_tpc pc
++#define ureg_y y
++
++#define TARGET_FPRS_FEF (1 << 2)
++#define TARGET_MC_VERSION 1L
++
+ #define TARGET_MINSIGSTKSZ (1024 * 4)
+ #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
+
+-static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
++#define TARGET_STACK_BIAS 2047 /* AKA. SPOFF */
++
++struct target_mcontext {
++ uint64_t mc_global[8];
++ uint64_t mc_out[8];
++ uint64_t mc_local[8];
++ uint64_t mc_in[8];
++ uint32_t mc_fp[64];
++} __aligned(64);
++
++typedef struct target_mcontext target_mcontext_t;
++
++typedef struct target_ucontext {
++ target_sigset_t uc_sigmask;
++ target_mcontext_t uc_mcontext;
++ abi_ulong uc_link;
++ target_stack_t uc_stack;
++ int32_t uc_flags;
++ int32_t __spare__[4];
++} target_ucontext_t;
++
++struct target_sigframe {
++ target_ucontext_t sf_uc;
++ target_siginfo_t sf_si;
++};
++
++extern abi_ulong sparc_user_sigtramp;
++
++static inline int
++set_sigtramp_args(CPUSPARCState *regs, int sig, struct target_sigframe *frame,
++ abi_ulong frame_addr, struct target_sigaction *ka)
+ {
++
++ frame->sf_si.si_signo = sig;
++ frame->sf_si.si_code = TARGET_SA_SIGINFO;
++
++ /* Arguments to signal handler:
++ *
++ * i0 = signal number
++ * i1 = pointer to siginfo struct
++ * i2 = pointer to ucontext struct
++ * i3 = (not used in new style)
++ * i4 = signal handler address (called by sigtramp)
++ */
++ regs->ureg_i0 = sig;
++ regs->ureg_i1 = frame_addr +
++ offsetof(struct target_sigframe, sf_si);
++ regs->ureg_i2 = frame_addr +
++ offsetof(struct target_sigframe, sf_uc);
++ /* env->ureg_o3 used in the Old FreeBSD-style arguments. */
++ regs->ureg_i4 = ka->_sa_handler;
++ regs->ureg_tpc = sparc_user_sigtramp;
++ regs->ureg_tnpc = (regs->ureg_tpc + 4);
++ regs->ureg_sp = frame_addr - TARGET_STACK_BIAS;
++
++ return (0);
++}
++
++static inline abi_ulong
++get_sp_from_cpustate(CPUSPARCState *state)
++{
++
+ return state->regwptr[UREG_FP];
+ }
+
++/* compare to sparc64/sparc64/machdep.c get_mcontext() */
++static inline int
++get_mcontext(CPUSPARCState *regs, target_mcontext_t *mcp, int flags)
++{
++
++ /* Skip over the trap instruction, first. */
++ regs->pc = regs->npc;
++ regs->npc += 4;
++
++ mcp->mc_flags = TARGET_MC_VERSION; /* mc_global[0] */
++ mcp->mc_global[1] = tswapal(regs->gregs[1]);
++ mcp->mc_global[2] = tswapal(regs->gregs[2]);
++ mcp->mc_global[3] = tswapal(regs->gregs[3]);
++ mcp->mc_global[4] = tswapal(regs->gregs[4]);
++ mcp->mc_global[5] = tswapal(regs->gregs[5]);
++ mcp->mc_global[6] = tswapal(regs->gregs[6]);
++ /* skip %g7 since it is used as the userland TLS register */
++
++ if (flags & TARGET_MC_GET_CLEAR_RET) {
++ mcp->mc_out[0] = 0;
++ mcp->mc_out[1] = 0;
++ } else {
++ mcp->mc_out[0] = tswapal(regs->ureg_i0);
++ mcp->mc_out[1] = tswapal(regs->ureg_i1);
++ }
++ mcp->mc_out[2] = tswapal(regs->ureg_i2);
++ mcp->mc_out[3] = tswapal(regs->ureg_i3);
++ mcp->mc_out[4] = tswapal(regs->ureg_i4);
++ mcp->mc_out[5] = tswapal(regs->ureg_i5);
++ mcp->mc_out[6] = tswapal(regs->ureg_i6);
++ mcp->mc_out[7] = tswapal(regs->ureg_i7);
++
++ mcp->mc_fprs = tswapal(regs->fprs); /* mc_local[0] */
++ mcp->mc_fsr = tswapal(regs->fsr); /* mc_local[1] */
++ mcp->mc_gsr = tswapal(regs->gsr); /* mc_local[2] */
++
++ mcp->mc_tnpc = tswapal(regs->npc); /* mc_in[0] */
++ mcp->mc_tpc = tswapal(regs->pc); /* mc_in[1] */
++#if 0
++ mcp->mc_tstate = tswapal(regs->ureg_tstate); /* mc_in[2] */
++#else
++ abi_ulong cwp64 = cpu_get_cwp64(regs);
++ abi_ulong ccr = cpu_get_ccr(regs) << 32;
++ abi_ulong asi = (regs->asi & 0xff) << 24;
++ mcp->mc_tstate = tswapal(ccr | asi | cwp64);
++#endif
++
++ mcp->mc_y = tswapal(regs->y); /* mc_in[4] */
++
++ /* XXX
++ if ((regs->ureg_l0 & TARGET_FPRS_FEF) != 0) {
++ int i;
++
++ for(i = 0; i < 64; i++)
++ mcp->mc_fp[i] = tswapal(regs->fpr[i]);
++ }
++ */
++
++ return (0);
++}
++
++extern void helper_flushw(CPUSPARCState *env);
++
++/* compare to sparc64/sparc64/machdep.c set_mcontext() */
++static inline int
++set_mcontext(CPUSPARCState *regs, target_mcontext_t *mcp, int flags)
++{
++ /* XXX need to add version check here. */
++
++ /* Make sure the windows are spilled first. */
++ helper_flushw(regs);
++
++ regs->gregs[1] = tswapal(mcp->mc_global[1]);
++ regs->gregs[2] = tswapal(mcp->mc_global[2]);
++ regs->gregs[3] = tswapal(mcp->mc_global[3]);
++ regs->gregs[4] = tswapal(mcp->mc_global[4]);
++ regs->gregs[5] = tswapal(mcp->mc_global[5]);
++ regs->gregs[6] = tswapal(mcp->mc_global[6]);
++
++ regs->ureg_i0 = tswapal(mcp->mc_out[0]);
++ regs->ureg_i1 = tswapal(mcp->mc_out[1]);
++ regs->ureg_i2 = tswapal(mcp->mc_out[2]);
++ regs->ureg_i3 = tswapal(mcp->mc_out[3]);
++ regs->ureg_i4 = tswapal(mcp->mc_out[4]);
++ regs->ureg_i5 = tswapal(mcp->mc_out[5]);
++ regs->ureg_i6 = tswapal(mcp->mc_out[6]);
++ regs->ureg_i7 = tswapal(mcp->mc_out[7]);
++
++ regs->fprs = tswapal(mcp->mc_fprs); /* mc_local[0] */
++ regs->fsr = tswapal(mcp->mc_fsr); /* mc_local[1] */
++ regs->gsr = tswapal(mcp->mc_gsr); /* mc_local[2] */
++
++ regs->npc = tswapal(mcp->mc_tnpc); /* mc_in[0] */
++ regs->pc = tswapal(mcp->mc_tpc); /* mc_in[1] */
++
++#if 0
++ regs->ureg_tstate = tswapal(mcp->mc_tstate); /* mc_in[2] */
++#else
++ abi_ulong tstate = tswapal(mcp->mc_tstate); /* mc_in[2] */
++
++ regs->asi = (tstate >> 24) & 0xff;
++ cpu_put_ccr(regs, tstate >> 32);
++ cpu_put_cwp64(regs, tstate & 0x1f);
++
++#endif
++ regs->ureg_y = tswapal(mcp->mc_y); /* mc_in[4] */
++
++ /* XXX
++ if ((regs->ureg_fprs & TARGET_FPRS_FEF) != 0) {
++ int i;
++
++ regs->ureg_l0 = 0;
++ for(i = 0; i < 64; i++)
++ regs->fpr[i] = tswapal(mcp->mc_fp[i]);
++ }
++ */
++
++ return (0);
++}
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
+index 625c3cf..4deb0db 100644
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -43,6 +43,12 @@
+ #ifdef __FreeBSD__
+ #include <sys/regression.h>
+ #include <sys/procdesc.h>
++#include <sys/ucontext.h>
++#include <sys/thr.h>
++#include <sys/rtprio.h>
++#include <sys/umtx.h>
++#include <pthread.h>
++#include <machine/atomic.h>
+ #endif
+ #include <sys/un.h>
+ #include <sys/ipc.h>
+@@ -251,7 +257,24 @@ static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
+ #ifdef TARGET_MIPS
+ static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
+ {
+- return -TARGET_EINVAL;
++ int ret = 0;
++ CPUMIPSState *mips_env = (CPUMIPSState *)env;
++
++ switch(op) {
++ case TARGET_MIPS_SET_TLS:
++ if (get_user(mips_env->tls_value, parms, abi_ulong))
++ ret = -TARGET_EFAULT;
++ break;
++ case TARGET_MIPS_GET_TLS:
++ if (put_user(mips_env->tls_value, parms, abi_ulong))
++ ret = -TARGET_EFAULT;
++ break;
++ default:
++ ret = -TARGET_EINVAL;
++ break;
++ }
++
++ return (ret);
+ }
+ #endif
+
+@@ -2119,6 +2142,383 @@ do_fork(CPUArchState *env, int num, int flags, int *fdp)
+ return (ret);
+ }
+
++#if defined(CONFIG_USE_NPTL)
++
++#define NEW_STACK_SIZE (0x40000)
++
++static pthread_mutex_t new_thread_lock = PTHREAD_MUTEX_INITIALIZER;
++typedef struct {
++ CPUArchState *env;
++ long tid;
++ pthread_mutex_t mutex;
++ pthread_cond_t cond;
++ pthread_t thread;
++ sigset_t sigmask;
++ struct target_thr_param param;
++} new_thread_info_t;
++
++static void *
++new_thread_start(void *arg)
++{
++ new_thread_info_t *info = arg;
++ CPUArchState *env;
++ TaskState *ts;
++ long tid;
++
++ env = info->env;
++ thread_env = env;
++ ts = (TaskState *)thread_env->opaque;
++ (void)thr_self(&tid);
++ info->tid = tid;
++ task_settid(ts);
++
++ /* copy out the TID info */
++ if (info->param.child_tid)
++ put_user(tid, info->param.child_tid, abi_long);
++ if (info->param.parent_tid)
++ put_user(tid, info->param.parent_tid, abi_long);
++
++#ifdef TARGET_MIPS64
++ CPUMIPSState *regs = env;
++ regs->active_tc.gpr[25] = regs->active_tc.PC = info->param.start_func;
++ regs->active_tc.gpr[ 4] = info->param.arg;
++ regs->active_tc.gpr[29] = info->param.stack_base;
++#endif
++ /* Eenable signals */
++ sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
++ /* Signal to the parent that we're ready. */
++ pthread_mutex_lock(&info->mutex);
++ pthread_cond_broadcast(&info->cond);
++ pthread_mutex_unlock(&info->mutex);
++ /* Wait until the parent has finished initializing the TLS state. */
++ pthread_mutex_lock(&new_thread_lock);
++ pthread_mutex_unlock(&new_thread_lock);
++
++ cpu_loop(env);
++ /* never exits */
++
++ return (NULL);
++}
++
++static void
++rtp_to_schedparam(const struct rtprio *rtp, int *policy, struct sched_param *param)
++{
++
++ switch(rtp->type) {
++ case RTP_PRIO_REALTIME:
++ *policy = SCHED_RR;
++ param->sched_priority = RTP_PRIO_MAX - rtp->prio;
++ break;
++
++ case RTP_PRIO_FIFO:
++ *policy = SCHED_FIFO;
++ param->sched_priority = RTP_PRIO_MAX - rtp->prio;
++ break;
++
++ default:
++ *policy = SCHED_OTHER;
++ param->sched_priority = 0;
++ break;
++ }
++}
++
++static int
++do_thr_create(CPUArchState *env, ucontext_t *ctx, long *id, int flags)
++{
++
++ return (unimplemented(TARGET_FREEBSD_NR_thr_create));
++}
++
++static int
++do_thr_new(CPUArchState *env, abi_ulong target_param_addr, int32_t param_size)
++{
++ new_thread_info_t info;
++ pthread_attr_t attr;
++ TaskState *ts;
++ CPUArchState *new_env;
++ struct target_thr_param *target_param;
++ abi_ulong target_rtp_addr;
++ struct target_rtprio *target_rtp;
++ struct rtprio *rtp_ptr, rtp;
++ TaskState *parent_ts = (TaskState *)env->opaque;
++ sigset_t sigmask;
++ struct sched_param sched_param;
++ int sched_policy;
++ int ret = 0;
++
++ memset(&info, 0, sizeof(info));
++
++ if (!lock_user_struct(VERIFY_READ, target_param, target_param_addr, 1))
++ return (-TARGET_EFAULT);
++ info.param.start_func = tswapal(target_param->start_func);
++ info.param.arg = tswapal(target_param->arg);
++ info.param.stack_base = tswapal(target_param->stack_base);
++ info.param.stack_size = tswapal(target_param->stack_size);
++ info.param.tls_base = tswapal(target_param->tls_base);
++ info.param.tls_size = tswapal(target_param->tls_size);
++ info.param.child_tid = tswapal(target_param->child_tid);
++ info.param.parent_tid = tswapal(target_param->parent_tid);
++ target_rtp_addr = info.param.rtp = tswapal(target_param->rtp);
++ unlock_user(target_param, target_param_addr, 0);
++
++ if (target_rtp_addr) {
++ if (!lock_user_struct(VERIFY_READ, target_rtp, target_rtp_addr,
++ 1))
++ return (-TARGET_EFAULT);
++ rtp.type = tswap16(target_rtp->type);
++ rtp.prio = tswap16(target_rtp->prio);
++ unlock_user(target_rtp, target_rtp_addr, 0);
++ rtp_ptr = &rtp;
++ } else {
++ rtp_ptr = NULL;
++ }
++
++ /* Create a new CPU instance. */
++ ts = g_malloc0(sizeof(TaskState));
++ init_task_state(ts);
++ new_env = cpu_copy(env);
++#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
++ cpu_reset(ENV_GET_CPU(new_env));
++#endif
++
++ /* init regs that differ from the parent thread. */
++ cpu_clone_regs(new_env, info.param.stack_base);
++ new_env->opaque = ts;
++ ts->bprm = parent_ts->bprm;
++ ts->info = parent_ts->info;
++
++#if defined(TARGET_MIPS)
++ env->tls_value = info.param.tls_base;
++ /* cpu_set_tls(new_env, info.param.tls_base); */
++#endif
++
++ /* Grab a mutex so that thread setup appears atomic. */
++ pthread_mutex_lock(&new_thread_lock);
++
++ pthread_mutex_init(&info.mutex, NULL);
++ pthread_mutex_lock(&info.mutex);
++ pthread_cond_init(&info.cond, NULL);
++ info.env = new_env;
++
++ /* XXX return value needs to be checked... */
++ pthread_attr_init(&attr);
++ pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
++ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
++ if (rtp_ptr) {
++ rtp_to_schedparam(&rtp, &sched_policy, &sched_param);
++ pthread_attr_setschedpolicy(&attr, sched_policy);
++ pthread_attr_setschedparam(&attr, &sched_param);
++ }
++
++ /*
++ * It is not safe to deliver signals until the child has finished
++ * initializing, so temporarily block all signals.
++ */
++ sigfillset(&sigmask);
++ sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
++
++ /* XXX return value needs to be checked... */
++ ret = pthread_create(&info.thread, &attr, new_thread_start, &info);
++ /* XXX Free new CPU state if thread creation fails. */
++
++ sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
++ pthread_attr_destroy(&attr);
++ if (0 == ret) {
++ /* Wait for the child to initialize. */
++ pthread_cond_wait(&info.cond, &info.mutex);
++ } else {
++ /* pthread_create failed. */
++ }
++
++ pthread_mutex_unlock(&info.mutex);
++ pthread_cond_destroy(&info.cond);
++ pthread_mutex_destroy(&info.mutex);
++ pthread_mutex_unlock(&new_thread_lock);
++
++ return (ret);
++}
++
++static int
++do_thr_self(long *id)
++{
++
++ return (get_errno(thr_self(id)));
++}
++
++static void
++do_thr_exit(CPUArchState *cpu_env, abi_ulong tid_addr)
++{
++
++ if (first_cpu->next_cpu) {
++ TaskState *ts;
++ CPUArchState **lastp, *p;
++
++ /*
++ * *XXX This probably breaks if a signal arrives.
++ * We should disable signals.
++ */
++ cpu_list_lock();
++ lastp = &first_cpu;
++ p = first_cpu;
++ while (p && p != (CPUArchState *)cpu_env) {
++ lastp = &p->next_cpu;
++ p = p->next_cpu;
++ }
++ /*
++ * if we didn't find the CPU for this thread then something
++ * is horribly wrong.
++ */
++ if (!p)
++ abort();
++ /* Remove the CPU from the list. */
++ *lastp = p->next_cpu;
++ cpu_list_unlock();
++ ts = ((CPUArchState *)cpu_env)->opaque;
++
++ if (tid_addr) {
++ /* Signal target userland that it can free the stack. */
++ if (! put_user_u32(1, tid_addr))
++ _umtx_op(g2h(tid_addr), UMTX_OP_WAKE, INT_MAX,
++ NULL, NULL);
++ }
++
++ thread_env = NULL;
++ object_delete(OBJECT(ENV_GET_CPU(cpu_env)));
++ g_free(ts);
++ pthread_exit(NULL);
++ }
++}
++
++static int
++do_thr_kill(long id, int sig)
++{
++
++ return (get_errno(thr_kill(id, sig)));
++}
++
++static int
++do_thr_kill2(pid_t pid, long id, int sig)
++{
++
++ return (get_errno(thr_kill2(pid, id, sig)));
++}
++
++static int
++do_thr_suspend(const struct timespec *timeout)
++{
++
++ return (get_errno(thr_suspend(timeout)));
++}
++
++static int
++do_thr_wake(long tid)
++{
++
++ return (get_errno(thr_wake(tid)));
++}
++
++static int
++do_thr_set_name(long tid, char *name)
++{
++
++ return (get_errno(thr_set_name(tid, name)));
++}
++
++
++#else /* ! CONFIG_USE_NPTL */
++
++static int
++do_thr_create(CPUArchState *env, ucontext_t *ctx, long *id, int flags)
++{
++ return (unimplemented(TARGET_FREEBSD_NR_thr_create));
++}
++
++static int
++do_thr_new(CPUArchState *env, abi_ulong target_param_addr, int32_t param_size)
++{
++ return (unimplemented(TARGET_FREEBSD_NR_thr_new));
++}
++
++static int
++do_thr_self(long *tid)
++{
++ return (unimplemented(TARGET_FREEBSD_NR_thr_self));
++}
++
++static void
++do_thr_exit(CPUArchState *cpu_env, abi_ulong state_addr)
++{
++}
++
++static int
++do_thr_kill(long tid, int sig)
++{
++ return (unimplemented(TARGET_FREEBSD_NR_thr_kill2));
++}
++
++static int
++do_thr_kill2(pid_t pid, long tid, int sig)
++{
++ return (unimplemented(TARGET_FREEBSD_NR_thr_kill2));
++}
++
++static int
++do_thr_suspend(const struct timespec *timeout)
++{
++ return (unimplemented(TARGET_FREEBSD_NR_thr_suspend));
++}
++
++static int
++do_thr_wake(long tid)
++{
++ return (unimplemented(TARGET_FREEBSD_NR_thr_wake));
++}
++
++static int
++do_thr_set_name(long tid, char *name)
++{
++ return (unimplemented(TARGET_FREEBSD_NR_thr_set_name));
++}
++
++#endif /* CONFIG_USE_NPTL */
++
++static int
++do_umtx_lock(abi_ulong umtx_addr, uint32_t id)
++{
++ int ret = 0;
++
++ for (;;) {
++ ret = get_errno(_umtx_op(g2h(umtx_addr +
++ offsetof(struct target_umtx, u_owner)),
++ UMTX_OP_MUTEX_WAIT, UMTX_UNOWNED, 0, 0));
++ if (ret)
++ return (ret);
++ if (atomic_cmpset_acq_32(g2h(umtx_addr +
++ offsetof(struct target_umtx, u_owner)),
++ UMTX_UNOWNED, id))
++ return (0);
++ }
++}
++
++static int
++do_umtx_unlock(abi_ulong umtx_addr, uint32 id)
++{
++ uint32_t owner;
++
++ do {
++ if (get_user_u32(owner, umtx_addr +
++ offsetof(struct target_umtx, u_owner)))
++ return (-TARGET_EFAULT);
++ if (owner != id)
++ return (-TARGET_EPERM);
++ } while (!atomic_cmpset_rel_32(g2h(umtx_addr +
++ offsetof(struct target_umtx, u_owner)), owner,
++ UMUTEX_UNOWNED));
++
++ return (0);
++}
++
++
+ /* 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>. */
+@@ -4091,6 +4491,23 @@ do_stat:
+ break;
+ #endif
+
++#ifdef TARGET_FREEBSD_NR_getdomainname
++ case TARGET_FREEBSD_NR_getdomainname:
++ ret = unimplemented(num);
++ break;
++#endif
++#ifdef TARGET_FREEBSD_NR_setdomainname
++ case TARGET_FREEBSD_NR_setdomainname:
++ ret = unimplemented(num);
++ break;
++#endif
++#ifdef TARGET_FREEBSD_NR_uname
++ case TARGET_FREEBSD_NR_uname:
++ ret = unimplemented(num);
++ break;
++#endif
++
++
+ #if 0 /* XXX not supported in libc yet, it seems (10.0 addition). */
+ case TARGET_FREEBSD_NR_posix_fadvise:
+ {
+@@ -4136,6 +4553,211 @@ do_stat:
+ break;
+ #endif
+
++ case TARGET_FREEBSD_NR_thr_new:
++ ret = do_thr_new(cpu_env, arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_thr_create:
++ {
++ ucontext_t ucxt;
++ long tid;
++
++ ret = do_thr_create(cpu_env, &ucxt, &tid, arg3);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_thr_set_name:
++ if (!(p = lock_user_string(arg2)))
++ goto efault;
++ ret = do_thr_set_name(arg1, p);
++ unlock_user(p, arg2, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_thr_self:
++ {
++ long tid;
++
++ if ((ret = do_thr_self(&tid)) == 0) {
++ if (put_user((abi_long)tid, arg1, abi_long))
++ goto efault;
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_thr_suspend:
++ {
++ struct timespec ts;
++
++ if (target_to_host_timespec(&ts, arg1))
++ goto efault;
++
++ ret = do_thr_suspend(&ts);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_thr_wake:
++ ret = do_thr_wake(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_thr_kill:
++ ret = do_thr_kill(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_thr_kill2:
++ ret = do_thr_kill2(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_thr_exit:
++ ret = 0; /* suspress compile warning */
++ do_thr_exit(cpu_env, arg1);
++ /* Shouldn't be reached. */
++ break;
++
++ case TARGET_FREEBSD_NR_rtprio_thread:
++ ret = 0;
++ break;
++
++ case TARGET_FREEBSD_NR_getcontext:
++ {
++ target_ucontext_t *ucp;
++ sigset_t sigmask;
++
++ if (0 == arg1) {
++ ret = -TARGET_EINVAL;
++ } else {
++ ret = get_errno(sigprocmask(0, NULL, &sigmask));
++ if (!is_error(ret)) {
++ if (!(ucp = lock_user(VERIFY_WRITE, arg1,
++ sizeof(target_ucontext_t), 0)))
++ goto efault;
++ ret = get_mcontext(cpu_env, &ucp->uc_mcontext,
++ TARGET_MC_GET_CLEAR_RET);
++ host_to_target_sigset(&ucp->uc_sigmask,
++ &sigmask);
++ memset(ucp->__spare__, 0,
++ sizeof(ucp->__spare__));
++ unlock_user(ucp, arg1,
++ sizeof(target_ucontext_t));
++ }
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_setcontext:
++ {
++ target_ucontext_t *ucp;
++ sigset_t sigmask;
++
++ if (0 == arg1) {
++ ret = -TARGET_EINVAL;
++ } else {
++ if (!(ucp = lock_user(VERIFY_READ, arg1,
++ sizeof(target_ucontext_t), 1)))
++ goto efault;
++ ret = set_mcontext(cpu_env, &ucp->uc_mcontext, 0);
++ target_to_host_sigset(&sigmask, &ucp->uc_sigmask);
++ unlock_user(ucp, arg1, sizeof(target_ucontext_t));
++ if (0 == ret)
++ (void)sigprocmask(SIG_SETMASK, &sigmask, NULL);
++ }
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_swapcontext:
++ /*
++ * XXX Does anything besides old implementations of
++ * setjmp()/longjmp() uses these?
++ */
++ ret = unimplemented(num);
++ break;
++
++ case TARGET_FREEBSD_NR__umtx_lock:
++ {
++ long tid;
++
++ thr_self(&tid);
++ ret = do_umtx_lock(arg1, tswap32(tid));
++ }
++ break;
++
++ case TARGET_FREEBSD_NR__umtx_unlock:
++ {
++ long tid;
++
++ thr_self(&tid);
++ ret = do_umtx_unlock(arg1, tswap32(tid));
++ }
++ break;
++
++ case TARGET_FREEBSD_NR__umtx_op:
++ {
++ struct timespec ts;
++ void *object = NULL;
++ int operation;
++ void *addr = NULL;
++ void *addr2 = NULL;
++
++
++ /* int _umtx_op(void *obj, int op, u_long val,
++ * void *uaddr, void *uaddr2); */
++
++ abi_ulong obj = arg1;
++ int op = (int)arg2;
++ u_long val = arg3;
++ /* abi_ulong uaddr = arg4; */
++ abi_ulong uaddr2 = arg5;
++
++ switch(op) {
++ case TARGET_UMTX_OP_LOCK:
++ ret = do_umtx_lock(obj, tswap32((uint32_t)val));
++ break;
++
++ case TARGET_UMTX_OP_UNLOCK:
++ ret = do_umtx_unlock(obj, tswap32((uint32_t)val));
++ break;
++
++ case TARGET_UMTX_OP_WAIT:
++ if (uaddr2) {
++ if (target_to_host_timespec(&ts, uaddr2))
++ goto efault;
++ addr2 = (void *)&ts;
++ }
++ ret = get_errno(_umtx_op(g2h(obj), UMTX_OP_WAIT,
++ tswap32(val), addr, addr2));
++ break;
++
++ case TARGET_UMTX_OP_WAKE:
++ operation = UMTX_OP_WAKE;
++ object = g2h(obj);
++ ret = get_errno(_umtx_op(g2h(obj), UMTX_OP_WAKE,
++ val, 0, 0));
++ break;
++
++ case TARGET_UMTX_OP_MUTEX_TRYLOCK:
++ case TARGET_UMTX_OP_MUTEX_LOCK:
++ case TARGET_UMTX_OP_MUTEX_UNLOCK:
++ case TARGET_UMTX_OP_SET_CEILING:
++ case TARGET_UMTX_OP_CV_WAIT:
++ case TARGET_UMTX_OP_CV_SIGNAL:
++ case TARGET_UMTX_OP_CV_BROADCAST:
++ case TARGET_UMTX_OP_WAIT_UINT:
++ case TARGET_UMTX_OP_RW_RDLOCK:
++ case TARGET_UMTX_OP_RW_WRLOCK:
++ case TARGET_UMTX_OP_RW_UNLOCK:
++ case TARGET_UMTX_OP_WAIT_UINT_PRIVATE:
++ case TARGET_UMTX_OP_WAKE_PRIVATE:
++ case TARGET_UMTX_OP_MUTEX_WAIT:
++ case TARGET_UMTX_OP_MUTEX_WAKE:
++ case TARGET_UMTX_OP_SEM_WAIT:
++ case TARGET_UMTX_OP_SEM_WAKE:
++ case TARGET_UMTX_OP_NWAKE_PRIVATE:
++ default:
++ ret = -TARGET_EINVAL;
++ break;
++ }
++ }
++ break;
++
+ case TARGET_FREEBSD_NR_yield:
+ case TARGET_FREEBSD_NR_sched_setparam:
+ case TARGET_FREEBSD_NR_sched_getparam:
+@@ -4146,36 +4768,18 @@ do_stat:
+ case TARGET_FREEBSD_NR_sched_get_priority_min:
+ case TARGET_FREEBSD_NR_sched_rr_get_interval:
+
+-
+ case TARGET_FREEBSD_NR_reboot:
+ case TARGET_FREEBSD_NR_shutdown:
+
+ case TARGET_FREEBSD_NR_swapon:
+ case TARGET_FREEBSD_NR_swapoff:
+
+- case TARGET_FREEBSD_NR_thr_create:
+- case TARGET_FREEBSD_NR_thr_exit:
+- case TARGET_FREEBSD_NR_thr_self:
+- case TARGET_FREEBSD_NR_thr_suspend:
+- case TARGET_FREEBSD_NR_thr_wake:
+- case TARGET_FREEBSD_NR_thr_new:
+- case TARGET_FREEBSD_NR_thr_set_name:
+- case TARGET_FREEBSD_NR_thr_kill2:
+-
+- case TARGET_FREEBSD_NR_getcontext:
+- case TARGET_FREEBSD_NR_setcontext:
+- case TARGET_FREEBSD_NR_swapcontext:
+-
+- case TARGET_FREEBSD_NR_rtprio_thread:
+ case TARGET_FREEBSD_NR_cpuset:
+ case TARGET_FREEBSD_NR_cpuset_getid:
+ case TARGET_FREEBSD_NR_cpuset_setid:
+ case TARGET_FREEBSD_NR_cpuset_getaffinity:
+ case TARGET_FREEBSD_NR_cpuset_setaffinity:
+
+- case TARGET_FREEBSD_NR__umtx_lock:
+- case TARGET_FREEBSD_NR__umtx_unlock:
+-
+ case TARGET_FREEBSD_NR_rctl_get_racct:
+ case TARGET_FREEBSD_NR_rctl_get_rules:
+ case TARGET_FREEBSD_NR_rctl_add_rule:
+@@ -4185,16 +4789,6 @@ do_stat:
+ case TARGET_FREEBSD_NR_ntp_adjtime:
+ case TARGET_FREEBSD_NR_ntp_gettime:
+
+-#ifdef TARGET_FREEBSD_NR_getdomainname
+- case TARGET_FREEBSD_NR_getdomainname:
+-#endif
+-#ifdef TARGET_FREEBSD_NR_setdomainname
+- case TARGET_FREEBSD_NR_setdomainname:
+-#endif
+-#ifdef TARGET_FREEBSD_NR_uname
+- case TARGET_FREEBSD_NR_uname:
+-#endif
+-
+ case TARGET_FREEBSD_NR_sctp_peeloff:
+ case TARGET_FREEBSD_NR_sctp_generic_sendmsg:
+ case TARGET_FREEBSD_NR_sctp_generic_recvmsg:
+diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h
+index ea1d25d..2879d83 100644
+--- a/bsd-user/syscall_defs.h
++++ b/bsd-user/syscall_defs.h
+@@ -416,6 +416,11 @@ struct target_shmid_ds {
+ abi_ulong shm_ctime; /* time of last change by shmctl() */
+ };
+
++#define TARGET_UCONTEXT_MAGIC 0xACEDBADE
++#define TARGET_MC_GET_CLEAR_RET 0x0001
++#define TARGET_MC_ADD_MAGIC 0x0002
++#define TARGET_MC_SET_ONSTACK 0x0004
++
+ /* this struct defines a stack used during syscall handling */
+ typedef struct target_sigaltstack {
+ abi_long ss_sp;
+@@ -477,95 +482,6 @@ typedef struct target_siginfo {
+ } _reason;
+ } target_siginfo_t;
+
+-#if defined(TARGET_MIPS)
+-
+-struct target_sigcontext {
+- target_sigset_t sc_mask; /* signal mask to retstore */
+- int32_t sc_onstack; /* sigstack state to restore */
+- abi_long sc_pc; /* pc at time of signal */
+- abi_long sc_reg[32]; /* processor regs 0 to 31 */
+- abi_long mullo, mulhi; /* mullo and mulhi registers */
+- int32_t sc_fpused; /* fp has been used */
+- abi_long sc_fpregs[33]; /* fp regs 0 to 31 & csr */
+- abi_long sc_fpc_eir; /* fp exception instr reg */
+- /* int32_t reserved[8]; */
+-};
+-
+-typedef struct target_mcontext {
+- int32_t mc_onstack; /* sigstack state to restore */
+- abi_long mc_pc; /* pc at time of signal */
+- abi_long mc_regs[32]; /* process regs 0 to 31 */
+- abi_long sr; /* status register */
+- abi_long mullo, mulhi;
+- int32_t mc_fpused; /* fp has been used */
+- abi_long mc_fpregs[33]; /* fp regs 0 to 32 & csr */
+- abi_long mc_fpc_eir; /* fp exception instr reg */
+- abi_ulong mc_tls; /* pointer to TLS area */
+-} target_mcontext_t;
+-
+-typedef struct target_ucontext {
+- target_sigset_t uc_sigmask;
+- target_mcontext_t uc_mcontext;
+- target_ulong uc_link;
+- target_stack_t uc_stack;
+- int32_t uc_flags;
+- int32_t __space__[8];
+-} target_ucontext_t;
+-
+-struct target_sigframe {
+- abi_ulong sf_signum;
+- abi_ulong sf_siginfo; /* code or pointer to sf_si */
+- abi_ulong sf_ucontext; /* points to sf_uc */
+- abi_ulong sf_addr; /* undocumented 4th arg */
+- target_ucontext_t sf_uc; /* = *sf_uncontext */
+- target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/
+- uint32_t __spare__[2];
+-};
+-
+-#elif defined(TARGET_SPARC64)
+-
+-struct target_mcontext {
+- uint64_t mc_global[8];
+- uint64_t mc_out[8];
+- uint64_t mc_local[8];
+- uint64_t mc_in[8];
+- uint32_t mc_fp[64];
+-} __aligned(64);
+-
+-typedef struct target_mcontext target_mcontext_t;
+-
+-typedef struct target_ucontext {
+- target_sigset_t uc_sigmask;
+- target_mcontext_t uc_mcontext;
+- target_ulong uc_link;
+- target_stack_t uc_stack;
+- int32_t uc_flags;
+- int32_t __space__[8];
+-} target_ucontext_t;
+-
+-struct target_sigframe {
+- target_ucontext_t sf_uc;
+- target_siginfo_t sf_si;
+-};
+-
+-#else
+-
+-typedef target_ulong target_mcontext_t; /* dummy */
+-
+-#endif
+-
+-/* XXX where did this come from?
+-typedef struct target_ucontext {
+- target_ulong uc_flags;
+- target_ulong uc_link;
+- target_stack_t uc_stack;
+- target_mcontext_t uc_mcontext;
+- target_ulong uc_filer[80];
+- target_sigset_t uc_sigmask;
+-} target_ucontext_t;
+-*/
+-
+-
+ #ifdef BSWAP_NEEDED
+ static inline void
+ tswap_sigset(target_sigset_t *d, const target_sigset_t *s)
+@@ -603,3 +519,101 @@ void host_to_target_old_sigset(abi_ulong *old_sigset, const sigset_t *sigset);
+ void target_to_host_old_sigset(sigset_t *sigset, const abi_ulong *old_sigset);
+ int do_sigaction(int sig, const struct target_sigaction *act,
+ struct target_sigaction *oact);
++
++
++/*
++ * FreeBSD thread support.
++ */
++
++#define TARGET_THR_SUSPENDED 0x0001
++#define TARGET_THR_SYSTEM_SCOPE 0x0002
++
++/* sysarch() ops */
++#define TARGET_MIPS_SET_TLS 1
++#define TARGET_MIPS_GET_TLS 2
++
++struct target_thr_param {
++ abi_ulong start_func; /* thread entry function. */
++ abi_ulong arg; /* argument for entry function. */
++ abi_ulong stack_base; /* stack base address. */
++ abi_ulong stack_size; /* stack size. */
++ abi_ulong tls_base; /* tls base address. */
++ abi_ulong tls_size; /* tls size. */
++ abi_ulong child_tid; /* address to store new TID. */
++ abi_ulong parent_tid; /* parent access the new TID here. */
++ abi_ulong rtp; /* Real-time scheduling priority. */
++ abi_ulong spare[3]; /* spares. */
++};
++
++struct target_rtprio {
++ uint16_t type;
++ uint16_t prio;
++};
++
++/*
++ * sys/_umtx.h
++ */
++
++struct target_umtx {
++ uint32_t u_owner; /* Owner of the mutex. */
++};
++
++struct target_umutex {
++ uint32_t m_owner; /* Owner of the mutex */
++ uint32_t m_flags; /* Flags of the mutex */
++ uint32_t m_ceiling[2]; /* Priority protect ceiling */
++ uint32_t m_spare[4];
++};
++
++struct target_ucond {
++ uint32_t c_has_waiters; /* Has waiters in kernel */
++ uint32_t c_flags; /* Flags of the condition variable */
++ uint32_t c_clockid; /* Clock id */
++ uint32_t c_spare[1];
++};
++
++struct target_urwlock {
++ int32_t rw_state;
++ uint32_t rw_flags;
++ uint32_t rw_blocked_readers;
++ uint32_t rw_blocked_writers;
++ uint32_t rw_spare[4];
++};
++
++struct target__usem {
++ uint32_t _has_waiters;
++ uint32_t _count;
++ uint32_t _flags;
++};
++
++/*
++ * sys/utmx.h
++ */
++
++/* op code for _umtx_op */
++#define TARGET_UMTX_OP_LOCK 0
++#define TARGET_UMTX_OP_UNLOCK 1
++#define TARGET_UMTX_OP_WAIT 2
++#define TARGET_UMTX_OP_WAKE 3
++#define TARGET_UMTX_OP_MUTEX_TRYLOCK 4
++#define TARGET_UMTX_OP_MUTEX_LOCK 5
++#define TARGET_UMTX_OP_MUTEX_UNLOCK 6
++#define TARGET_UMTX_OP_SET_CEILING 7
++#define TARGET_UMTX_OP_CV_WAIT 8
++#define TARGET_UMTX_OP_CV_SIGNAL 9
++#define TARGET_UMTX_OP_CV_BROADCAST 10
++#define TARGET_UMTX_OP_WAIT_UINT 11
++#define TARGET_UMTX_OP_RW_RDLOCK 12
++#define TARGET_UMTX_OP_RW_WRLOCK 13
++#define TARGET_UMTX_OP_RW_UNLOCK 14
++#define TARGET_UMTX_OP_WAIT_UINT_PRIVATE 15
++#define TARGET_UMTX_OP_WAKE_PRIVATE 16
++#define TARGET_UMTX_OP_MUTEX_WAIT 17
++#define TARGET_UMTX_OP_MUTEX_WAKE 18
++#define TARGET_UMTX_OP_SEM_WAIT 19
++#define TARGET_UMTX_OP_SEM_WAKE 20
++#define TARGET_UMTX_OP_NWAKE_PRIVATE 21
++#define TARGET_UMTX_OP_MAX 22
++
++/* flags for UMTX_OP_CV_WAIT */
++#define TARGET_CHECK_UNPARKING 0x01
+diff --git a/bsd-user/x86_64/target_signal.h b/bsd-user/x86_64/target_signal.h
+index ea89f5a..a14e0b9 100644
+--- a/bsd-user/x86_64/target_signal.h
++++ b/bsd-user/x86_64/target_signal.h
+@@ -15,4 +15,29 @@ static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
+ #define TARGET_MINSIGSTKSZ (512 * 4)
+ #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
+
++typedef target_ulong target_mcontext_t; /* dummy */
++
++typedef struct target_ucontext {
++ target_sigset_t uc_sigmask;
++ target_mcontext_t uc_mcontext;
++ abi_ulong uc_link;
++ target_stack_t uc_stack;
++ int32_t uc_flags;
++ int32_t __spare__[4];
++} target_ucontext_t;
++
++static inline int
++get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
++{
++ fprintf(stderr, "x86_64 doesn't have support for get_mcontext()\n");
++ return (-TARGET_ENOSYS);
++}
++
++static inline int
++set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
++{
++ fprintf(stderr, "x86_64 doesn't have support for set_mcontext()\n");
++ return (-TARGET_ENOSYS);
++}
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/configure b/configure
+index 34eca43..be75584 100755
+--- a/configure
++++ b/configure
+@@ -1386,6 +1386,11 @@ fi
+
+ if test "$nptl" != "no" ; then
+ cat > $TMPC <<EOF
++#ifdef __FreeBSD__
++int main(void) {
++ return (0);
++}
++#else
+ #include <sched.h>
+ #include <linux/futex.h>
+ int main(void) {
+@@ -1394,6 +1399,7 @@ int main(void) {
+ #endif
+ return 0;
+ }
++#endif
+ EOF
+
+ if compile_object ; then
+@@ -3751,5 +3757,6 @@ case "$target_arch2" in
+ TARGET_ARCH=mips64
+ TARGET_BASE_ARCH=mips
+ echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak
++ target_nptl="yes"
+ target_long_alignment=8
+ ;;
diff --git a/emulators/qemu-devel/files/patch-z2d-bsd-user-sson-002d b/emulators/qemu-devel/files/patch-z2d-bsd-user-sson-002d
new file mode 100644
index 000000000000..107d03b485a3
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z2d-bsd-user-sson-002d
@@ -0,0 +1,30 @@
+diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
+index 4deb0db..bde9ee9 100644
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -2377,7 +2377,7 @@ do_thr_exit(CPUArchState *cpu_env, abi_ulong tid_addr)
+
+ if (tid_addr) {
+ /* Signal target userland that it can free the stack. */
+- if (! put_user_u32(1, tid_addr))
++ if (! put_user_sal(1, tid_addr))
+ _umtx_op(g2h(tid_addr), UMTX_OP_WAKE, INT_MAX,
+ NULL, NULL);
+ }
+@@ -4588,10 +4588,13 @@ do_stat:
+ {
+ struct timespec ts;
+
+- if (target_to_host_timespec(&ts, arg1))
+- goto efault;
++ if (arg1) {
++ if (target_to_host_timespec(&ts, arg1))
++ goto efault;
++ ret = do_thr_suspend(&ts);
++ } else
++ ret = do_thr_suspend(NULL);
+
+- ret = do_thr_suspend(&ts);
+ }
+ break;
+
diff --git a/emulators/qemu-devel/files/patch-z2e-bsd-user-sson-002e b/emulators/qemu-devel/files/patch-z2e-bsd-user-sson-002e
new file mode 100644
index 000000000000..969b6b825640
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z2e-bsd-user-sson-002e
@@ -0,0 +1,3316 @@
+diff --git a/Makefile.target b/Makefile.target
+--- a/Makefile.target
++++ b/Makefile.target
+@@ -95,7 +95,7 @@ ifdef CONFIG_BSD_USER
+ QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ARCH)
+
+ obj-y += bsd-user/
+-obj-y += gdbstub.o user-exec.o
++obj-y += gdbstub.o thunk.o user-exec.o
+
+ endif #CONFIG_BSD_USER
+
+diff --git a/bsd-user/freebsd/ioccom.h b/bsd-user/freebsd/ioccom.h
+new file mode 100644
+index 0000000..830e377
+--- /dev/null
++++ b/bsd-user/freebsd/ioccom.h
+@@ -0,0 +1,34 @@
++#ifndef _FREEBSD_IOCCOM_H_
++#define _FREEBSD_IOCCOM_H_
++/*
++ * Ioctl's have the command encoded in the lower word, and the size of
++ * any in or out parameters in the upper word. The high 3 bits of the
++ * upper word are used to encode the in/out status of the parameter.
++ */
++/* number of bits for ioctl size */
++#define TARGET_IOCPARM_SHIFT 13
++
++/* parameter length mask */
++#define TARGET_IOCPARM_MASK ((1 << TARGET_IOCPARM_SHIFT) - 1)
++
++#define TARGET_IOCPARM_LEN(x) (((x) >> 16) & TARGET_IOCPARM_MASK)
++#define TARGET_IOCBASECMD(x) ((x) & ~(TARGET_IOCPARM_MASK << 16))
++#define TARGET_IOCGROUP(x) (((x) >> 8) & 0xff)
++
++#define TARGET_IOCPARM_MAX (1 << TARGET_IOCPARM_SHIFT) /* max size of ioctl */
++#define TARGET_IOC_VOID 0x20000000 /* no parameters */
++#define TARGET_IOC_OUT 0x40000000 /* copy out parameters */
++#define TARGET_IOC_IN 0x80000000 /* copy in parameters */
++#define TARGET_IOC_INOUT (TARGET_IOC_IN|TARGET_IOC_OUT)
++#define TARGET_IOC_DIRMASK (TARGET_IOC_VOID|TARGET_IOC_OUT|TARGET_IOC_IN)
++
++#define TARGET_IOC(inout,group,num,len) ((abi_ulong) \
++ ((inout) | (((len) & TARGET_IOCPARM_MASK) << 16) | ((group) << 8) \
++ | (num)))
++#define TARGET_IO(g,n) TARGET_IOC(IOC_VOID, (g), (n), 0)
++#define TARGET_IOWINT(g,n) TARGET_IOC(IOC_VOID, (g), (n), sizeof(int))
++#define TARGET_IOR(g,n,t) TARGET_IOC(IOC_OUT, (g), (n), sizeof(t))
++#define TARGET_IOW(g,n,t) TARGET_IOC(IOC_IN, (g), (n), sizeof(t))
++/* this should be _IORW, but stdio got there first */
++#define TARGET_IOWR(g,n,t) TARGET_IOC(IOC_INOUT, (g), (n), sizeof(t))
++#endif
+diff --git a/bsd-user/freebsd/ioctl.h b/bsd-user/freebsd/ioctl.h
+new file mode 100644
+index 0000000..67c5583
+--- /dev/null
++++ b/bsd-user/freebsd/ioctl.h
+@@ -0,0 +1,35 @@
++#ifndef _FREEBSD_IOCTL_H_
++#define _FREEBSD_IOCTL_H_
++
++/* sys/ttycom.h tty(4) */
++IOCTL(TIOCSETD, IOC_W, MK_PTR(TYPE_INT))
++IOCTL(TIOCGETD, IOC_R, MK_PTR(TYPE_INT))
++IOCTL(TIOCSBRK, IOC_, TYPE_NULL)
++IOCTL(TIOCCBRK, IOC_, TYPE_NULL)
++IOCTL(TIOCSDTR, IOC_, TYPE_NULL)
++IOCTL(TIOCCDTR, IOC_, TYPE_NULL)
++IOCTL(TIOCGPGRP, IOC_W, MK_PTR(TYPE_INT))
++IOCTL(TIOCSPGRP, IOC_R, MK_PTR(TYPE_INT))
++IOCTL(TIOCGETA, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
++IOCTL(TIOCSETA, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
++IOCTL(TIOCSETAW, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
++IOCTL(TIOCSETAF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
++IOCTL(TIOCOUTQ, IOC_R, MK_PTR(TYPE_INT))
++IOCTL(TIOCSTI, IOC_W, MK_PTR(TYPE_CHAR))
++IOCTL(TIOCNOTTY, IOC_, TYPE_NULL)
++IOCTL(TIOCSTOP, IOC_, TYPE_NULL)
++IOCTL(TIOCSTART, IOC_, TYPE_NULL)
++IOCTL(TIOCSCTTY, IOC_, TYPE_NULL)
++IOCTL(TIOCDRAIN, IOC_, TYPE_NULL)
++IOCTL(TIOCEXCL, IOC_, TYPE_NULL)
++IOCTL(TIOCNXCL, IOC_, TYPE_NULL)
++IOCTL(TIOCFLUSH, IOC_W, MK_PTR(TYPE_INT))
++IOCTL(TIOCGWINSZ, IOC_R, MK_PTR(MK_STRUCT(STRUCT_winsize)))
++IOCTL(TIOCSWINSZ, IOC_W, MK_PTR(MK_STRUCT(STRUCT_winsize)))
++IOCTL(TIOCCONS, IOC_W, MK_PTR(TYPE_INT))
++IOCTL(TIOCMSET, IOC_W, MK_PTR(TYPE_INT))
++IOCTL(TIOCMGET, IOC_R, MK_PTR(TYPE_INT))
++IOCTL(TIOCMBIS, IOC_W, MK_PTR(TYPE_INT))
++IOCTL(TIOCMBIC, IOC_W, MK_PTR(TYPE_INT))
++
++#endif
+diff --git a/bsd-user/freebsd/strace.list b/bsd-user/freebsd/strace.list
+index b09f766..bcdd931 100644
+--- a/bsd-user/freebsd/strace.list
++++ b/bsd-user/freebsd/strace.list
+@@ -2,6 +2,7 @@
+ { TARGET_FREEBSD_NR___semctl, "__semctl", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR___syscall, "__syscall", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR___sysctl, "__sysctl", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR__umtx_op, "_umtx_op", "%s(%#x, %d, %d, %#x, %#x)", NULL, NULL },
+ { TARGET_FREEBSD_NR_accept, "accept", "%s(%d,%#x,%#x)", NULL, NULL },
+ { TARGET_FREEBSD_NR_access, "access", "%s(\"%s\",%#o)", NULL, NULL },
+ { TARGET_FREEBSD_NR_acct, "acct", NULL, NULL, NULL },
+diff --git a/bsd-user/freebsd/syscall_types.h b/bsd-user/freebsd/syscall_types.h
+new file mode 100644
+index 0000000..6e43400
+--- /dev/null
++++ b/bsd-user/freebsd/syscall_types.h
+@@ -0,0 +1,8 @@
++#ifndef _FREEBSD_SYSCALL_TYPES_H_
++#define _FREEBSD_SYSCALL_TYPES_H_
++
++STRUCT_SPECIAL(termios)
++
++STRUCT(winsize, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT)
++
++#endif
+diff --git a/bsd-user/freebsd/ttycom.h b/bsd-user/freebsd/ttycom.h
+new file mode 100644
+index 0000000..699c282
+--- /dev/null
++++ b/bsd-user/freebsd/ttycom.h
+@@ -0,0 +1,238 @@
++#ifndef _FREEBSD_TTYCOM_H_
++#define _FREEBSD_TTYCOM_H_
++
++#include "ioccom.h"
++
++/* From sys/ttycom.h and sys/_termios.h */
++
++#define TARGET_VEOF 0 /* ICANON */
++#define TARGET_VEOL 1 /* ICANON */
++#define TARGET_VEOL2 2 /* ICANON together with IEXTEN */
++#define TARGET_VERASE 3 /* ICANON */
++#define TARGET_VWERASE 4 /* ICANON together with IEXTEN */
++#define TARGET_VKILL 5 /* ICANON */
++#define TARGET_VREPRINT 6 /* ICANON together with IEXTEN */
++#define TARGET_VERASE2 7 /* ICANON */
++#define TARGET_VINTR 8 /* ISIG */
++#define TARGET_VQUIT 9 /* ISIG */
++#define TARGET_VSUSP 10 /* ISIG */
++#define TARGET_VDSUSP 11 /* ISIG together with IEXTEN */
++#define TARGET_VSTART 12 /* IXON, IXOFF */
++#define TARGET_VSTOP 13 /* IXON, IXOFF */
++#define TARGET_VLNEXT 14 /* IEXTEN */
++#define TARGET_VDISCARD 15 /* IEXTEN */
++#define TARGET_VMIN 16 /* !ICANON */
++#define TARGET_VTIME 17 /* !ICANON */
++#define TARGET_VSTATUS 18 /* ICANON together with IEXTEN */
++/* 19 spare 2 */
++#define TARGET_NCCS 20
++
++/*
++ * Input flags - software input processing
++ */
++#define TARGET_IGNBRK 0x00000001 /* ignore BREAK condition */
++#define TARGET_BRKINT 0x00000002 /* map BREAK to SIGINTR */
++#define TARGET_IGNPAR 0x00000004 /* ignore (discard) parity errors */
++#define TARGET_PARMRK 0x00000008 /* mark parity and framing errors */
++#define TARGET_INPCK 0x00000010 /* enable checking of parity errors */
++#define TARGET_ISTRIP 0x00000020 /* strip 8th bit off chars */
++#define TARGET_INLCR 0x00000040 /* map NL into CR */
++#define TARGET_IGNCR 0x00000080 /* ignore CR */
++#define TARGET_ICRNL 0x00000100 /* map CR to NL (ala CRMOD) */
++#define TARGET_IXON 0x00000200 /* enable output flow control */
++#define TARGET_IXOFF 0x00000400 /* enable input flow control */
++#define TARGET_IXANY 0x00000800 /* any char will restart after stop */
++#define TARGET_IMAXBEL 0x00002000 /* ring bell on input queue full */
++
++/*
++ * Output flags - software output processing
++ */
++#define TARGET_OPOST 0x00000001 /* enable following output processing */
++#define TARGET_ONLCR 0x00000002 /* map NL to CR-NL (ala CRMOD) */
++#define TARGET_TABDLY 0x00000004 /* tab delay mask */
++#define TARGET_TAB0 0x00000000 /* no tab delay and expansion */
++#define TARGET_TAB3 0x00000004 /* expand tabs to spaces */
++#define TARGET_ONOEOT 0x00000008 /* discard EOT's (^D) on output) */
++#define TARGET_OCRNL 0x00000010 /* map CR to NL on output */
++#define TARGET_ONOCR 0x00000020 /* no CR output at column 0 */
++#define TARGET_ONLRET 0x00000040 /* NL performs CR function */
++
++/*
++ * Control flags - hardware control of terminal
++ */
++#define TARGET_CIGNORE 0x00000001 /* ignore control flags */
++#define TARGET_CSIZE 0x00000300 /* character size mask */
++#define TARGET_CS5 0x00000000 /* 5 bits (pseudo) */
++#define TARGET_CS6 0x00000100 /* 6 bits */
++#define TARGET_CS7 0x00000200 /* 7 bits */
++#define TARGET_CS8 0x00000300 /* 8 bits */
++#define TARGET_CSTOPB 0x00000400 /* send 2 stop bits */
++#define TARGET_CREAD 0x00000800 /* enable receiver */
++#define TARGET_PARENB 0x00001000 /* parity enable */
++#define TARGET_PARODD 0x00002000 /* odd parity, else even */
++#define TARGET_HUPCL 0x00004000 /* hang up on last close */
++#define TARGET_CLOCAL 0x00008000 /* ignore modem status lines */
++#define TARGET_CCTS_OFLOW 0x00010000 /* CTS flow control of output */
++#define TARGET_CRTSCTS (TARGET_CCTS_OFLOW | TARGET_CRTS_IFLOW)
++#define TARGET_CRTS_IFLOW 0x00020000 /* RTS flow control of input */
++#define TARGET_CDTR_IFLOW 0x00040000 /* DTR flow control of input */
++#define TARGET_CDSR_OFLOW 0x00080000 /* DSR flow control of output */
++#define TARGET_CCAR_OFLOW 0x00100000 /* DCD flow control of output */
++
++/*
++ * "Local" flags - dumping ground for other state
++ */
++#define TARGET_ECHOKE 0x00000001 /* visual erase for line kill */
++#define TARGET_ECHOE 0x00000002 /* visually erase chars */
++#define TARGET_ECHOK 0x00000004 /* echo NL after line kill */
++#define TARGET_ECHO 0x00000008 /* enable echoing */
++#define TARGET_ECHONL 0x00000010 /* echo NL even if ECHO is off */
++#define TARGET_ECHOPRT 0x00000020 /* visual erase mode for hardcopy */
++#define TARGET_ECHOCTL 0x00000040 /* echo control chars as ^(Char) */
++#define TARGET_ISIG 0x00000080 /* enable signals INTR, QUIT, [D]SUSP */
++#define TARGET_ICANON 0x00000100 /* canonicalize input lines */
++#define TARGET_ALTWERASE 0x00000200 /* use alternate WERASE algorithm */
++#define TARGET_IEXTEN 0x00000400 /* enable DISCARD and LNEXT */
++#define TARGET_EXTPROC 0x00000800 /* external processing */
++#define TARGET_TOSTOP 0x00400000 /* stop background jobs from output */
++#define TARGET_FLUSHO 0x00800000 /* output being flushed (state) */
++#define TARGET_NOKERNINFO 0x02000000 /* no kernel output from VSTATUS */
++#define TARGET_PENDIN 0x20000000 /* XXX retype pending input (state) */
++#define TARGET_NOFLSH 0x80000000 /* don't flush after interrupt */
++
++struct target_termios {
++ uint32_t c_iflag; /* input flags */
++ uint32_t c_oflag; /* output flags */
++ uint32_t c_cflag; /* control flags */
++ uint32_t c_lflag; /* local flags */
++ uint8_t c_cc[TARGET_NCCS]; /* control chars */
++ uint32_t c_ispeed; /* input speed */
++ uint32_t c_ospeed; /* output speed */
++};
++
++
++struct target_winsize {
++ uint16_t ws_row; /* rows, in characters */
++ uint16_t ws_col; /* columns, in characters */
++ uint16_t ws_xpixel; /* horizontal size, pixels */
++ uint16_t ws_ypixel; /* vertical size, pixels */
++};
++
++ /* 0-2 compat */
++ /* 3-7 unused */
++ /* 8-10 compat */
++ /* 11-12 unused */
++#define TARGET_TIOCEXCL TARGET_IO('t', 13) /* set exclusive use of tty */
++#define TARGET_TIOCNXCL TARGET_IO('t', 14) /* reset exclusive use of tty */
++#define TARGET_TIOCGPTN TARGET_IOR('t', 15, int) /* Get pts number. */
++#define TARGET_TIOCFLUSH TARGET_IOW('t', 16, int) /* flush buffers */
++ /* 17-18 compat */
++/* get termios struct */
++#define TARGET_TIOCGETA TARGET_IOR('t', 19, struct target_termios)
++/* set termios struct */
++#define TARGET_TIOCSETA TARGET_IOW('t', 20, struct target_termios)
++/* drain output, set */
++#define TARGET_TIOCSETAW TARGET_IOW('t', 21, struct target_termios)
++/* drn out, fls in, set */
++#define TARGET_TIOCSETAF TARGET_IOW('t', 22, struct target_termios)
++ /* 23-25 unused */
++#define TARGET_TIOCGETD TARGET_IOR('t', 26, int) /* get line discipline */
++#define TARGET_TIOCSETD TARGET_IOW('t', 27, int) /* set line discipline */
++#define TARGET_TIOCPTMASTER TARGET_IO('t', 28) /* pts master validation */
++ /* 29-85 unused */
++/* get ttywait timeout */
++#define TARGET_TIOCGDRAINWAIT TARGET_IOR('t', 86, int)
++/* set ttywait timeout */
++#define TARGET_TIOCSDRAINWAIT TARGET_IOW('t', 87, int)
++ /* 88 unused */
++ /* 89-91 conflicts: tun and tap */
++/* enable/get timestamp of last input event */
++#define TARGET_TIOCTIMESTAMP TARGET_IOR('t', 89, struct target_timeval)
++/* modem: get wait on close */
++#define TARGET_TIOCMGDTRWAIT TARGET_IOR('t', 90, int)
++/* modem: set wait on close */
++#define TARGET_TIOCMSDTRWAIT TARGET_IOW('t', 91, int)
++ /* 92-93 tun and tap */
++ /* 94-97 conflicts: tun and tap */
++/* wait till output drained */
++#define TARGET_TIOCDRAIN TARGET_IO('t', 94)
++ /* pty: generate signal */
++#define TARGET_TIOCSIG TARGET_IOWINT('t', 95)
++/* pty: external processing */
++#define TARGET_TIOCEXT TARGET_IOW('t', 96, int)
++/* become controlling tty */
++#define TARGET_TIOCSCTTY TARGET_IO('t', 97)
++/* become virtual console */
++#define TARGET_TIOCCONS TARGET_IOW('t', 98, int)
++/* get session id */
++#define TARGET_TIOCGSID TARGET_IOR('t', 99, int)
++ /* 100 unused */
++/* simulate ^T status message */
++#define TARGET_TIOCSTAT TARGET_IO('t', 101)
++ /* pty: set/clr usr cntl mode */
++#define TARGET_TIOCUCNTL TARGET_IOW('t', 102, int)
++/* usr cntl op "n" */
++#define TARGET_TIOCCMD(n) TARGET_IO('u', n)
++/* set window size */
++#define TARGET_TIOCSWINSZ TARGET_IOW('t', 103, struct target_winsize)
++/* get window size */
++#define TARGET_TIOCGWINSZ TARGET_IOR('t', 104, struct target_winsize)
++ /* 105 unused */
++/* get all modem bits */
++#define TARGET_TIOCMGET TARGET_IOR('t', 106, int)
++#define TARGET_TIOCM_LE 0001 /* line enable */
++#define TARGET_TIOCM_DTR 0002 /* data terminal ready */
++#define TARGET_TIOCM_RTS 0004 /* request to send */
++#define TARGET_TIOCM_ST 0010 /* secondary transmit */
++#define TARGET_TIOCM_SR 0020 /* secondary receive */
++#define TARGET_TIOCM_CTS 0040 /* clear to send */
++#define TARGET_TIOCM_DCD 0100 /* data carrier detect */
++#define TARGET_TIOCM_RI 0200 /* ring indicate */
++#define TARGET_TIOCM_DSR 0400 /* data set ready */
++#define TARGET_TIOCM_CD TARGET_TIOCM_DCD
++#define TARGET_TIOCM_CAR TARGET_TIOCM_DCD
++#define TARGET_TIOCM_RNG TARGET_TIOCM_RI
++#define TARGET_TIOCMBIC TARGET_IOW('t', 107, int) /* bic modem bits */
++#define TARGET_TIOCMBIS TARGET_IOW('t', 108, int) /* bis modem bits */
++#define TARGET_TIOCMSET TARGET_IOW('t', 109, int) /* set all modem bits */
++/* start output, like ^Q */
++#define TARGET_TIOCSTART TARGET_IO('t', 110)
++/* stop output, like ^S */
++#define TARGET_TIOCSTOP TARGET_IO('t', 111)
++/* pty: set/clear packet mode */
++#define TARGET_TIOCPKT TARGET_IOW('t', 112, int)
++#define TARGET_TIOCPKT_DATA 0x00 /* data packet */
++#define TARGET_TIOCPKT_FLUSHREAD 0x01 /* flush packet */
++#define TARGET_TIOCPKT_FLUSHWRITE 0x02 /* flush packet */
++#define TARGET_TIOCPKT_STOP 0x04 /* stop output */
++#define TARGET_TIOCPKT_START 0x08 /* start output */
++#define TARGET_TIOCPKT_NOSTOP 0x10 /* no more ^S, ^Q */
++#define TARGET_TIOCPKT_DOSTOP 0x20 /* now do ^S ^Q */
++#define TARGET_TIOCPKT_IOCTL 0x40 /* state change of pty
++ driver */
++#define TARGET_TIOCNOTTY TARGET_IO('t', 113) /* void tty
++ association */
++#define TARGET_TIOCSTI TARGET_IOW('t', 114, char) /* simulate
++ terminal input */
++#define TARGET_TIOCOUTQ TARGET_IOR('t', 115, int) /* output queue size */
++ /* 116-117 compat */
++#define TARGET_TIOCSPGRP TARGET_IOW('t', 118, int) /* set pgrp of tty */
++#define TARGET_TIOCGPGRP TARGET_IOR('t', 119, int) /* get pgrp of tty */
++#define TARGET_TIOCCDTR TARGET_IO('t', 120) /* clear data terminal
++ ready */
++#define TARGET_TIOCSDTR TARGET_IO('t', 121) /* set data terminal
++ ready */
++#define TARGET_TIOCCBRK TARGET_IO('t', 122) /* clear break bit */
++#define TARGET_TIOCSBRK TARGET_IO('t', 123) /* set break bit */
++ /* 124-127 compat */
++
++#define TARGET_TTYDISC 0 /* termios tty line
++ discipline */
++#define TARGET_SLIPDISC 4 /* serial IP discipline */
++#define TARGET_PPPDISC 5 /* PPP discipline */
++#define TARGET_NETGRAPHDISC 6 /* Netgraph tty node
++ discipline */
++#define TARGET_H4DISC 7 /* Netgraph Bluetooth H4
++ discipline */
++
++#endif /* _FREEBSD_TTYCOM_H_ */
+diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
+index 9d4edbf..e3bcc57 100644
+--- a/bsd-user/qemu.h
++++ b/bsd-user/qemu.h
+@@ -23,6 +23,7 @@ extern enum BSDType bsd_type;
+ abi_long memcpy_to_target(abi_ulong dest, const void *src,
+ unsigned long len);
+
++#include "exec/user/thunk.h"
+ #include "syscall_defs.h"
+ #include "syscall.h"
+ #include "target_vmparam.h"
+diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
+index bde9ee9..89ce296 100644
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -47,6 +47,12 @@
+ #include <sys/thr.h>
+ #include <sys/rtprio.h>
+ #include <sys/umtx.h>
++#include <sys/uuid.h>
++#include <sys/_termios.h>
++#include <sys/ttycom.h>
++#include <sys/reboot.h>
++#include <sys/timex.h>
++#include <kenv.h>
+ #include <pthread.h>
+ #include <machine/atomic.h>
+ #endif
+@@ -61,6 +67,10 @@
+
+ #include "qemu.h"
+ #include "qemu-common.h"
++#ifdef __FreeBSD__
++#include "freebsd/ttycom.h"
++#endif
++
+
+ //#define DEBUG
+
+@@ -791,7 +801,7 @@ host_to_target_waitstatus(int status)
+ }
+
+ static inline abi_long
+-copy_from_user_timeval(struct timeval *tv, abi_ulong target_tv_addr)
++target_to_host_timeval(struct timeval *tv, abi_ulong target_tv_addr)
+ {
+ struct target_freebsd_timeval *target_tv;
+
+@@ -804,6 +814,33 @@ copy_from_user_timeval(struct timeval *tv, abi_ulong target_tv_addr)
+ }
+
+ static inline abi_long
++target_to_host_timex(struct timex *host_tx, abi_ulong target_tx_addr)
++{
++ struct target_timex *target_tx;
++
++ if (!lock_user_struct(VERIFY_READ, target_tx, target_tx_addr, 0))
++ return (-TARGET_EFAULT);
++ __get_user(host_tx->modes, &target_tx->modes);
++ __get_user(host_tx->offset, &target_tx->offset);
++ __get_user(host_tx->freq, &target_tx->freq);
++ __get_user(host_tx->maxerror, &target_tx->maxerror);
++ __get_user(host_tx->esterror, &target_tx->esterror);
++ __get_user(host_tx->status, &target_tx->status);
++ __get_user(host_tx->constant, &target_tx->constant);
++ __get_user(host_tx->precision, &target_tx->precision);
++ __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
++ __get_user(host_tx->jitter, &target_tx->jitter);
++ __get_user(host_tx->shift, &target_tx->shift);
++ __get_user(host_tx->stabil, &target_tx->stabil);
++ __get_user(host_tx->jitcnt, &target_tx->jitcnt);
++ __get_user(host_tx->calcnt, &target_tx->calcnt);
++ __get_user(host_tx->errcnt, &target_tx->errcnt);
++ __get_user(host_tx->stbcnt, &target_tx->stbcnt);
++ unlock_user_struct(target_tx, target_tx_addr, 1);
++ return (0);
++}
++
++static inline abi_long
+ target_to_host_timespec(struct timespec *ts, abi_ulong target_ts_addr)
+ {
+ struct target_freebsd_timespec *target_ts;
+@@ -817,7 +854,7 @@ target_to_host_timespec(struct timespec *ts, abi_ulong target_ts_addr)
+ }
+
+ static inline abi_long
+-fbsd_copy_to_user_timeval(struct timeval *tv, abi_ulong target_tv_addr)
++host_to_target_timeval(struct timeval *tv, abi_ulong target_tv_addr)
+ {
+ struct target_freebsd_timeval *target_tv;
+
+@@ -841,6 +878,23 @@ host_to_target_timespec(abi_ulong target_ts_addr, struct timespec *ts)
+ unlock_user_struct(target_ts, target_ts_addr, 1);
+ return (0);
+ }
++
++static inline abi_long
++host_to_target_ntptimeval(abi_ulong target_ntv_addr, struct ntptimeval *ntv)
++{
++ struct target_ntptimeval *target_ntv;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_ntv, target_ntv_addr, 0))
++ return (-TARGET_EFAULT);
++ __put_user(ntv->time.tv_sec, &target_ntv->time.tv_sec);
++ __put_user(ntv->time.tv_nsec, &target_ntv->time.tv_nsec);
++ __put_user(ntv->maxerror, &target_ntv->maxerror);
++ __put_user(ntv->esterror, &target_ntv->esterror);
++ __put_user(ntv->tai, &target_ntv->tai);
++ __put_user(ntv->time_state, &target_ntv->time_state);
++ return (0);
++}
++
+ static inline abi_ulong
+ copy_from_user_fdset(fd_set *fds, abi_ulong target_fds_addr, int n)
+ {
+@@ -1251,7 +1305,7 @@ do_freebsd_select(int n, abi_ulong rfd_addr, abi_ulong wfd_addr,
+ return (ret);
+
+ if (target_tv_addr) {
+- if (copy_from_user_timeval(&tv, target_tv_addr))
++ if (target_to_host_timeval(&tv, target_tv_addr))
+ return (-TARGET_EFAULT);
+ tv_ptr = &tv;
+ } else {
+@@ -1269,7 +1323,7 @@ do_freebsd_select(int n, abi_ulong rfd_addr, abi_ulong wfd_addr,
+ return (-TARGET_EFAULT);
+
+ if (target_tv_addr &&
+- fbsd_copy_to_user_timeval(&tv, target_tv_addr))
++ host_to_target_timeval(&tv, target_tv_addr))
+ return (-TARGET_EFAULT);
+ }
+
+@@ -2483,234 +2537,1659 @@ do_thr_set_name(long tid, char *name)
+ #endif /* CONFIG_USE_NPTL */
+
+ static int
+-do_umtx_lock(abi_ulong umtx_addr, uint32_t id)
++tcmpset_al(abi_ulong *addr, abi_ulong a, abi_ulong b)
+ {
+- int ret = 0;
++ abi_ulong current = tswapal(a);
++ abi_ulong new = tswapal(b);
++
++#ifdef TARGET_ABI32
++ return (atomic_cmpset_acq_32(addr, current, new));
++#else
++ return (atomic_cmpset_acq_64(addr, current, new));
++#endif
++}
++
++static int
++tcmpset_32(uint32_t *addr, uint32_t a, uint32_t b)
++{
++ uint32_t current = tswap32(a);
++ uint32_t new = tswap32(b);
++
++ return (atomic_cmpset_acq_32(addr, current, new));
++}
++
++static int
++do_lock_umtx(abi_ulong target_addr, abi_long id, struct timespec *timeout)
++{
++ abi_long owner;
++ int ret;
+
++ /*
++ * XXX Note that memory at umtx_addr can change and so we need to be
++ * careful and check for faults.
++ */
+ for (;;) {
+- ret = get_errno(_umtx_op(g2h(umtx_addr +
+- offsetof(struct target_umtx, u_owner)),
+- UMTX_OP_MUTEX_WAIT, UMTX_UNOWNED, 0, 0));
++ struct target_umtx *target_umtx;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_umtx, target_addr, 0))
++ return (-TARGET_EFAULT);
++
++ /* Check the simple uncontested case. */
++ if (tcmpset_al(&target_umtx->u_owner,
++ TARGET_UMTX_UNOWNED, id)) {
++ unlock_user_struct(target_umtx, target_addr, 1);
++ return (0);
++ }
++
++ /* Check to see if the lock is contested but free. */
++ __get_user(owner, &target_umtx->u_owner);
++
++ if (TARGET_UMTX_CONTESTED == owner) {
++ if (tcmpset_al(&target_umtx->u_owner,
++ TARGET_UMTX_CONTESTED,
++ id | TARGET_UMTX_CONTESTED)) {
++ unlock_user_struct(target_umtx, target_addr, 1);
++ return (0);
++ }
++
++ /* We failed because it changed on us, restart. */
++ unlock_user_struct(target_umtx, target_addr, 1);
++ continue;
++ }
++
++ /* Set the contested bit and sleep. */
++ do {
++ __get_user(owner, &target_umtx->u_owner);
++ if (owner & TARGET_UMTX_CONTESTED)
++ break;
++ } while (!tcmpset_al(&target_umtx->u_owner, owner,
++ owner | TARGET_UMTX_CONTESTED));
++
++ __get_user(owner, &target_umtx->u_owner);
++ unlock_user_struct(target_umtx, target_addr, 1);
++
++ /* Byte swap, if needed, to match what is stored in user mem. */
++ owner = tswapal(owner);
++#ifdef TARGET_ABI32
++ ret = get_errno(_umtx_op(target_umtx, UMTX_OP_WAIT_UINT, owner,
++ NULL, timeout));
++#else
++ ret = get_errno(_umtx_op(target_umtx, UMTX_OP_WAIT, owner,
++ NULL, timeout));
++#endif
+ if (ret)
+ return (ret);
+- if (atomic_cmpset_acq_32(g2h(umtx_addr +
+- offsetof(struct target_umtx, u_owner)),
+- UMTX_UNOWNED, id))
+- return (0);
+ }
+ }
+
+ static int
+-do_umtx_unlock(abi_ulong umtx_addr, uint32 id)
++do_unlock_umtx(abi_ulong target_addr, abi_ulong id)
+ {
+- uint32_t owner;
++ abi_ulong owner;
++ struct target_umtx *target_umtx;
+
+- do {
+- if (get_user_u32(owner, umtx_addr +
+- offsetof(struct target_umtx, u_owner)))
+- return (-TARGET_EFAULT);
+- if (owner != id)
+- return (-TARGET_EPERM);
+- } while (!atomic_cmpset_rel_32(g2h(umtx_addr +
+- offsetof(struct target_umtx, u_owner)), owner,
+- UMUTEX_UNOWNED));
++ if (!lock_user_struct(VERIFY_WRITE, target_umtx, target_addr, 0))
++ return (-TARGET_EFAULT);
++
++ __get_user(owner, &target_umtx->u_owner);
++ if ((owner & ~TARGET_UMTX_CONTESTED) != id) {
++ unlock_user_struct(target_umtx, target_addr, 1);
++ return (-TARGET_EPERM);
++ }
++
++ /* Check the simple uncontested case. */
++ if ((owner & ~TARGET_UMTX_CONTESTED) == 0)
++ if (tcmpset_al(&target_umtx->u_owner, owner,
++ TARGET_UMTX_UNOWNED)) {
++ unlock_user_struct(target_umtx, target_addr, 1);
++ return (0);
++ }
++
++ /* This is a contested lock. Unlock it. */
++ __put_user(TARGET_UMTX_UNOWNED, &target_umtx->u_owner);
++ unlock_user_struct(target_umtx, target_addr, 1);
++
++ /* Wake up all those contesting it. */
++ _umtx_op(target_umtx, UMTX_OP_WAKE, 0, 0, 0);
+
+ return (0);
+ }
+
+-
+-/* 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>. */
+-abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+- abi_long arg2, abi_long arg3, abi_long arg4,
+- abi_long arg5, abi_long arg6, abi_long arg7,
+- abi_long arg8)
++static int
++do_lock_umutex(abi_ulong target_addr, uint32_t id, struct timespec *ts,
++ int mode)
+ {
+- abi_long ret;
+- void *p;
+- struct stat st;
++ uint32_t owner, flags;
++ int ret;
+
+-#ifdef DEBUG
+- gemu_log("freebsd syscall %d\n", num);
+-#endif
+- if(do_strace)
+- print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
+-
+- switch(num) {
+- case TARGET_FREEBSD_NR_exit:
+-#ifdef TARGET_GPROF
+- _mcleanup();
+-#endif
+- gdb_exit(cpu_env, arg1);
+- /* XXX: should free thread stack and CPU env */
+- _exit(arg1);
+- ret = 0; /* avoid warning */
+- break;
+- case TARGET_FREEBSD_NR_read:
+- if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
+- goto efault;
+- ret = get_errno(read(arg1, p, arg3));
+- unlock_user(p, arg2, ret);
+- break;
++ for (;;) {
++ struct target_umutex *target_umutex;
+
+- case TARGET_FREEBSD_NR_readv:
+- {
+- int count = arg3;
+- struct iovec *vec;
++ if (!lock_user_struct(VERIFY_WRITE, target_umutex,
++ target_addr, 0))
++ return (-TARGET_EFAULT);
+
+- vec = alloca(count * sizeof(struct iovec));
+- if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
+- goto efault;
+- ret = get_errno(readv(arg1, vec, count));
+- unlock_iovec(vec, arg2, count, 1);
+- }
+- break;
++ __get_user(owner, &target_umutex->m_owner);
+
+- case TARGET_FREEBSD_NR_pread:
+- if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
+- goto efault;
+- ret = get_errno(pread(arg1, p, arg3, target_offset64(arg4, arg5)));
+- unlock_user(p, arg2, ret);
+- break;
++ if (TARGET_UMUTEX_WAIT == mode) {
++ if (TARGET_UMUTEX_UNOWNED == owner ||
++ TARGET_UMUTEX_CONTESTED == owner)
++ unlock_user_struct(target_umutex,
++ target_addr, 1);
++ return (0);
++ } else {
++ if (tcmpset_32(&target_umutex->m_owner,
++ TARGET_UMUTEX_UNOWNED, id)) {
++ /* The acquired succeeded. */
++ unlock_user_struct(target_umutex,
++ target_addr, 1);
++ return (0);
++ }
+
+- case TARGET_FREEBSD_NR_preadv:
+- {
+- int count = arg3;
+- struct iovec *vec;
++ /*
++ * If no one owns it but it is contested try to acquire
++ * it.
++ */
++ if (TARGET_UMUTEX_CONTESTED == owner) {
++ if (tcmpset_32(&target_umutex->m_owner,
++ TARGET_UMUTEX_CONTESTED,
++ id | TARGET_UMUTEX_CONTESTED)) {
+
+- vec = alloca(count * sizeof(struct iovec));
+- if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
+- goto efault;
+- ret = get_errno(preadv(arg1, vec, count,
+- target_offset64(arg4, arg5)));
+- unlock_iovec(vec, arg2, count, 1);
+- }
+- break;
++ unlock_user_struct(target_umutex,
++ target_addr, 1);
++ return (0);
++ }
+
+- case TARGET_FREEBSD_NR_write:
+- if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
+- goto efault;
+- ret = get_errno(write(arg1, p, arg3));
+- unlock_user(p, arg2, 0);
+- break;
++ /* The lock changed so restart. */
++ unlock_user_struct(target_umutex,
++ target_addr, 1);
++ continue;
++ }
++ }
+
+- case TARGET_FREEBSD_NR_writev:
+- {
+- int count = arg3;
+- struct iovec *vec;
++ __get_user(flags, &target_umutex->m_flags);
++ flags = tswap32(flags);
++ if ((flags & TARGET_UMUTEX_ERROR_CHECK) != 0 &&
++ (owner & ~TARGET_UMUTEX_CONTESTED) == id) {
++ unlock_user_struct(target_umutex, target_addr, 1);
++ return (-TARGET_EDEADLK);
++ }
+
+- vec = alloca(count * sizeof(struct iovec));
+- if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
+- goto efault;
+- ret = get_errno(writev(arg1, vec, count));
+- unlock_iovec(vec, arg2, count, 0);
+- }
+- break;
++ if (TARGET_UMUTEX_TRY == mode) {
++ unlock_user_struct(target_umutex, target_addr, 1);
++ return (-TARGET_EBUSY);
++ }
+
+- case TARGET_FREEBSD_NR_pwrite:
+- if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
+- goto efault;
+- ret = get_errno(pwrite(arg1, p, arg3, target_offset64(arg4, arg5)));
+- unlock_user(p, arg2, 0);
+- break;
++ /* Set the contested bit and sleep. */
++ if (!tcmpset_32(&target_umutex->m_owner, owner,
++ owner | TARGET_UMUTEX_CONTESTED)) {
++ unlock_user_struct(target_umutex, target_addr, 1);
++ continue;
++ }
+
+- case TARGET_FREEBSD_NR_pwritev:
+- {
+- int count = arg3;
+- struct iovec *vec;
++ owner = owner | TARGET_UMUTEX_CONTESTED;
++ unlock_user_struct(target_umutex, target_addr, 1);
+
+- vec = alloca(count * sizeof(struct iovec));
+- if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
+- goto efault;
+- ret = get_errno(pwritev(arg1, vec, count,
+- target_offset64(arg4, arg5)));
+- unlock_iovec(vec, arg2, count, 0);
++ /* Byte swap, if needed, to match what is stored in user mem. */
++ owner = tswap32(owner);
++ ret = get_errno(_umtx_op(target_umutex, UMTX_OP_WAIT_UINT, owner,
++ 0, ts));
++ if (ret)
++ return (ret);
+ }
+- break;
+
+- case TARGET_FREEBSD_NR_open:
+- if (!(p = lock_user_string(arg1)))
+- goto efault;
+- ret = get_errno(open(path(p),
+- target_to_host_bitmask(arg2, fcntl_flags_tbl),
+- arg3));
+- unlock_user(p, arg1, 0);
+- break;
++ return (0);
++}
+
+- case TARGET_FREEBSD_NR_openat:
+- if (!(p = lock_user_string(arg2)))
+- goto efault;
+- ret = get_errno(openat(arg1, path(p),
+- target_to_host_bitmask(arg3, fcntl_flags_tbl),
+- arg4));
+- unlock_user(p, arg2, 0);
+- break;
++static int
++do_unlock_umutex(abi_ulong target_addr, uint32_t id)
++{
++ struct target_umutex *target_umutex;
++ uint32_t owner;
+
+- case TARGET_FREEBSD_NR_close:
+- ret = get_errno(close(arg1));
+- break;
+
+- case TARGET_FREEBSD_NR_closefrom:
+- ret = 0;
+- closefrom(arg1);
+- break;
++ if (!lock_user_struct(VERIFY_WRITE, target_umutex, target_addr, 0))
++ return (-TARGET_EFAULT);
+
+-#ifdef TARGET_FREEBSD_NR_creat
+- case TARGET_FREEBSD_NR_creat:
+- if (!(p = lock_user_string(arg1)))
+- goto efault;
+- ret = get_errno(creat(p, arg2));
+- unlock_user(p, arg1, 0);
+- break;
+-#endif
++ /* Make sure we own this mutex. */
++ __get_user(owner, &target_umutex->m_owner);
++ if ((owner & ~TARGET_UMUTEX_CONTESTED) != id) {
++ unlock_user_struct(target_umutex, target_addr, 1);
++ return (-TARGET_EPERM);
++ }
+
+- case TARGET_FREEBSD_NR_mmap:
+- ret = get_errno(target_mmap(arg1, arg2, arg3,
+- target_to_host_bitmask(arg4, mmap_flags_tbl),
+- arg5,
+- arg6));
+- break;
++ if ((owner & TARGET_UMUTEX_CONTESTED) == 0)
++ if (tcmpset_32(&target_umutex->m_owner, owner,
++ TARGET_UMTX_UNOWNED)) {
++ unlock_user_struct(target_umutex, target_addr, 1);
++ return (0);
++ }
+
+- case TARGET_FREEBSD_NR_munmap:
+- ret = get_errno(target_munmap(arg1, arg2));
+- break;
++ /* This is a contested lock. Unlock it. */
++ __put_user(TARGET_UMUTEX_UNOWNED, &target_umutex->m_owner);
++ unlock_user_struct(target_umutex, target_addr, 1);
+
+- case TARGET_FREEBSD_NR_mprotect:
+- ret = get_errno(target_mprotect(arg1, arg2, arg3));
+- break;
++ /* And wake up all those contesting it. */
++ return ( _umtx_op(g2h(target_addr), UMTX_OP_WAKE, 0, 0, 0));
++}
+
+- case TARGET_FREEBSD_NR_msync:
+- ret = get_errno(msync(g2h(arg1), arg2, arg3));
+- break;
++/*
++ * _cv_mutex is keeps other threads from doing a signal or broadcast until
++ * the thread is actually asleep and ready. This is a global mutex for all
++ * condition vars so I am sure performance may be a problem if there are lots
++ * of CVs.
++ */
++static struct umutex _cv_mutex = {0,0,{0,0},{0,0,0,0}};
+
+- case TARGET_FREEBSD_NR_mlock:
+- ret = get_errno(mlock(g2h(arg1), arg2));
+- break;
+
+- case TARGET_FREEBSD_NR_munlock:
+- ret = get_errno(munlock(g2h(arg1), arg2));
+- break;
++/*
++ * wflags CVWAIT_CHECK_UNPARKING, CVWAIT_ABSTIME, CVWAIT_CLOCKID
++ */
++static int
++do_cv_wait(abi_ulong target_ucond_addr, abi_ulong target_umtx_addr,
++ struct timespec *ts, int wflags)
++{
++ long tid;
++ int ret;
+
+- case TARGET_FREEBSD_NR_mlockall:
+- ret = get_errno(mlockall(arg1));
+- break;
++ if (! access_ok(VERIFY_WRITE, target_ucond_addr,
++ sizeof(struct target_ucond))) {
+
+- case TARGET_FREEBSD_NR_munlockall:
+- ret = get_errno(munlockall());
+- break;
++ return (-TARGET_EFAULT);
++ }
+
+- case TARGET_FREEBSD_NR_madvise:
+- /*
+- * A straight passthrough may not be safe because qemu sometimes
+- * turns private file-backed mapping into anonymous mappings. This
+- * will break MADV_DONTNEED. This is a hint, so ignoring and returing
+- * success is ok.
+- */
+- ret = get_errno(0);
+- break;
++ /* Check the clock ID if needed. */
++ if ((wflags & TARGET_CVWAIT_CLOCKID) != 0) {
++ struct target_ucond *target_ucond;
++ uint32_t clockid;
+
+- case TARGET_FREEBSD_NR_break:
++ if (!lock_user_struct(VERIFY_WRITE, target_ucond,
++ target_ucond_addr, 0))
++ return (-TARGET_EFAULT);
++ __get_user(clockid, &target_ucond->c_clockid);
++ unlock_user_struct(target_ucond, target_ucond_addr, 1);
++ if (clockid < CLOCK_REALTIME ||
++ clockid >= CLOCK_THREAD_CPUTIME_ID) {
++ /* Only HW clock id will work. */
++ return (-TARGET_EINVAL);
++ }
++ }
++
++ thr_self(&tid);
++
++ /* Lock the _cv_mutex so we can safely unlock the user mutex */
++ _umtx_op(&_cv_mutex, UMTX_OP_MUTEX_LOCK, 0, NULL, NULL);
++
++ /* unlock the user mutex */
++ ret = do_unlock_umutex(target_umtx_addr, tid);
++ if (ret) {
++ _umtx_op(&_cv_mutex, UMTX_OP_MUTEX_UNLOCK, 0, NULL, NULL);
++ return (ret);
++ }
++
++ /* UMTX_OP_CV_WAIT unlocks _cv_mutex */
++ ret = get_errno(_umtx_op(g2h(target_ucond_addr), UMTX_OP_CV_WAIT,
++ wflags, &_cv_mutex, ts));
++
++ return (ret);
++}
++
++static int
++do_cv_signal(abi_ulong target_ucond_addr)
++{
++ int ret;
++
++ if (! access_ok(VERIFY_WRITE, target_ucond_addr,
++ sizeof(struct target_ucond)))
++ return (-TARGET_EFAULT);
++
++ /* Lock the _cv_mutex to prevent a race in do_cv_wait(). */
++ _umtx_op(&_cv_mutex, UMTX_OP_MUTEX_LOCK, 0, NULL, NULL);
++ ret = get_errno(_umtx_op(g2h(target_ucond_addr), UMTX_OP_CV_SIGNAL, 0,
++ NULL, NULL));
++ _umtx_op(&_cv_mutex, UMTX_OP_MUTEX_UNLOCK, 0, NULL, NULL);
++
++ return (ret);
++}
++
++static int
++do_cv_broadcast(abi_ulong target_ucond_addr)
++{
++ int ret;
++
++ if (! access_ok(VERIFY_WRITE, target_ucond_addr,
++ sizeof(struct target_ucond)))
++ return (-TARGET_EFAULT);
++
++ /* Lock the _cv_mutex to prevent a race in do_cv_wait(). */
++ _umtx_op(&_cv_mutex, UMTX_OP_MUTEX_LOCK, 0, NULL, NULL);
++ ret = get_errno(_umtx_op(g2h(target_ucond_addr), UMTX_OP_CV_BROADCAST,
++ 0, NULL, NULL));
++ _umtx_op(&_cv_mutex, UMTX_OP_MUTEX_UNLOCK, 0, NULL, NULL);
++
++ return (ret);
++}
++
++static int
++do_umtx_op_wait(abi_ulong target_addr, abi_ulong id, struct timespec *ts)
++{
++
++ /* We want to check the user memory but not lock it. We might sleep. */
++ if (! access_ok(VERIFY_READ, target_addr, sizeof(abi_ulong)))
++ return (-TARGET_EFAULT);
++
++ /* id has already been byte swapped to match what may be in user mem. */
++#ifdef TARGET_ABI32
++ return (get_errno(_umtx_op(g2h(target_addr), UMTX_OP_WAIT_UINT, id, NULL,
++ ts)));
++#else
++ return (get_errno(_umtx_op(g2h(target_addr), UMTX_OP_WAIT, id, NULL,
++ ts)));
++#endif
++}
++
++static int
++do_umtx_op_wake(abi_ulong target_addr, abi_ulong n_wake)
++{
++
++ return (get_errno(_umtx_op(g2h(target_addr), UMTX_OP_WAKE, n_wake, NULL,
++ 0)));
++}
++
++static int
++do_rw_rdlock(abi_ulong target_addr, long fflag, struct timespec *ts)
++{
++ struct target_urwlock *target_urwlock;
++ uint32_t flags, wrflags;
++ uint32_t state;
++ uint32_t blocked_readers;
++ int ret;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_urwlock, target_addr, 0))
++ return (-TARGET_EFAULT);
++
++ __get_user(flags, &target_urwlock->rw_flags);
++ wrflags = TARGET_URWLOCK_WRITE_OWNER;
++ if (!(fflag & TARGET_URWLOCK_PREFER_READER) &&
++ !(flags & TARGET_URWLOCK_PREFER_READER))
++ wrflags |= TARGET_URWLOCK_WRITE_WAITERS;
++
++ for (;;) {
++ __get_user(state, &target_urwlock->rw_state);
++ /* try to lock it */
++ while (!(state & wrflags)) {
++ if (TARGET_URWLOCK_READER_COUNT(state) ==
++ TARGET_URWLOCK_MAX_READERS) {
++ unlock_user_struct(target_urwlock,
++ target_addr, 1);
++ return (-TARGET_EAGAIN);
++ }
++ if (tcmpset_32(&target_urwlock->rw_state, state,
++ (state + 1))) {
++ /* The acquired succeeded. */
++ unlock_user_struct(target_urwlock,
++ target_addr, 1);
++ return (0);
++ }
++ __get_user(state, &target_urwlock->rw_state);
++ }
++
++ /* set read contention bit */
++ if (! tcmpset_32(&target_urwlock->rw_state, state,
++ state | TARGET_URWLOCK_READ_WAITERS)) {
++ /* The state has changed. Start over. */
++ continue;
++ }
++
++ /* contention bit is set, increase read waiter count */
++ __get_user(blocked_readers, &target_urwlock->rw_blocked_readers);
++ while (! tcmpset_32(&target_urwlock->rw_blocked_readers,
++ blocked_readers, blocked_readers + 1)) {
++ __get_user(blocked_readers,
++ &target_urwlock->rw_blocked_readers);
++ }
++
++ while (state & wrflags) {
++ /* sleep/wait */
++ unlock_user_struct(target_urwlock, target_addr, 1);
++ ret = get_errno(_umtx_op(
++ &target_urwlock->rw_blocked_readers,
++ UMTX_OP_WAIT_UINT, blocked_readers, 0, ts));
++ if (ret)
++ return (ret);
++ if (!lock_user_struct(VERIFY_WRITE, target_urwlock,
++ target_addr, 0))
++ return (-TARGET_EFAULT);
++ __get_user(state, &target_urwlock->rw_state);
++ }
++
++ /* decrease read waiter count */
++ __get_user(blocked_readers, &target_urwlock->rw_blocked_readers);
++ while (! tcmpset_32(&target_urwlock->rw_blocked_readers,
++ blocked_readers, (blocked_readers - 1))) {
++ __get_user(blocked_readers,
++ &target_urwlock->rw_blocked_readers);
++ }
++ if (1 == blocked_readers) {
++ /* clear read contention bit */
++ __get_user(state, &target_urwlock->rw_state);
++ while(! tcmpset_32(&target_urwlock->rw_state, state,
++ state & ~TARGET_URWLOCK_READ_WAITERS)) {
++ __get_user(state, &target_urwlock->rw_state);
++ }
++ }
++ }
++}
++
++static int
++do_rw_wrlock(abi_ulong target_addr, long fflag, struct timespec *ts)
++{
++ struct target_urwlock *target_urwlock;
++ uint32_t blocked_readers, blocked_writers;
++ uint32_t state;
++ int ret;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_urwlock, target_addr, 0))
++ return (-TARGET_EFAULT);
++
++ blocked_readers = 0;
++ for (;;) {
++ __get_user(state, &target_urwlock->rw_state);
++ while (!(state & TARGET_URWLOCK_WRITE_OWNER) &&
++ TARGET_URWLOCK_READER_COUNT(state) == 0) {
++ if (tcmpset_32(&target_urwlock->rw_state, state,
++ state | TARGET_URWLOCK_WRITE_OWNER)) {
++ unlock_user_struct(target_urwlock,
++ target_addr, 1);
++ return (0);
++ }
++ __get_user(state, &target_urwlock->rw_state);
++ }
++
++ if (!(state & (TARGET_URWLOCK_WRITE_OWNER |
++ TARGET_URWLOCK_WRITE_WAITERS)) &&
++ blocked_readers != 0) {
++ ret = get_errno(_umtx_op(
++ &target_urwlock->rw_blocked_readers,
++ UMTX_OP_WAKE, INT_MAX, NULL, NULL));
++ return (ret);
++ }
++
++ /* re-read the state */
++ __get_user(state, &target_urwlock->rw_state);
++
++ /* and set TARGET_URWLOCK_WRITE_WAITERS */
++ while (((state & TARGET_URWLOCK_WRITE_OWNER) ||
++ TARGET_URWLOCK_READER_COUNT(state) != 0) &&
++ (state & TARGET_URWLOCK_WRITE_WAITERS) == 0) {
++ if (tcmpset_32(&target_urwlock->rw_state, state,
++ state | TARGET_URWLOCK_WRITE_WAITERS)) {
++ break;
++ }
++ __get_user(state, &target_urwlock->rw_state);
++ }
++
++ /* contention bit is set, increase write waiter count */
++ __get_user(blocked_writers, &target_urwlock->rw_blocked_writers);
++ while (! tcmpset_32(&target_urwlock->rw_blocked_writers,
++ blocked_writers, blocked_writers + 1)) {
++ __get_user(blocked_writers,
++ &target_urwlock->rw_blocked_writers);
++ }
++
++ /* sleep */
++ while ((state & TARGET_URWLOCK_WRITE_OWNER) ||
++ (TARGET_URWLOCK_READER_COUNT(state) != 0)) {
++ unlock_user_struct(target_urwlock, target_addr, 1);
++ ret = get_errno(_umtx_op(
++ &target_urwlock->rw_blocked_writers,
++ UMTX_OP_WAIT_UINT, blocked_writers, 0, ts));
++ if (ret)
++ return (ret);
++ if (!lock_user_struct(VERIFY_WRITE, target_urwlock,
++ target_addr, 0))
++ return (-TARGET_EFAULT);
++ __get_user(state, &target_urwlock->rw_state);
++ }
++
++ /* decrease the write waiter count */
++ __get_user(blocked_writers, &target_urwlock->rw_blocked_writers);
++ while (! tcmpset_32(&target_urwlock->rw_blocked_writers,
++ blocked_writers, (blocked_writers - 1))) {
++ __get_user(blocked_writers,
++ &target_urwlock->rw_blocked_writers);
++ }
++ if (1 == blocked_writers) {
++ /* clear write contention bit */
++ __get_user(state, &target_urwlock->rw_state);
++ while(! tcmpset_32(&target_urwlock->rw_state, state,
++ state & ~TARGET_URWLOCK_WRITE_WAITERS)) {
++ __get_user(state, &target_urwlock->rw_state);
++ }
++ __get_user(blocked_readers,
++ &target_urwlock->rw_blocked_readers);
++ } else
++ blocked_readers = 0;
++ }
++}
++
++static int
++do_rw_unlock(abi_ulong target_addr)
++{
++ struct target_urwlock *target_urwlock;
++ uint32_t flags, state, count;
++ void *q = NULL;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_urwlock, target_addr, 0))
++ return (-TARGET_EFAULT);
++
++ __get_user(flags, &target_urwlock->rw_flags);
++ __get_user(state, &target_urwlock->rw_state);
++
++ if (state & TARGET_URWLOCK_WRITE_OWNER) {
++ for (;;) {
++ if (! tcmpset_32(&target_urwlock->rw_state, state,
++ state & ~TARGET_URWLOCK_WRITE_OWNER)) {
++ __get_user(state, &target_urwlock->rw_state);
++ if (!(state & TARGET_URWLOCK_WRITE_OWNER)) {
++ unlock_user_struct(target_urwlock,
++ target_addr, 1);
++ return (-TARGET_EPERM);
++ }
++ } else
++ break;
++ }
++ } else if (TARGET_URWLOCK_READER_COUNT(state) != 0) {
++ /* decrement reader count */
++ for (;;) {
++ if (! tcmpset_32(&target_urwlock->rw_state,
++ state, (state - 1))) {
++ if (TARGET_URWLOCK_READER_COUNT(state) == 0) {
++ unlock_user_struct(target_urwlock,
++ target_addr, 1);
++ return (-TARGET_EPERM);
++ }
++ } else
++ break;
++ }
++ } else {
++ unlock_user_struct(target_urwlock, target_addr, 1);
++ return (-TARGET_EPERM);
++ }
++
++ count = 0;
++
++ if (! (flags & TARGET_URWLOCK_PREFER_READER)) {
++ if (state & TARGET_URWLOCK_WRITE_WAITERS) {
++ count = 1;
++ q = &target_urwlock->rw_blocked_writers;
++ } else if (state & TARGET_URWLOCK_READ_WAITERS) {
++ count = INT_MAX;
++ q = &target_urwlock->rw_blocked_readers;
++ }
++ } else {
++ if (state & TARGET_URWLOCK_READ_WAITERS) {
++ count = INT_MAX;
++ q = &target_urwlock->rw_blocked_readers;
++ } else if (state & TARGET_URWLOCK_WRITE_WAITERS) {
++ count = 1;
++ q = &target_urwlock->rw_blocked_writers;
++ }
++ }
++
++ unlock_user_struct(target_urwlock, target_addr, 1);
++ if (q != NULL)
++ return (get_errno(_umtx_op(q, UMTX_OP_WAKE, count, NULL, NULL)));
++ else
++ return (0);
++}
++
++static inline abi_long
++target_to_host_statfs(struct statfs *host_statfs, abi_ulong target_addr)
++{
++ struct target_statfs *target_statfs;
++
++ if (!lock_user_struct(VERIFY_READ, target_statfs, target_addr, 1))
++ return (-TARGET_EFAULT);
++ __get_user(host_statfs->f_version, &target_statfs->f_version);
++ __get_user(host_statfs->f_type, &target_statfs->f_type);
++ __get_user(host_statfs->f_flags, &target_statfs->f_flags);
++ __get_user(host_statfs->f_bsize, &target_statfs->f_bsize);
++ __get_user(host_statfs->f_iosize, &target_statfs->f_iosize);
++ __get_user(host_statfs->f_blocks, &target_statfs->f_blocks);
++ __get_user(host_statfs->f_bfree, &target_statfs->f_bfree);
++ __get_user(host_statfs->f_bavail, &target_statfs->f_bavail);
++ __get_user(host_statfs->f_files, &target_statfs->f_files);
++ __get_user(host_statfs->f_ffree, &target_statfs->f_ffree);
++ __get_user(host_statfs->f_syncwrites, &target_statfs->f_syncwrites);
++ __get_user(host_statfs->f_asyncwrites, &target_statfs->f_asyncwrites);
++ __get_user(host_statfs->f_syncreads, &target_statfs->f_syncreads);
++ __get_user(host_statfs->f_asyncreads, &target_statfs->f_asyncreads);
++ /* uint64_t f_spare[10]; */
++ __get_user(host_statfs->f_namemax, &target_statfs->f_namemax);
++ __get_user(host_statfs->f_owner, &target_statfs->f_owner);
++ __get_user(host_statfs->f_fsid.val[0], &target_statfs->f_fsid.val[0]);
++ __get_user(host_statfs->f_fsid.val[1], &target_statfs->f_fsid.val[1]);
++ /* char f_charspace[80]; */
++ strncpy(host_statfs->f_fstypename, &target_statfs->f_fstypename[0],
++ TARGET_MFSNAMELEN);
++ strncpy(host_statfs->f_mntfromname, &target_statfs->f_mntfromname[0],
++ TARGET_MNAMELEN);
++ strncpy(host_statfs->f_mntonname, &target_statfs->f_mntonname[0],
++ TARGET_MNAMELEN);
++ unlock_user_struct(target_statfs, target_addr, 0);
++ return (0);
++}
++
++static inline abi_long
++host_to_target_statfs(abi_ulong target_addr, struct statfs *host_statfs)
++{
++ struct target_statfs *target_statfs;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_statfs, target_addr, 0))
++ return (-TARGET_EFAULT);
++ __put_user(host_statfs->f_version, &target_statfs->f_version);
++ __put_user(host_statfs->f_type, &target_statfs->f_type);
++ __put_user(host_statfs->f_flags, &target_statfs->f_flags);
++ __put_user(host_statfs->f_bsize, &target_statfs->f_bsize);
++ __put_user(host_statfs->f_iosize, &target_statfs->f_iosize);
++ __put_user(host_statfs->f_blocks, &target_statfs->f_blocks);
++ __put_user(host_statfs->f_bfree, &target_statfs->f_bfree);
++ __put_user(host_statfs->f_bavail, &target_statfs->f_bavail);
++ __put_user(host_statfs->f_files, &target_statfs->f_files);
++ __put_user(host_statfs->f_ffree, &target_statfs->f_ffree);
++ __put_user(host_statfs->f_syncwrites, &target_statfs->f_syncwrites);
++ __put_user(host_statfs->f_asyncwrites, &target_statfs->f_asyncwrites);
++ __put_user(host_statfs->f_syncreads, &target_statfs->f_syncreads);
++ __put_user(host_statfs->f_asyncreads, &target_statfs->f_asyncreads);
++ /* uint64_t f_spare[10]; */
++ __put_user(host_statfs->f_namemax, &target_statfs->f_namemax);
++ __put_user(host_statfs->f_owner, &target_statfs->f_owner);
++ __put_user(host_statfs->f_fsid.val[0], &target_statfs->f_fsid.val[0]);
++ __put_user(host_statfs->f_fsid.val[1], &target_statfs->f_fsid.val[1]);
++ /* char f_charspace[80]; */
++ strncpy(&target_statfs->f_fstypename[0], host_statfs->f_fstypename,
++ TARGET_MFSNAMELEN);
++ strncpy(&target_statfs->f_mntfromname[0], host_statfs->f_mntfromname,
++ TARGET_MNAMELEN);
++ strncpy(&target_statfs->f_mntonname[0], host_statfs->f_mntonname,
++ TARGET_MNAMELEN);
++ unlock_user_struct(target_statfs, target_addr, 1);
++ return (0);
++}
++
++static inline abi_long
++target_to_host_fhandle(fhandle_t *host_fh, abi_ulong target_addr)
++{
++ target_fhandle_t *target_fh;
++
++ if (!lock_user_struct(VERIFY_READ, target_fh, target_addr, 1))
++ return (-TARGET_EFAULT);
++ __get_user(host_fh->fh_fsid.val[0], &target_fh->fh_fsid.val[0]);
++ __get_user(host_fh->fh_fsid.val[1], &target_fh->fh_fsid.val[0]);
++
++ __get_user(host_fh->fh_fid.fid_len, &target_fh->fh_fid.fid_len);
++ /* u_short fid_data0; */
++ memcpy(host_fh->fh_fid.fid_data, target_fh->fh_fid.fid_data,
++ TARGET_MAXFIDSZ);
++ unlock_user_struct(target_fh, target_addr, 0);
++ return (0);
++}
++
++static inline abi_long
++host_to_target_fhandle(abi_ulong target_addr, fhandle_t *host_fh)
++{
++ target_fhandle_t *target_fh;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_fh, target_addr, 0))
++ return (-TARGET_EFAULT);
++ __put_user(host_fh->fh_fsid.val[0], &target_fh->fh_fsid.val[0]);
++ __put_user(host_fh->fh_fsid.val[1], &target_fh->fh_fsid.val[0]);
++
++ __put_user(host_fh->fh_fid.fid_len, &target_fh->fh_fid.fid_len);
++ /* u_short fid_data0; */
++ memcpy(target_fh->fh_fid.fid_data, host_fh->fh_fid.fid_data,
++ TARGET_MAXFIDSZ);
++ unlock_user_struct(target_fh, target_addr, 1);
++ return (0);
++}
++
++static inline abi_long
++target_to_host_sched_param(struct sched_param *host_sp, abi_ulong target_addr)
++{
++ struct target_sched_param *target_sp;
++
++ if (!lock_user_struct(VERIFY_READ, target_sp, target_addr, 1))
++ return (-TARGET_EFAULT);
++ __get_user(host_sp->sched_priority, &target_sp->sched_priority);
++ unlock_user_struct(target_sp, target_addr, 0);
++ return (0);
++}
++
++static inline abi_long
++host_to_target_sched_param(abi_ulong target_addr, struct sched_param *host_sp)
++{
++ struct target_sched_param *target_sp;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_sp, target_addr, 0))
++ return (-TARGET_EFAULT);
++ __put_user(host_sp->sched_priority, &target_sp->sched_priority);
++ unlock_user_struct(target_sp, target_addr, 1);
++ return (0);
++}
++
++static inline abi_long
++do_sched_setparam(pid_t pid, abi_ulong target_sp_addr)
++{
++ int ret;
++ struct sched_param host_sp;
++
++ ret = target_to_host_sched_param(&host_sp, target_sp_addr);
++ if (0 == ret)
++ ret = get_errno(sched_setparam(pid, &host_sp));
++
++ return (ret);
++}
++
++static inline abi_long
++do_sched_getparam(pid_t pid, abi_ulong target_sp_addr)
++{
++ int ret;
++ struct sched_param host_sp;
++
++ ret = get_errno(sched_getparam(pid, &host_sp));
++ if (0 == ret)
++ ret = host_to_target_sched_param(target_sp_addr, &host_sp);
++
++ return (ret);
++}
++
++static inline abi_long
++do_sched_setscheduler(pid_t pid, int policy, abi_ulong target_sp_addr)
++{
++ int ret;
++ struct sched_param host_sp;
++
++ ret = target_to_host_sched_param(&host_sp, target_sp_addr);
++ if (0 == ret)
++ ret = get_errno(sched_setscheduler(pid, policy, &host_sp));
++
++ return (ret);
++}
++
++static inline abi_long
++do_sched_rr_get_interval(pid_t pid, abi_ulong target_ts_addr)
++{
++ int ret;
++ struct timespec host_ts;
++
++ ret = get_errno(sched_rr_get_interval(pid, &host_ts));
++ if (0 == ret)
++ ret = host_to_target_timespec(target_ts_addr, &host_ts);
++
++ return (ret);
++}
++
++static inline abi_long
++host_to_target_uuid(abi_ulong target_addr, struct uuid *host_uuid)
++{
++ struct target_uuid *target_uuid;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_uuid, target_addr, 0))
++ return (-TARGET_EFAULT);
++ __put_user(host_uuid->time_low, &target_uuid->time_low);
++ __put_user(host_uuid->time_mid, &target_uuid->time_mid);
++ __put_user(host_uuid->time_hi_and_version,
++ &target_uuid->time_hi_and_version);
++ host_uuid->clock_seq_hi_and_reserved =
++ target_uuid->clock_seq_hi_and_reserved;
++ host_uuid->clock_seq_low = target_uuid->clock_seq_low;
++ memcpy(host_uuid->node, target_uuid->node, TARGET_UUID_NODE_LEN);
++ unlock_user_struct(target_uuid, target_addr, 1);
++ return (0);
++}
++
++static inline abi_long
++host_to_target_stat(abi_ulong target_addr, struct stat *host_st)
++{
++ struct target_freebsd_stat *target_st;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
++ return (-TARGET_EFAULT);
++ memset(target_st, 0, sizeof(*target_st));
++ __put_user(host_st->st_dev, &target_st->st_dev);
++ __put_user(host_st->st_ino, &target_st->st_ino);
++ __put_user(host_st->st_mode, &target_st->st_mode);
++ __put_user(host_st->st_nlink, &target_st->st_nlink);
++ __put_user(host_st->st_uid, &target_st->st_uid);
++ __put_user(host_st->st_gid, &target_st->st_gid);
++ __put_user(host_st->st_rdev, &target_st->st_rdev);
++ __put_user(host_st->st_atim.tv_sec, &target_st->st_atim.tv_sec);
++ __put_user(host_st->st_atim.tv_nsec, &target_st->st_atim.tv_nsec);
++ __put_user(host_st->st_mtim.tv_sec, &target_st->st_mtim.tv_sec);
++ __put_user(host_st->st_mtim.tv_nsec, &target_st->st_mtim.tv_nsec);
++ __put_user(host_st->st_ctim.tv_sec, &target_st->st_ctim.tv_sec);
++ __put_user(host_st->st_ctim.tv_nsec, &target_st->st_ctim.tv_nsec);
++ __put_user(host_st->st_size, &target_st->st_size);
++ __put_user(host_st->st_blocks, &target_st->st_blocks);
++ __put_user(host_st->st_blksize, &target_st->st_blksize);
++ __put_user(host_st->st_flags, &target_st->st_flags);
++ __put_user(host_st->st_gen, &target_st->st_gen);
++ /* st_lspare not used */
++ __put_user(host_st->st_birthtim.tv_sec, &target_st->st_birthtim.tv_sec);
++ __put_user(host_st->st_birthtim.tv_nsec,
++ &target_st->st_birthtim.tv_nsec);
++ unlock_user_struct(target_st, target_addr, 1);
++
++ return (0);
++}
++
++static inline abi_long
++do_getfh(const char *path, abi_ulong target_addr)
++{
++ abi_long ret;
++ fhandle_t host_fh;
++
++ ret = get_errno(getfh(path, &host_fh));
++ if (ret)
++ return (ret);
++
++ return (host_to_target_fhandle(target_addr, &host_fh));
++}
++
++static inline abi_long
++do_lgetfh(const char *path, abi_ulong target_addr)
++{
++ abi_long ret;
++ fhandle_t host_fh;
++
++ ret = get_errno(lgetfh(path, &host_fh));
++ if (ret)
++ return (ret);
++
++ return (host_to_target_fhandle(target_addr, &host_fh));
++}
++
++static inline abi_long
++do_fhopen(abi_ulong target_addr, int flags)
++{
++ abi_long ret;
++ fhandle_t host_fh;
++
++ ret = target_to_host_fhandle(&host_fh, target_addr);
++ if (ret)
++ return (ret);
++
++ return (get_errno(fhopen(&host_fh, flags)));
++}
++
++static inline abi_long
++do_fhstat(abi_ulong target_fhp_addr, abi_ulong target_sb_addr)
++{
++ abi_long ret;
++ fhandle_t host_fh;
++ struct stat host_sb;
++
++ ret = target_to_host_fhandle(&host_fh, target_fhp_addr);
++ if (ret)
++ return (ret);
++
++ ret = get_errno(fhstat(&host_fh, &host_sb));
++ if (ret)
++ return (ret);
++
++ return (host_to_target_stat(target_sb_addr, &host_sb));
++}
++
++static inline abi_long
++do_fhstatfs(abi_ulong target_fhp_addr, abi_ulong target_stfs_addr)
++{
++ abi_long ret;
++ fhandle_t host_fh;
++ struct statfs host_stfs;
++
++ ret = target_to_host_fhandle(&host_fh, target_fhp_addr);
++ if (ret)
++ return (ret);
++
++ ret = get_errno(fhstatfs(&host_fh, &host_stfs));
++ if (ret)
++ return (ret);
++
++ return (host_to_target_statfs(target_stfs_addr, &host_stfs));
++}
++
++static inline abi_long
++do_statfs(const char *path, abi_ulong target_addr)
++{
++ abi_long ret;
++ struct statfs host_stfs;
++
++ ret = get_errno(statfs(path, &host_stfs));
++ if (ret)
++ return (ret);
++
++ return (host_to_target_statfs(target_addr, &host_stfs));
++}
++
++static inline abi_long
++do_fstatfs(int fd, abi_ulong target_addr)
++{
++ abi_long ret;
++ struct statfs host_stfs;
++
++ ret = get_errno(fstatfs(fd, &host_stfs));
++ if (ret)
++ return (ret);
++
++ return (host_to_target_statfs(target_addr, &host_stfs));
++}
++
++static inline abi_long
++do_getfsstat(abi_ulong target_addr, abi_long bufsize, int flags)
++{
++ abi_long ret;
++ struct statfs *host_stfs;
++ int count;
++ long host_bufsize;
++
++ count = bufsize / sizeof(struct target_statfs);
++
++ /* if user buffer is NULL then return number of mounted FS's */
++ if (0 == target_addr || 0 == count)
++ return (get_errno(getfsstat(NULL, 0, flags)));
++
++ /* XXX check count to be reasonable */
++ host_bufsize = sizeof(struct statfs) * count;
++ host_stfs = alloca(host_bufsize);
++ if (! host_stfs)
++ return (-TARGET_EINVAL);
++
++ ret = count = get_errno(getfsstat(host_stfs, host_bufsize, flags));
++ if (ret < 0)
++ return (ret);
++
++ while (count--)
++ if (host_to_target_statfs(
++ (target_addr + (count * sizeof(struct target_statfs))),
++ &host_stfs[count]))
++ return (-TARGET_EFAULT);
++
++ return (ret);
++}
++
++static abi_long
++do_uuidgen(abi_ulong target_addr, int count)
++{
++ int i;
++ abi_long ret;
++ struct uuid *host_uuid;
++
++ if (count < 1 || count > 2048)
++ return (-TARGET_EINVAL);
++
++ host_uuid = (struct uuid *)g_malloc(count * sizeof(struct uuid));
++
++ if (NULL == host_uuid)
++ return (-TARGET_EINVAL);
++
++ ret = get_errno(uuidgen(host_uuid, count));
++ if (ret)
++ goto out;
++ for(i = 0; i < count; i++) {
++ ret = host_to_target_uuid(target_addr +
++ (abi_ulong)(sizeof(struct target_uuid) * i), &host_uuid[i]);
++ if (ret)
++ goto out;
++ }
++
++out:
++ g_free(host_uuid);
++ return (ret);
++}
++
++static abi_long
++do_adjtime(abi_ulong target_delta_addr, abi_ulong target_old_addr)
++{
++ abi_long ret;
++ struct timeval host_delta, host_old;
++
++ ret = target_to_host_timeval(&host_delta, target_delta_addr);
++ if (ret)
++ goto out;
++
++ if (target_old_addr) {
++ ret = get_errno(adjtime(&host_delta, &host_old));
++ if (ret)
++ goto out;
++ ret = host_to_target_timeval(&host_old, target_old_addr);
++ } else
++ ret = get_errno(adjtime(&host_delta, NULL));
++
++out:
++ return (ret);
++}
++
++static abi_long
++do_ntp_adjtime(abi_ulong target_tx_addr)
++{
++ abi_long ret;
++ struct timex host_tx;
++
++ ret = target_to_host_timex(&host_tx, target_tx_addr);
++ if (ret)
++ goto out;
++
++ ret = get_errno(ntp_adjtime(&host_tx));
++
++out:
++ return (ret);
++}
++
++static abi_long
++do_ntp_gettime(abi_ulong target_ntv_addr)
++{
++ abi_long ret;
++ struct ntptimeval host_ntv;
++
++ ret = get_errno(ntp_gettime(&host_ntv));
++ if (ret)
++ goto out;
++
++ ret = host_to_target_ntptimeval(target_ntv_addr, &host_ntv);
++out:
++ return (ret);
++}
++
++/*
++ * ioctl()
++ */
++
++static const bitmask_transtbl iflag_tbl[] = {
++ { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
++ { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
++ { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
++ { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
++ { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
++ { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
++ { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
++ { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
++ { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
++ { TARGET_IXON, TARGET_IXON, IXON, IXON },
++ { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
++#ifdef IXANY
++ { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
++#endif
++#ifdef IMAXBEL
++ { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
++#endif
++ { 0, 0, 0, 0 }
++};
++
++static const bitmask_transtbl oflag_tbl[] = {
++ { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
++#ifdef ONLCR
++ { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
++#endif
++#ifdef TABDLY
++ { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
++ { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
++#endif
++#ifdef ONOEOT
++ { TARGET_ONOEOT, TARGET_ONOEOT, ONOEOT, ONOEOT },
++#endif
++#ifdef OCRNL
++ { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
++#endif
++#ifdef ONOCR
++ { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
++#endif
++#ifdef ONLRET
++ { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
++#endif
++ { 0, 0, 0, 0 }
++};
++
++static const bitmask_transtbl cflag_tbl[] = {
++#ifdef CIGNORE
++ { TARGET_CIGNORE, TARGET_CIGNORE, CIGNORE, CIGNORE },
++#endif
++ { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
++ { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
++ { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
++ { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
++ { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
++ { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
++ { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
++ { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
++ { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
++ { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
++#ifdef CCTS_OFLOW
++ { TARGET_CCTS_OFLOW, TARGET_CCTS_OFLOW, CCTS_OFLOW, CCTS_OFLOW },
++#endif
++#ifdef CRTSCTS
++ { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
++#endif
++#ifdef CRTS_IFLOW
++ { TARGET_CRTS_IFLOW, TARGET_CRTS_IFLOW, CRTS_IFLOW, CRTS_IFLOW },
++#endif
++#ifdef CDTS_IFLOW
++ { TARGET_CDTR_IFLOW, TARGET_CDTR_IFLOW, CDTR_IFLOW, CDTR_IFLOW },
++#endif
++#ifdef CDSR_OFLOW
++ { TARGET_CDSR_OFLOW, TARGET_CDSR_OFLOW, CDSR_OFLOW, CDSR_OFLOW },
++#endif
++#ifdef CCAR_OFLOW
++ { TARGET_CCAR_OFLOW, TARGET_CCAR_OFLOW, CCAR_OFLOW, CCAR_OFLOW },
++#endif
++ { 0, 0, 0, 0 }
++};
++
++static const bitmask_transtbl lflag_tbl[] = {
++#ifdef ECHOKE
++ { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
++#endif
++ { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
++ { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
++ { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
++ { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
++#ifdef ECHOPRT
++ { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
++#endif
++#ifdef ECHOCTL
++ { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
++#endif
++ { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
++ { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
++#ifdef ALTWERASE
++ { TARGET_ALTWERASE, TARGET_ALTWERASE, ALTWERASE, ALTWERASE },
++#endif
++ { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
++ { TARGET_EXTPROC, TARGET_EXTPROC, EXTPROC, EXTPROC },
++ { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
++#ifdef FLUSHO
++ { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
++#endif
++#ifdef NOKERNINFO
++ { TARGET_NOKERNINFO, TARGET_NOKERNINFO, NOKERNINFO, NOKERNINFO },
++#endif
++#ifdef PENDIN
++ { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
++#endif
++ { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
++ { 0, 0, 0, 0 }
++};
++
++static void
++target_to_host_termios(void *dst, const void *src)
++{
++ struct termios *host = dst;
++ const struct target_termios *target = src;
++
++ host->c_iflag =
++ target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
++ host->c_oflag =
++ target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
++ host->c_cflag =
++ target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
++ host->c_lflag =
++ target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
++
++ memset(host->c_cc, 0, sizeof(host->c_cc));
++ host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
++ host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
++#ifdef VEOL2
++ host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
++#endif
++ host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
++#ifdef VWERASE
++ host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
++#endif
++ host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
++#ifdef VREPRINT
++ host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
++#endif
++#ifdef VERASE2
++ host->c_cc[VERASE2] = target->c_cc[TARGET_VERASE2];
++#endif
++ host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
++ host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
++ host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
++#ifdef VDSUSP
++ host->c_cc[VDSUSP] = target->c_cc[TARGET_VDSUSP];
++#endif
++ host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
++ host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
++#ifdef VLNEXT
++ host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
++#endif
++#ifdef VDISCARD
++ host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
++#endif
++ host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
++ host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
++#ifdef VSTATUS
++ host->c_cc[VSTATUS] = target->c_cc[TARGET_VSTATUS];
++#endif
++
++ host->c_ispeed = tswap32(target->c_ispeed);
++ host->c_ospeed = tswap32(target->c_ospeed);
++}
++
++static void
++host_to_target_termios(void *dst, const void *src)
++{
++ struct target_termios *target = dst;
++ const struct termios *host = src;
++
++ target->c_iflag =
++ tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
++ target->c_oflag =
++ tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
++ target->c_cflag =
++ tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
++ target->c_lflag =
++ tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
++
++ memset(target->c_cc, 0, sizeof(target->c_cc));
++ target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
++ target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
++#ifdef VEOL2
++ target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
++#endif
++ target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
++#ifdef VWERASE
++ target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
++#endif
++ target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
++#ifdef VREPRINT
++ target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
++#endif
++#ifdef VERASE2
++ target->c_cc[TARGET_VERASE2] = host->c_cc[VERASE2];
++#endif
++ target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
++ target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
++ target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
++#ifdef VDSUSP
++ target->c_cc[TARGET_VDSUSP] = host->c_cc[VDSUSP];
++#endif
++ target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
++ target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
++#ifdef VLNEXT
++ target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
++#endif
++#ifdef VDISCARD
++ target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
++#endif
++ target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
++ target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
++#ifdef VSTATUS
++ target->c_cc[TARGET_VSTATUS] = host->c_cc[VSTATUS];
++#endif
++
++ target->c_ispeed = tswap32(host->c_ispeed);
++ target->c_ospeed = tswap32(host->c_ospeed);
++}
++
++static const StructEntry struct_termios_def = {
++ .convert = { host_to_target_termios, target_to_host_termios },
++ .size = { sizeof(struct target_termios), sizeof(struct termios) },
++ .align = { __alignof__(struct target_termios),
++ __alignof__(struct termios) },
++};
++
++/* kernel structure types definitions */
++
++#define STRUCT(name, ...) STRUCT_ ## name,
++#define STRUCT_SPECIAL(name) STRUCT_ ## name,
++enum {
++#ifdef __FreeBSD__
++#include "freebsd/syscall_types.h"
++#else
++#warning No syscall_types.h
++#endif
++};
++#undef STRUCT
++#undef STRUCT_SPECIAL
++
++#define STRUCT(name, ...) \
++ static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
++#define STRUCT_SPECIAL(name)
++#ifdef __FreeBSD__
++#include "freebsd/syscall_types.h"
++#else
++#warning No syscall_types.h
++#endif
++#undef STRUCT
++#undef STRUCT_SPECIAL
++
++typedef struct IOCTLEntry IOCTLEntry;
++
++typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
++ int fd, abi_long cmd, abi_long arg);
++
++struct IOCTLEntry {
++ unsigned int target_cmd;
++ unsigned int host_cmd;
++ const char *name;
++ int access;
++ do_ioctl_fn *do_ioctl;
++ const argtype arg_type[5];
++};
++
++#define MAX_STRUCT_SIZE 4096
++
++static IOCTLEntry ioctl_entries[] = {
++#define IOC_ 0x0000
++#define IOC_R 0x0001
++#define IOC_W 0x0002
++#define IOC_RW (IOC_R | IOC_W)
++#define IOCTL(cmd, access, ...) \
++ { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
++#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
++ { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
++#ifdef __FreeBSD__
++#include "freebsd/ioctl.h"
++#else
++#warning No ioctl.h
++#endif
++ { 0, 0 },
++};
++
++static abi_long
++do_ioctl(int fd, abi_long cmd, abi_long arg)
++{
++ const IOCTLEntry *ie;
++ const argtype *arg_type;
++ abi_long ret;
++ uint8_t buf_temp[MAX_STRUCT_SIZE];
++ int target_size;
++ void *argptr;
++
++ ie = ioctl_entries;
++ for(;;) {
++ if (0 == ie->target_cmd) {
++ gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
++ return (-TARGET_ENOSYS);
++ }
++ if (ie->target_cmd == cmd)
++ break;
++ ie++;
++ }
++ arg_type = ie->arg_type;
++#if defined(DEBUG)
++ gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
++#endif
++ if (ie->do_ioctl) {
++ return (ie->do_ioctl(ie, buf_temp, fd, cmd, arg));
++ }
++
++ switch(arg_type[0]) {
++ case TYPE_NULL:
++ /* no argument */
++ ret = get_errno(ioctl(fd, ie->host_cmd));
++ break;
++
++ case TYPE_PTRVOID:
++ case TYPE_INT:
++ /* int argument */
++ ret = get_errno(ioctl(fd, ie->host_cmd, arg));
++ break;
++
++ case TYPE_PTR:
++ arg_type++;
++ target_size = thunk_type_size(arg_type, 0);
++ switch(ie->access) {
++ case IOC_R:
++ ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
++ if (!is_error(ret)) {
++ argptr = lock_user(VERIFY_WRITE, arg,
++ target_size, 0);
++ if (!argptr)
++ return (-TARGET_EFAULT);
++ thunk_convert(argptr, buf_temp, arg_type,
++ THUNK_TARGET);
++ unlock_user(argptr, arg, target_size);
++ }
++ break;
++
++ case IOC_W:
++ argptr = lock_user(VERIFY_READ, arg, target_size, 1);
++ if (!argptr)
++ return (-TARGET_EFAULT);
++ thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
++ unlock_user(argptr, arg, 0);
++ ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
++
++ case IOC_RW:
++ default:
++ argptr = lock_user(VERIFY_READ, arg, target_size, 1);
++ if (!argptr)
++ return (-TARGET_EFAULT);
++ thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
++ unlock_user(argptr, arg, 0);
++ ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
++ if (!is_error(ret)) {
++ argptr = lock_user(VERIFY_WRITE, arg,
++ target_size, 0);
++ if (!argptr)
++ return (-TARGET_EFAULT);
++ thunk_convert(argptr, buf_temp, arg_type,
++ THUNK_TARGET);
++ unlock_user(argptr, arg, target_size);
++ }
++ break;
++ }
++ break;
++
++ default:
++ gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
++ (long)cmd, arg_type[0]);
++ ret = -TARGET_ENOSYS;
++ break;
++ }
++ return (ret);
++}
++
++/* 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>. */
++abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
++ abi_long arg2, abi_long arg3, abi_long arg4,
++ abi_long arg5, abi_long arg6, abi_long arg7,
++ abi_long arg8)
++{
++ abi_long ret;
++ void *p;
++
++#ifdef DEBUG
++ gemu_log("freebsd syscall %d\n", num);
++#endif
++ if(do_strace)
++ print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
++
++ switch(num) {
++ case TARGET_FREEBSD_NR_exit:
++#ifdef TARGET_GPROF
++ _mcleanup();
++#endif
++ gdb_exit(cpu_env, arg1);
++ /* XXX: should free thread stack and CPU env */
++ _exit(arg1);
++ ret = 0; /* avoid warning */
++ break;
++ case TARGET_FREEBSD_NR_read:
++ if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
++ goto efault;
++ ret = get_errno(read(arg1, p, arg3));
++ unlock_user(p, arg2, ret);
++ break;
++
++ case TARGET_FREEBSD_NR_readv:
++ {
++ int count = arg3;
++ struct iovec *vec;
++
++ vec = alloca(count * sizeof(struct iovec));
++ if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
++ goto efault;
++ ret = get_errno(readv(arg1, vec, count));
++ unlock_iovec(vec, arg2, count, 1);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_pread:
++ if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
++ goto efault;
++ ret = get_errno(pread(arg1, p, arg3, target_offset64(arg4, arg5)));
++ unlock_user(p, arg2, ret);
++ break;
++
++ case TARGET_FREEBSD_NR_preadv:
++ {
++ int count = arg3;
++ struct iovec *vec;
++
++ vec = alloca(count * sizeof(struct iovec));
++ if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
++ goto efault;
++ ret = get_errno(preadv(arg1, vec, count,
++ target_offset64(arg4, arg5)));
++ unlock_iovec(vec, arg2, count, 1);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_write:
++ if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
++ goto efault;
++ ret = get_errno(write(arg1, p, arg3));
++ unlock_user(p, arg2, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_writev:
++ {
++ int count = arg3;
++ struct iovec *vec;
++
++ vec = alloca(count * sizeof(struct iovec));
++ if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
++ goto efault;
++ ret = get_errno(writev(arg1, vec, count));
++ unlock_iovec(vec, arg2, count, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_pwrite:
++ if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
++ goto efault;
++ ret = get_errno(pwrite(arg1, p, arg3, target_offset64(arg4, arg5)));
++ unlock_user(p, arg2, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_pwritev:
++ {
++ int count = arg3;
++ struct iovec *vec;
++
++ vec = alloca(count * sizeof(struct iovec));
++ if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
++ goto efault;
++ ret = get_errno(pwritev(arg1, vec, count,
++ target_offset64(arg4, arg5)));
++ unlock_iovec(vec, arg2, count, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_open:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(open(path(p),
++ target_to_host_bitmask(arg2, fcntl_flags_tbl),
++ arg3));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_openat:
++ if (!(p = lock_user_string(arg2)))
++ goto efault;
++ ret = get_errno(openat(arg1, path(p),
++ target_to_host_bitmask(arg3, fcntl_flags_tbl),
++ arg4));
++ unlock_user(p, arg2, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_close:
++ ret = get_errno(close(arg1));
++ break;
++
++ case TARGET_FREEBSD_NR_closefrom:
++ ret = 0;
++ closefrom(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_revoke:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(revoke(p));
++ unlock_user(p, arg1, 0);
++ break;
++
++#ifdef TARGET_FREEBSD_NR_creat
++ case TARGET_FREEBSD_NR_creat:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(creat(p, arg2));
++ unlock_user(p, arg1, 0);
++ break;
++#endif
++
++ case TARGET_FREEBSD_NR_mmap:
++ ret = get_errno(target_mmap(arg1, arg2, arg3,
++ target_to_host_bitmask(arg4, mmap_flags_tbl),
++ arg5,
++ arg6));
++ break;
++
++ case TARGET_FREEBSD_NR_munmap:
++ ret = get_errno(target_munmap(arg1, arg2));
++ break;
++
++ case TARGET_FREEBSD_NR_mprotect:
++ ret = get_errno(target_mprotect(arg1, arg2, arg3));
++ break;
++
++ case TARGET_FREEBSD_NR_msync:
++ ret = get_errno(msync(g2h(arg1), arg2, arg3));
++ break;
++
++ case TARGET_FREEBSD_NR_mlock:
++ ret = get_errno(mlock(g2h(arg1), arg2));
++ break;
++
++ case TARGET_FREEBSD_NR_munlock:
++ ret = get_errno(munlock(g2h(arg1), arg2));
++ break;
++
++ case TARGET_FREEBSD_NR_mlockall:
++ ret = get_errno(mlockall(arg1));
++ break;
++
++ case TARGET_FREEBSD_NR_munlockall:
++ ret = get_errno(munlockall());
++ break;
++
++ case TARGET_FREEBSD_NR_madvise:
++ /*
++ * A straight passthrough may not be safe because qemu sometimes
++ * turns private file-backed mapping into anonymous mappings. This
++ * will break MADV_DONTNEED. This is a hint, so ignoring and returing
++ * success is ok.
++ */
++ ret = get_errno(0);
++ break;
++
++ case TARGET_FREEBSD_NR_break:
+ ret = do_obreak(arg1);
+ break;
+ #ifdef __FreeBSD__
+@@ -2727,18 +4206,30 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ break;
+
+ case TARGET_FREEBSD_NR_stat:
+- if (!(p = lock_user_string(arg1)))
+- goto efault;
+- ret = get_errno(stat(path(p), &st));
+- unlock_user(p, arg1, 0);
+- goto do_stat;
++ {
++ struct stat st;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(stat(path(p), &st));
++ unlock_user(p, arg1, 0);
++ if (0 == ret)
++ ret = host_to_target_stat(arg2, &st);
++ }
++ break;
+
+ case TARGET_FREEBSD_NR_lstat:
+- if (!(p = lock_user_string(arg1)))
+- goto efault;
+- ret = get_errno(lstat(path(p), &st));
+- unlock_user(p, arg1, 0);
+- goto do_stat;
++ {
++ struct stat st;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(lstat(path(p), &st));
++ unlock_user(p, arg1, 0);
++ if (0 == ret)
++ ret = host_to_target_stat(arg2, &st);
++ }
++ break;
+
+ case TARGET_FREEBSD_NR_nstat:
+ case TARGET_FREEBSD_NR_nfstat:
+@@ -2747,42 +4238,11 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ break;
+
+ case TARGET_FREEBSD_NR_fstat:
+- {
+- ret = get_errno(fstat(arg1, &st));
+-
+-do_stat:
+- if (!is_error(ret)) {
+- struct target_freebsd_stat *target_st;
+-
+- if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
+- goto efault;
+- memset(target_st, 0, sizeof(*target_st));
+- __put_user(st.st_dev, &target_st->st_dev);
+- __put_user(st.st_ino, &target_st->st_ino);
+- __put_user(st.st_mode, &target_st->st_mode);
+- __put_user(st.st_nlink, &target_st->st_nlink);
+- __put_user(st.st_uid, &target_st->st_uid);
+- __put_user(st.st_gid, &target_st->st_gid);
+- __put_user(st.st_rdev, &target_st->st_rdev);
+- __put_user(st.st_atim.tv_sec, &target_st->st_atim.tv_sec);
+- __put_user(st.st_atim.tv_nsec, &target_st->st_atim.tv_nsec);
+- __put_user(st.st_mtim.tv_sec, &target_st->st_mtim.tv_sec);
+- __put_user(st.st_mtim.tv_nsec, &target_st->st_mtim.tv_nsec);
+- __put_user(st.st_ctim.tv_sec, &target_st->st_ctim.tv_sec);
+- __put_user(st.st_ctim.tv_nsec, &target_st->st_ctim.tv_nsec);
+- __put_user(st.st_size, &target_st->st_size);
+- __put_user(st.st_blocks, &target_st->st_blocks);
+- __put_user(st.st_blksize, &target_st->st_blksize);
+- __put_user(st.st_flags, &target_st->st_flags);
+- __put_user(st.st_gen, &target_st->st_gen);
+- /* st_lspare not used */
+- __put_user(st.st_birthtim.tv_sec,
+- &target_st->st_birthtim.tv_sec);
+- __put_user(st.st_birthtim.tv_nsec,
+- &target_st->st_birthtim.tv_nsec);
+- unlock_user_struct(target_st, arg2, 1);
+- }
+-
++ {
++ struct stat st;
++ ret = get_errno(fstat(arg1, &st));
++ if (! ret)
++ ret = host_to_target_stat(arg2, &st);
+ }
+ break;
+
+@@ -2845,7 +4305,7 @@ do_stat:
+ }
+ ret = get_errno(gettimeofday(&tv, arg2 != 0 ? &tz : NULL));
+ if (!is_error(ret)) {
+- if (fbsd_copy_to_user_timeval(&tv, arg1))
++ if (host_to_target_timeval(&tv, arg1))
+ goto efault;
+ }
+ }
+@@ -2864,7 +4324,7 @@ do_stat:
+ __get_user(tz.tz_dsttime, &target_tz->tz_dsttime);
+ unlock_user_struct(target_tz, arg2, 1);
+ }
+- if (copy_from_user_timeval(&tv, arg1))
++ if (target_to_host_timeval(&tv, arg1))
+ goto efault;
+ ret = get_errno(settimeofday(&tv, arg2 != 0 ? & tz : NULL));
+ }
+@@ -3155,8 +4615,8 @@ do_stat:
+
+ if (arg2) {
+ pvalue = &value;
+- if (copy_from_user_timeval(&pvalue->it_interval,
+- arg2) || copy_from_user_timeval(
++ if (target_to_host_timeval(&pvalue->it_interval,
++ arg2) || target_to_host_timeval(
+ &pvalue->it_value, arg2 +
+ sizeof(struct target_timeval)))
+ goto efault;
+@@ -3165,8 +4625,8 @@ do_stat:
+ }
+ ret = get_errno(setitimer(arg1, pvalue, &ovalue));
+ if (!is_error(ret) && arg3) {
+- if (fbsd_copy_to_user_timeval(&ovalue.it_interval, arg3)
+- || fbsd_copy_to_user_timeval(&ovalue.it_value,
++ if (host_to_target_timeval(&ovalue.it_interval, arg3)
++ || host_to_target_timeval(&ovalue.it_value,
+ arg3 + sizeof(struct target_timeval)))
+ goto efault;
+ }
+@@ -3179,8 +4639,8 @@ do_stat:
+
+ ret = get_errno(getitimer(arg1, &value));
+ if (!is_error(ret) && arg2) {
+- if (fbsd_copy_to_user_timeval(&value.it_interval, arg2)
+- || fbsd_copy_to_user_timeval(&value.it_value,
++ if (host_to_target_timeval(&value.it_interval, arg2)
++ || host_to_target_timeval(&value.it_value,
+ arg2 + sizeof(struct target_timeval)))
+ goto efault;
+ }
+@@ -3192,8 +4652,8 @@ do_stat:
+ struct timeval *tvp, tv[2];
+
+ if (arg2) {
+- if (copy_from_user_timeval(&tv[0], arg2)
+- || copy_from_user_timeval(&tv[1],
++ if (target_to_host_timeval(&tv[0], arg2)
++ || target_to_host_timeval(&tv[1],
+ arg2 + sizeof(struct target_timeval)))
+
+ goto efault;
+@@ -3213,8 +4673,8 @@ do_stat:
+ struct timeval *tvp, tv[2];
+
+ if (arg2) {
+- if (copy_from_user_timeval(&tv[0], arg2)
+- || copy_from_user_timeval(&tv[1],
++ if (target_to_host_timeval(&tv[0], arg2)
++ || target_to_host_timeval(&tv[1],
+ arg2 + sizeof(struct target_timeval)))
+
+ goto efault;
+@@ -3234,8 +4694,8 @@ do_stat:
+ struct timeval *tvp, tv[2];
+
+ if (arg2) {
+- if (copy_from_user_timeval(&tv[0], arg2)
+- || copy_from_user_timeval(&tv[1],
++ if (target_to_host_timeval(&tv[0], arg2)
++ || target_to_host_timeval(&tv[1],
+ arg2 + sizeof(struct target_timeval)))
+ goto efault;
+ tvp = tv;
+@@ -3251,8 +4711,8 @@ do_stat:
+ struct timeval *tvp, tv[2];
+
+ if (arg3) {
+- if (copy_from_user_timeval(&tv[0], arg3)
+- || copy_from_user_timeval(&tv[1],
++ if (target_to_host_timeval(&tv[0], arg3)
++ || target_to_host_timeval(&tv[1],
+ arg3 + sizeof(struct target_timeval)))
+ goto efault;
+ tvp = tv;
+@@ -4024,6 +5484,10 @@ do_stat:
+ ret = do_socketpair(arg1, arg2, arg3, arg4);
+ break;
+
++ case TARGET_FREEBSD_NR_shutdown:
++ ret = get_errno(shutdown(arg1, arg2));
++ break;
++
+ case TARGET_FREEBSD_NR_getpriority:
+ /*
+ * Note that negative values are valid for getpriority, so we must
+@@ -4165,8 +5629,31 @@ do_stat:
+ break;
+
+ case TARGET_FREEBSD_NR_getresuid:
++ {
++ uid_t ruid, euid, suid;
++
++ ret = get_errno(getresuid(&ruid, &euid, &suid));
++ if (put_user_s32(ruid, arg1))
++ goto efault;
++ if (put_user_s32(euid, arg2))
++ goto efault;
++ if (put_user_s32(suid, arg3))
++ goto efault;
++ }
++ break;
++
+ case TARGET_FREEBSD_NR_getresgid:
+- ret = unimplemented(num);
++ {
++ gid_t rgid, egid, sgid;
++
++ ret = get_errno(getresgid(&rgid, &egid, &sgid));
++ if (put_user_s32(rgid, arg1))
++ goto efault;
++ if (put_user_s32(egid, arg2))
++ goto efault;
++ if (put_user_s32(sgid, arg3))
++ goto efault;
++ }
+ break;
+
+ case TARGET_FREEBSD_NR_setsid:
+@@ -4679,7 +6166,7 @@ do_stat:
+ long tid;
+
+ thr_self(&tid);
+- ret = do_umtx_lock(arg1, tswap32(tid));
++ ret = do_lock_umtx(arg1, tid, NULL);
+ }
+ break;
+
+@@ -4688,72 +6175,238 @@ do_stat:
+ long tid;
+
+ thr_self(&tid);
+- ret = do_umtx_unlock(arg1, tswap32(tid));
++ ret = do_unlock_umtx(arg1, tid);
+ }
+ break;
+
+ case TARGET_FREEBSD_NR__umtx_op:
+ {
+ struct timespec ts;
+- void *object = NULL;
+- int operation;
+- void *addr = NULL;
+- void *addr2 = NULL;
+-
++ long tid;
+
+ /* int _umtx_op(void *obj, int op, u_long val,
+- * void *uaddr, void *uaddr2); */
++ * void *uaddr, void *target_ts); */
+
+ abi_ulong obj = arg1;
+ int op = (int)arg2;
+ u_long val = arg3;
+- /* abi_ulong uaddr = arg4; */
+- abi_ulong uaddr2 = arg5;
++ abi_ulong uaddr = arg4;
++ abi_ulong target_ts = arg5;
+
+ switch(op) {
+ case TARGET_UMTX_OP_LOCK:
+- ret = do_umtx_lock(obj, tswap32((uint32_t)val));
++ thr_self(&tid);
++ if (target_ts) {
++ if (target_to_host_timespec(&ts, target_ts))
++ goto efault;
++ ret = do_lock_umtx(obj, tid, &ts);
++ } else
++ ret = do_lock_umtx(obj, tid, NULL);
+ break;
+
+ case TARGET_UMTX_OP_UNLOCK:
+- ret = do_umtx_unlock(obj, tswap32((uint32_t)val));
++ thr_self(&tid);
++ ret = do_unlock_umtx(obj, tid);
+ break;
+
+ case TARGET_UMTX_OP_WAIT:
+- if (uaddr2) {
+- if (target_to_host_timespec(&ts, uaddr2))
++ /* args: obj *, val, ts * */
++ if (target_ts) {
++ if (target_to_host_timespec(&ts, target_ts))
+ goto efault;
+- addr2 = (void *)&ts;
+- }
+- ret = get_errno(_umtx_op(g2h(obj), UMTX_OP_WAIT,
+- tswap32(val), addr, addr2));
+- break;
++ ret = do_umtx_op_wait(obj, tswapal(val), &ts);
++ } else
++ ret = do_umtx_op_wait(obj, tswapal(val), NULL);
++ break;
+
+ case TARGET_UMTX_OP_WAKE:
+- operation = UMTX_OP_WAKE;
+- object = g2h(obj);
+- ret = get_errno(_umtx_op(g2h(obj), UMTX_OP_WAKE,
+- val, 0, 0));
++ /* args: obj *, nr_wakeup */
++ ret = do_umtx_op_wake(obj, val);
+ break;
+
+- case TARGET_UMTX_OP_MUTEX_TRYLOCK:
+ case TARGET_UMTX_OP_MUTEX_LOCK:
++ thr_self(&tid);
++ if (target_ts) {
++ if (target_to_host_timespec(&ts, target_ts))
++ goto efault;
++ ret = do_lock_umutex(obj, tid, &ts, 0);
++ } else {
++ ret = do_lock_umutex(obj, tid, NULL, 0);
++ }
++ break;
++
+ case TARGET_UMTX_OP_MUTEX_UNLOCK:
++ thr_self(&tid);
++ ret = do_unlock_umutex(obj, tid);
++ break;
++
++ case TARGET_UMTX_OP_MUTEX_TRYLOCK:
++ thr_self(&tid);
++ ret = do_lock_umutex(obj, tid, NULL, TARGET_UMUTEX_TRY);
++ break;
++
++ case TARGET_UMTX_OP_MUTEX_WAIT:
++ thr_self(&tid);
++ if (target_ts) {
++ if (target_to_host_timespec(&ts, target_ts))
++ goto efault;
++ ret = do_lock_umutex(obj, tid, &ts,
++ TARGET_UMUTEX_WAIT);
++ } else {
++ ret = do_lock_umutex(obj, tid, NULL,
++ TARGET_UMUTEX_WAIT);
++ }
++ break;
++
++ case TARGET_UMTX_OP_MUTEX_WAKE:
++ /* Don't need to do access_ok(). */
++ ret = get_errno(_umtx_op(g2h(obj), UMTX_OP_MUTEX_WAKE,
++ val, NULL, NULL));
++ break;
++
+ case TARGET_UMTX_OP_SET_CEILING:
++ ret = 0; /* XXX quietly ignore these things for now */
++ break;
++
+ case TARGET_UMTX_OP_CV_WAIT:
++ /*
++ * Initialization of the struct conv is done by
++ * bzero'ing everything in userland.
++ */
++ if (target_ts) {
++ if (target_to_host_timespec(&ts, target_ts))
++ goto efault;
++ ret = do_cv_wait(obj, uaddr, &ts, val);
++ } else {
++ ret = do_cv_wait(obj, uaddr, NULL, val);
++ }
++ break;
++
+ case TARGET_UMTX_OP_CV_SIGNAL:
++ /*
++ * XXX
++ * User code may check if c_has_waiters is zero. Other
++ * than that it is assume that user code doesn't do
++ * much with the struct conv fields and is pretty
++ * much opauque to userland.
++ */
++ ret = do_cv_signal(obj);
++ break;
++
+ case TARGET_UMTX_OP_CV_BROADCAST:
++ /*
++ * XXX
++ * User code may check if c_has_waiters is zero. Other
++ * than that it is assume that user code doesn't do
++ * much with the struct conv fields and is pretty
++ * much opauque to userland.
++ */
++ ret = do_cv_broadcast(obj);
++ break;
++
+ case TARGET_UMTX_OP_WAIT_UINT:
++ if (! access_ok(VERIFY_READ, obj, sizeof(abi_ulong)))
++ goto efault;
++ if (target_ts) {
++ if (target_to_host_timespec(&ts, target_ts))
++ goto efault;
++ ret = get_errno(_umtx_op(g2h(obj),
++ UMTX_OP_WAIT_UINT,
++ tswap32((uint32_t)val), NULL, &ts));
++ } else
++ ret = get_errno(_umtx_op(g2h(obj),
++ UMTX_OP_WAIT_UINT,
++ tswap32((uint32_t)val), NULL, NULL));
++
++ break;
++
++ case TARGET_UMTX_OP_WAIT_UINT_PRIVATE:
++ if (! access_ok(VERIFY_READ, obj, sizeof(abi_ulong)))
++ goto efault;
++ if (target_ts) {
++ if (target_to_host_timespec(&ts, target_ts))
++ goto efault;
++ ret = get_errno(_umtx_op(g2h(obj),
++ UMTX_OP_WAIT_UINT_PRIVATE,
++ tswap32((uint32_t)val), NULL, &ts));
++ } else
++ ret = get_errno(_umtx_op(g2h(obj),
++ UMTX_OP_WAIT_UINT_PRIVATE,
++ tswap32((uint32_t)val), NULL, NULL));
++
++ break;
++
++ case TARGET_UMTX_OP_WAKE_PRIVATE:
++ /* Don't need to do access_ok(). */
++ ret = get_errno(_umtx_op(g2h(obj), UMTX_OP_WAKE_PRIVATE,
++ val, NULL, NULL));
++ break;
++
++ case TARGET_UMTX_OP_NWAKE_PRIVATE:
++ if (! access_ok(VERIFY_READ, obj,
++ val * sizeof(uint32_t)))
++ goto efault;
++ ret = get_errno(_umtx_op(g2h(obj), UMTX_OP_NWAKE_PRIVATE,
++ val, NULL, NULL));
++ break;
++
++
+ case TARGET_UMTX_OP_RW_RDLOCK:
++ if (target_ts) {
++ if (target_to_host_timespec(&ts, target_ts))
++ goto efault;
++ ret = do_rw_rdlock(obj, val, &ts);
++ } else
++ ret = do_rw_rdlock(obj, val, NULL);
++ break;
++
+ case TARGET_UMTX_OP_RW_WRLOCK:
++ if (target_ts) {
++ if (target_to_host_timespec(&ts, target_ts))
++ goto efault;
++ ret = do_rw_wrlock(obj, val, &ts);
++ } else
++ ret = do_rw_wrlock(obj, val, NULL);
++ break;
++
+ case TARGET_UMTX_OP_RW_UNLOCK:
+- case TARGET_UMTX_OP_WAIT_UINT_PRIVATE:
+- case TARGET_UMTX_OP_WAKE_PRIVATE:
+- case TARGET_UMTX_OP_MUTEX_WAIT:
+- case TARGET_UMTX_OP_MUTEX_WAKE:
++ ret = do_rw_unlock(obj);
++ break;
++
++#ifdef UMTX_OP_MUTEX_WAKE2
++ case TARGET_UMTX_OP_MUTEX_WAKE2:
++ if (! access_ok(VERIFY_WRITE, obj,
++ sizeof(struct target_ucond))) {
++ goto efault;
++ }
++ ret = get_errno(_umtx_op(g2h(obj),
++ UMTX_OP_MUTEX_WAKE2, val, NULL, NULL));
++ break;
++#endif
++
+ case TARGET_UMTX_OP_SEM_WAIT:
++ /* XXX Assumes struct _usem is opauque to the user */
++ if (! access_ok(VERIFY_WRITE, obj,
++ sizeof(struct target__usem))) {
++ goto efault;
++ }
++ if (target_ts) {
++ if (target_to_host_timespec(&ts, target_ts))
++ goto efault;
++ ret = get_errno(_umtx_op(g2h(obj),
++ UMTX_OP_SEM_WAIT, 0, NULL, &ts));
++ } else {
++ ret = get_errno(_umtx_op(g2h(obj),
++ UMTX_OP_SEM_WAIT, 0, NULL, NULL));
++ }
++ break;
++
+ case TARGET_UMTX_OP_SEM_WAKE:
+- case TARGET_UMTX_OP_NWAKE_PRIVATE:
++ /* Don't need to do access_ok(). */
++ ret = get_errno(_umtx_op(g2h(obj), UMTX_OP_SEM_WAKE,
++ val, NULL, NULL));
++ break;
++
+ default:
+ ret = -TARGET_EINVAL;
+ break;
+@@ -4761,21 +6414,150 @@ do_stat:
+ }
+ break;
+
++ case TARGET_FREEBSD_NR_getfh:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = do_getfh(path(p), arg2);
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_lgetfh:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = do_lgetfh(path(p), arg2);
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_fhopen:
++ ret = do_fhopen(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_fhstat:
++ ret = do_fhstat(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_fhstatfs:
++ ret = do_fhstatfs(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_getfsstat:
++ ret = do_getfsstat(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_statfs:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = do_statfs(path(p), arg2);
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_fstatfs:
++ ret = do_fstatfs(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_ioctl:
++ ret = do_ioctl(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_kenv:
++ {
++ char *n, *v;
++
++ if (!(n = lock_user_string(arg2)))
++ goto efault;
++ if (!(v = lock_user_string(arg3)))
++ goto efault;
++ ret = get_errno(kenv(arg1, n, v, arg4));
++ unlock_user(v, arg3, 0);
++ unlock_user(n, arg2, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR_swapon:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(swapon(path(p)));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_swapoff:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ ret = get_errno(swapoff(path(p)));
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR_reboot:
++ ret = get_errno(reboot(arg1));
++ break;
++
++ case TARGET_FREEBSD_NR_uuidgen:
++ ret = do_uuidgen(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_mincore:
++ if (!(p = lock_user(VERIFY_WRITE, arg3, arg2, 0)))
++ goto efault;
++ ret = get_errno(mincore(g2h(arg1), arg2, p));
++ unlock_user(p, arg3, ret);
++ break;
++
++ case TARGET_FREEBSD_NR_adjtime:
++ ret = do_adjtime(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_ntp_adjtime:
++ ret = do_ntp_adjtime(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_ntp_gettime:
++ ret = do_ntp_gettime(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_vadvise:
++ ret = -TARGET_EINVAL; /* See sys_ovadvise() in vm_unix.c */
++ break;
++
++ case TARGET_FREEBSD_NR_sbrk:
++ ret = -TARGET_EOPNOTSUPP; /* see sys_sbrk() in vm_mmap.c */
++ break;
++
++ case TARGET_FREEBSD_NR_sstk:
++ ret = -TARGET_EOPNOTSUPP; /* see sys_sstk() in vm_mmap.c */
++ break;
++
+ case TARGET_FREEBSD_NR_yield:
++ case TARGET_FREEBSD_NR_sched_yield:
++ ret = get_errno(sched_yield());
++ break;
++
+ case TARGET_FREEBSD_NR_sched_setparam:
++ ret = do_sched_setparam(arg1, arg2);
++ break;
++
+ case TARGET_FREEBSD_NR_sched_getparam:
++ ret = do_sched_getparam(arg1, arg2);
++ break;
++
+ case TARGET_FREEBSD_NR_sched_setscheduler:
++ ret = do_sched_setscheduler(arg1, arg2, arg3);
++ break;
++
+ case TARGET_FREEBSD_NR_sched_getscheduler:
+- case TARGET_FREEBSD_NR_sched_yield:
++ ret = get_errno(sched_getscheduler(arg1));
++ break;
++
+ case TARGET_FREEBSD_NR_sched_get_priority_max:
+- case TARGET_FREEBSD_NR_sched_get_priority_min:
+- case TARGET_FREEBSD_NR_sched_rr_get_interval:
++ ret = get_errno(sched_get_priority_max(arg1));
++ break;
+
+- case TARGET_FREEBSD_NR_reboot:
+- case TARGET_FREEBSD_NR_shutdown:
++ case TARGET_FREEBSD_NR_sched_get_priority_min:
++ ret = get_errno(sched_get_priority_min(arg1));
++ break;
+
+- case TARGET_FREEBSD_NR_swapon:
+- case TARGET_FREEBSD_NR_swapoff:
++ case TARGET_FREEBSD_NR_sched_rr_get_interval:
++ ret = do_sched_rr_get_interval(arg1, arg2);
++ break;
+
+ case TARGET_FREEBSD_NR_cpuset:
+ case TARGET_FREEBSD_NR_cpuset_getid:
+@@ -4789,22 +6571,10 @@ do_stat:
+ case TARGET_FREEBSD_NR_rctl_remove_rule:
+ case TARGET_FREEBSD_NR_rctl_get_limits:
+
+- case TARGET_FREEBSD_NR_ntp_adjtime:
+- case TARGET_FREEBSD_NR_ntp_gettime:
+-
+ case TARGET_FREEBSD_NR_sctp_peeloff:
+ case TARGET_FREEBSD_NR_sctp_generic_sendmsg:
+ case TARGET_FREEBSD_NR_sctp_generic_recvmsg:
+
+- case TARGET_FREEBSD_NR_getfh:
+- case TARGET_FREEBSD_NR_lgetfh:
+- case TARGET_FREEBSD_NR_fhstatfs:
+- case TARGET_FREEBSD_NR_fhopen:
+- case TARGET_FREEBSD_NR_fhstat:
+-
+- case TARGET_FREEBSD_NR_getfsstat:
+- case TARGET_FREEBSD_NR_fstatfs:
+-
+ case TARGET_FREEBSD_NR_modfnext:
+ case TARGET_FREEBSD_NR_modfind:
+ case TARGET_FREEBSD_NR_kldload:
+@@ -4821,8 +6591,6 @@ do_stat:
+ case TARGET_FREEBSD_NR_quota:
+ #endif
+
+- case TARGET_FREEBSD_NR_adjtime:
+-
+ #ifdef TARGET_FREEBSD_NR_gethostid
+ case TARGET_FREEBSD_NR_gethostid:
+ #endif
+@@ -4833,13 +6601,6 @@ do_stat:
+ case TARGET_FREEBSD_NR_sethostname:
+ #endif
+
+- case TARGET_FREEBSD_NR_mincore:
+-
+- case TARGET_FREEBSD_NR_vadvise:
+-
+- case TARGET_FREEBSD_NR_sbrk:
+- case TARGET_FREEBSD_NR_sstk:
+-
+ #ifdef TARGET_FREEBSD_NR_getkerninfo
+ case TARGET_FREEBSD_NR_getkerninfo:
+ #endif
+@@ -4847,8 +6608,6 @@ do_stat:
+ case TARGET_FREEBSD_NR_getpagesize:
+ #endif
+
+- case TARGET_FREEBSD_NR_revoke:
+-
+ case TARGET_FREEBSD_NR_profil:
+ case TARGET_FREEBSD_NR_ktrace:
+
+@@ -4857,12 +6616,13 @@ do_stat:
+ case TARGET_FREEBSD_NR_jail_get:
+ case TARGET_FREEBSD_NR_jail_set:
+ case TARGET_FREEBSD_NR_jail_remove:
++ ret = unimplemented(num);
++ break;
+
+ case TARGET_FREEBSD_NR_cap_enter:
+ case TARGET_FREEBSD_NR_cap_getmode:
+-
+- case TARGET_FREEBSD_NR_kenv:
+- case TARGET_FREEBSD_NR_uuidgen:
++ ret = unimplemented(num);
++ break;
+
+ case TARGET_FREEBSD_NR___mac_get_proc:
+ case TARGET_FREEBSD_NR___mac_set_proc:
+@@ -4873,6 +6633,8 @@ do_stat:
+ case TARGET_FREEBSD_NR___mac_get_link:
+ case TARGET_FREEBSD_NR___mac_set_link:
+ case TARGET_FREEBSD_NR_mac_syscall:
++ ret = unimplemented(num);
++ break;
+
+ case TARGET_FREEBSD_NR_audit:
+ case TARGET_FREEBSD_NR_auditon:
+@@ -4881,6 +6643,8 @@ do_stat:
+ case TARGET_FREEBSD_NR_getaudit_addr:
+ case TARGET_FREEBSD_NR_setaudit_addr:
+ case TARGET_FREEBSD_NR_auditctl:
++ ret = unimplemented(num);
++ break;
+
+
+ #ifdef TARGET_FREEBSD_NR_obreak
+@@ -4894,7 +6658,6 @@ do_stat:
+ case TARGET_FREEBSD_NR_sendfile:
+ case TARGET_FREEBSD_NR_ptrace:
+ case TARGET_FREEBSD_NR_utrace:
+- case TARGET_FREEBSD_NR_ioctl:
+ ret = unimplemented(num);
+ break;
+
+@@ -5061,4 +6824,43 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
+
+ void syscall_init(void)
+ {
++ IOCTLEntry *ie;
++ const argtype *arg_type;
++ int size;
++
++#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
++#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
++#ifdef __FreeBSD__
++#include "freebsd/syscall_types.h"
++#else
++#warning No syscall_types.h
++#endif
++#undef STRUCT
++#undef STRUCT_SPECIAL
++
++ /*
++ * Patch the ioctl size if necessary using the fact that no
++ * ioctl has all the bits at '1' in the size field
++ * (IOCPARM_MAX - 1).
++ */
++ ie = ioctl_entries;
++ while (ie->target_cmd != 0) {
++ if (((ie->target_cmd >> TARGET_IOCPARM_SHIFT) &
++ TARGET_IOCPARM_MASK) == TARGET_IOCPARM_MASK) {
++ 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_IOCPARM_MASK
++ << TARGET_IOCPARM_SHIFT)) |
++ (size << TARGET_IOCPARM_SHIFT);
++ }
++ ie++;
++ }
++
+ }
+diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h
+index 2879d83..3eb760b 100644
+--- a/bsd-user/syscall_defs.h
++++ b/bsd-user/syscall_defs.h
+@@ -555,7 +555,7 @@ struct target_rtprio {
+ */
+
+ struct target_umtx {
+- uint32_t u_owner; /* Owner of the mutex. */
++ abi_ulong u_owner; /* Owner of the mutex. */
+ };
+
+ struct target_umutex {
+@@ -573,7 +573,7 @@ struct target_ucond {
+ };
+
+ struct target_urwlock {
+- int32_t rw_state;
++ uint32_t rw_state;
+ uint32_t rw_flags;
+ uint32_t rw_blocked_readers;
+ uint32_t rw_blocked_writers;
+@@ -613,7 +613,146 @@ struct target__usem {
+ #define TARGET_UMTX_OP_SEM_WAIT 19
+ #define TARGET_UMTX_OP_SEM_WAKE 20
+ #define TARGET_UMTX_OP_NWAKE_PRIVATE 21
+-#define TARGET_UMTX_OP_MAX 22
++#define TARGET_UMTX_OP_MUTEX_WAKE2 22
++#define TARGET_UMTX_OP_MAX 23
+
+ /* flags for UMTX_OP_CV_WAIT */
+-#define TARGET_CHECK_UNPARKING 0x01
++#define TARGET_CVWAIT_CHECK_UNPARKING 0x01
++#define TARGET_CVWAIT_ABSTIME 0x02
++#define TARGET_CVWAIT_CLOCKID 0x04
++
++#define TARGET_UMTX_UNOWNED 0x0
++#define TARGET_UMUTEX_UNOWNED 0x0
++#define TARGET_UMTX_CONTESTED (abi_long)(0x8000000000000000)
++#define TARGET_UMUTEX_CONTESTED 0x80000000U
++
++/* flags for umutex */
++#define TARGET_UMUTEX_ERROR_CHECK 0x0002 /* Error-checking mutex */
++#define TARGET_UMUTEX_PRIO_INHERIT 0x0004 /* Priority inherited mutex */
++#define TARGET_UMUTEX_PRIO_PROTECT 0x0008 /* Priority protect mutex */
++
++#define TARGET_UMUTEX_TRY 1
++#define TARGET_UMUTEX_WAIT 2
++
++/* urwlock flags */
++#define TARGET_URWLOCK_PREFER_READER 0x0002
++#define TARGET_URWLOCK_WRITE_OWNER 0x80000000U
++#define TARGET_URWLOCK_WRITE_WAITERS 0x40000000U
++#define TARGET_URWLOCK_READ_WAITERS 0x20000000U
++#define TARGET_URWLOCK_MAX_READERS 0x1fffffffU
++#define TARGET_URWLOCK_READER_COUNT(c) ((c) & TARGET_URWLOCK_MAX_READERS)
++
++/* mount.h statfs */
++/*
++ * filesystem id type
++ */
++typedef struct target_fsid { int32_t val[2]; } target_fsid_t;
++
++/*
++ * filesystem statistics
++ */
++#define TARGET_MFSNAMELEN 16 /* length of type name include null */
++#define TARGET_MNAMELEN 88 /* size of on/from name bufs */
++#define TARGET_STATFS_VERSION 0x20030518 /* current version number */
++struct target_statfs {
++ uint32_t f_version; /* structure version number */
++ uint32_t f_type; /* type of filesystem */
++ uint64_t f_flags; /* copy of mount exported flags */
++ uint64_t f_bsize; /* filesystem fragment size */
++ uint64_t f_iosize; /* optimal transfer block size */
++ uint64_t f_blocks; /* total data blocks in filesystem */
++ uint64_t f_bfree; /* free blocks in filesystem */
++ int64_t f_bavail; /* free blocks avail to non-superuser */
++ uint64_t f_files; /* total file nodes in filesystem */
++ int64_t f_ffree; /* free nodes avail to non-superuser */
++ uint64_t f_syncwrites; /* count of sync writes since mount */
++ uint64_t f_asyncwrites; /* count of async writes since mount */
++ uint64_t f_syncreads; /* count of sync reads since mount */
++ uint64_t f_asyncreads; /* count of async reads since mount */
++ uint64_t f_spare[10]; /* unused spare */
++ uint32_t f_namemax; /* maximum filename length */
++ uid_t f_owner; /* user that mounted the filesystem */
++ target_fsid_t f_fsid; /* filesystem id */
++ char f_charspare[80]; /* spare string space */
++ char f_fstypename[TARGET_MFSNAMELEN]; /* filesys type name */
++ char f_mntfromname[TARGET_MNAMELEN]; /* mount filesystem */
++ char f_mntonname[TARGET_MNAMELEN]; /* dir on which mounted*/
++};
++
++/*
++ * File identifier.
++ * These are unique per filesystem on a single machine.
++ */
++#define TARGET_MAXFIDSZ 16
++
++struct target_fid {
++ u_short fid_len; /* len of data in bytes */
++ u_short fid_data0; /* force longword align */
++ char fid_data[TARGET_MAXFIDSZ]; /* data (variable len) */
++};
++
++/*
++ * Generic file handle
++ */
++struct target_fhandle {
++ target_fsid_t fh_fsid; /* Filesystem id of mount point */
++ struct target_fid fh_fid; /* Filesys specific id */
++};
++typedef struct target_fhandle target_fhandle_t;
++
++
++/*
++ * uuidgen. From sys/uuid.h.
++ */
++
++#define TARGET_UUID_NODE_LEN 6
++
++struct target_uuid {
++ uint32_t time_low;
++ uint16_t time_mid;
++ uint16_t time_hi_and_version;
++ uint8_t clock_seq_hi_and_reserved;
++ uint8_t clock_seq_low;
++ uint8_t node[TARGET_UUID_NODE_LEN];
++};
++
++/*
++ * ntp. From sys/timex.h.
++ */
++
++struct target_ntptimeval {
++ struct target_freebsd_timespec time;
++ abi_long maxerror;
++ abi_long esterror;
++ abi_long tai;
++ int32_t time_state;
++};
++
++struct target_timex {
++ uint32_t modes;
++ abi_long offset;
++ abi_long freq;
++ abi_long maxerror;
++ abi_long esterror;
++ int32_t status;
++ abi_long constant;
++ abi_long precision;
++ abi_long tolerance;
++
++ abi_long ppsfreq;
++ abi_long jitter;
++ int32_t shift;
++ abi_long stabil;
++ abi_long jitcnt;
++ abi_long calcnt;
++ abi_long errcnt;
++ abi_long stbcnt;
++};
++
++/*
++ * sched.h From sched.h
++ */
++
++struct target_sched_param {
++ int32_t sched_priority;
++};
diff --git a/emulators/qemu-devel/files/patch-z3-bsd-user-8fix b/emulators/qemu-devel/files/patch-z3-bsd-user-8fix
new file mode 100644
index 000000000000..d8ad10af8fd1
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z3-bsd-user-8fix
@@ -0,0 +1,61 @@
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -17,6 +17,18 @@
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
++
++#if defined(__FreeBSD__)
++#include <sys/param.h>
++#endif
++
++#if defined(__FreeBSD_version) && __FreeBSD_version < 900000
++#define st_atim st_atimespec
++#define st_ctim st_ctimespec
++#define st_mtim st_mtimespec
++#define st_birthtim st_birthtimespec
++#endif
++
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <stdint.h>
+@@ -1519,9 +1533,11 @@ do_setsockopt(int sockfd, int level, int
+ optname = SO_ERROR;
+ break;
+
++#ifdef SO_USER_COOKIE
+ case TARGET_SO_USER_COOKIE:
+ optname = SO_USER_COOKIE;
+ break;
++#endif
+
+ default:
+ goto unimplemented;
+@@ -2091,9 +2107,11 @@ do_fork(CPUArchState *env, int num, int
+ ret = rfork(flags);
+ break;
+
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+ case TARGET_FREEBSD_NR_pdfork:
+ ret = pdfork(&fd, flags);
+ break;
++#endif
+
+ default:
+ ret = -TARGET_ENOSYS;
+@@ -3499,6 +3517,7 @@ do_stat:
+ unlock_user(p, arg1, 0);
+ break;
+
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+ case TARGET_FREEBSD_NR_setloginclass:
+ if (!(p = lock_user_string(arg1)))
+ goto efault;
+@@ -3512,6 +3531,7 @@ do_stat:
+ ret = get_errno(getloginclass(p, arg2));
+ unlock_user(p, arg1, 0);
+ break;
++#endif
+
+ case TARGET_FREEBSD_NR_getrusage:
+ {
diff --git a/emulators/qemu-devel/files/patch-z3b-bsd-user-8fix b/emulators/qemu-devel/files/patch-z3b-bsd-user-8fix
new file mode 100644
index 000000000000..7a4de89f5a5b
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z3b-bsd-user-8fix
@@ -0,0 +1,34 @@
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -3890,6 +3890,7 @@ do_stat:
+ break;
+ #endif
+
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+ case TARGET_FREEBSD_NR_pdkill:
+ ret = get_errno(pdkill(arg1, target_to_host_signal(arg2)));
+ break;
+@@ -3903,6 +3904,7 @@ do_stat:
+ goto efault;
+ }
+ break;
++#endif
+
+ case TARGET_FREEBSD_NR_sigaction:
+ {
+@@ -4176,6 +4178,7 @@ do_stat:
+ break;
+ #endif
+
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+ case TARGET_FREEBSD_NR_posix_fallocate:
+ {
+ off_t offset = arg2, len = arg3;
+@@ -4192,6 +4195,7 @@ do_stat:
+ ret = get_errno(posix_fallocate(arg1, offset, len));
+ }
+ break;
++#endif
+
+ #ifdef TARGET_FREEBSD_posix_openpt
+ case TARGET_FREEBSD_posix_openpt:
diff --git a/emulators/qemu-devel/files/patch-z3c-bsd-user-8fix b/emulators/qemu-devel/files/patch-z3c-bsd-user-8fix
new file mode 100644
index 000000000000..20e2003aa488
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z3c-bsd-user-8fix
@@ -0,0 +1,12 @@
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -54,7 +54,9 @@
+ #include <sys/socket.h>
+ #ifdef __FreeBSD__
+ #include <sys/regression.h>
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+ #include <sys/procdesc.h>
++#endif
+ #include <sys/ucontext.h>
+ #include <sys/thr.h>
+ #include <sys/rtprio.h>
diff --git a/emulators/qemu-devel/files/patch-z3d-bsd-user-8fix b/emulators/qemu-devel/files/patch-z3d-bsd-user-8fix
new file mode 100644
index 000000000000..1e3201a4f6bc
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z3d-bsd-user-8fix
@@ -0,0 +1,47 @@
+--- qemu-1.4.0/bsd-user/syscall.c.orig
++++ qemu-1.4.0/bsd-user/syscall.c
+@@ -62,7 +62,11 @@
+ #include <sys/rtprio.h>
+ #include <sys/umtx.h>
+ #include <sys/uuid.h>
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+ #include <sys/_termios.h>
++#else
++#include <sys/termios.h>
++#endif
+ #include <sys/ttycom.h>
+ #include <sys/reboot.h>
+ #include <sys/timex.h>
+@@ -6383,6 +6387,7 @@ abi_long do_freebsd_syscall(void *cpu_en
+ val, NULL, NULL));
+ break;
+
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+ case TARGET_UMTX_OP_NWAKE_PRIVATE:
+ if (! access_ok(VERIFY_READ, obj,
+ val * sizeof(uint32_t)))
+@@ -6390,7 +6395,7 @@ abi_long do_freebsd_syscall(void *cpu_en
+ ret = get_errno(_umtx_op(g2h(obj), UMTX_OP_NWAKE_PRIVATE,
+ val, NULL, NULL));
+ break;
+-
++#endif
+
+ case TARGET_UMTX_OP_RW_RDLOCK:
+ if (target_ts) {
+@@ -6425,6 +6430,7 @@ abi_long do_freebsd_syscall(void *cpu_en
+ break;
+ #endif
+
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+ case TARGET_UMTX_OP_SEM_WAIT:
+ /* XXX Assumes struct _usem is opauque to the user */
+ if (! access_ok(VERIFY_WRITE, obj,
+@@ -6447,6 +6453,7 @@ abi_long do_freebsd_syscall(void *cpu_en
+ ret = get_errno(_umtx_op(g2h(obj), UMTX_OP_SEM_WAKE,
+ val, NULL, NULL));
+ break;
++#endif
+
+ default:
+ ret = -TARGET_EINVAL;
diff --git a/emulators/qemu-devel/files/patch-z4-bsd-user-elfload b/emulators/qemu-devel/files/patch-z4-bsd-user-elfload
new file mode 100644
index 000000000000..f1c4ae31ed17
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z4-bsd-user-elfload
@@ -0,0 +1,26 @@
+--- a/bsd-user/elfload.c
++++ b/bsd-user/elfload.c
+@@ -812,8 +812,9 @@ static abi_ulong setup_arg_pages(abi_ulo
+ * Add argv strings. Note that the argv[] vectors are added by
+ * loader_build_argptr()
+ */
+- i = bprm->argc;
+- while (i-- > 0) {
++ // i = bprm->argc;
++ // while (i-- > 0) {
++ for (i = 0; i < bprm->argc; ++i) {
+ size_t len = strlen(bprm->argv[i]) + 1;
+ /* XXX - check return value of memcpy_to_target(). */
+ memcpy_to_target(destp, bprm->argv[i], len);
+@@ -826,8 +827,9 @@ static abi_ulong setup_arg_pages(abi_ulo
+ * Add env strings. Note that the envp[] vectors are added by
+ * loader_build_argptr().
+ */
+- i = bprm->envc;
+- while(i-- > 0) {
++ // i = bprm->envc;
++ // while(i-- > 0) {
++ for (i = 0; i < bprm->envc; ++i) {
+ size_t len = strlen(bprm->envp[i]) + 1;
+ /* XXX - check return value of memcpy_to_target(). */
+ memcpy_to_target(destp, bprm->envp[i], len);
diff --git a/emulators/qemu-devel/files/patch-z6-bsd-user-usrstack1 b/emulators/qemu-devel/files/patch-z6-bsd-user-usrstack1
new file mode 100644
index 000000000000..df26a50388f1
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z6-bsd-user-usrstack1
@@ -0,0 +1,18 @@
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -377,6 +377,15 @@ static abi_long do_freebsd_sysctl(abi_ul
+ *q++ = tswap32(*p);
+ oidfmt(snamep, namelen, NULL, &kind);
+ /* XXX swap hnewp */
++#if HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32
++ /* XXX there may be more sysctls that differ */
++ if (namelen == 2 &&
++ snamep[0] == CTL_KERN && snamep[1] == KERN_USRSTACK &&
++ holdlen && holdlen == 4 && hnewp == NULL) {
++ (*(uint32_t *)holdp) = 0xfffff000U;
++ ret = 0;
++ } else
++#endif
+ ret = get_errno(sysctl(snamep, namelen, holdp, &holdlen, hnewp, newlen));
+ if (!ret)
+ sysctl_oldcvt(holdp, holdlen, kind);
diff --git a/emulators/qemu-devel/files/patch-z7-bsd-user-tls1-cognet b/emulators/qemu-devel/files/patch-z7-bsd-user-tls1-cognet
new file mode 100644
index 000000000000..f3aac00b4908
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z7-bsd-user-tls1-cognet
@@ -0,0 +1,171 @@
+--- oldqemu-1.3.0/bsd-user/syscall.c 2012-12-13 23:51:09.000000000 +0100
++++ qemu-1.3.0/bsd-user/syscall.c 2012-12-13 23:46:55.000000000 +0100
+@@ -258,6 +258,16 @@ static abi_long do_freebsd_sysarch(void
+ #ifdef TARGET_ARM
+ static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
+ {
++ abi_ulong val;
++
++ switch (op) {
++ case TARGET_FREEBSD_ARM_SET_TP:
++ if (get_user(val, parms, abi_ulong))
++ return -TARGET_EINVAL;
++ cpu_set_tls(env, val);
++ return 0;
++ }
++
+ return -TARGET_EINVAL;
+ }
+ #endif
+--- oldqemu-1.3.0/bsd-user/elfload.c 2012-12-13 23:51:09.000000000 +0100
++++ qemu-1.3.0/bsd-user/elfload.c 2012-12-13 23:50:14.000000000 +0100
+@@ -948,10 +948,8 @@ static abi_ulong create_elf_tables(abi_u
+ * Force 16 byte _final_ alignment here for generality.
+ */
+ sp = sp &~ (abi_ulong)15;
+-#ifdef __FreeBSD__
+- size = 0;
+-#else
+ size = (DLINFO_ITEMS + 1) * 2;
++#ifndef __FreeBSD__
+ if (k_platform)
+ size += 2;
+ #ifdef DLINFO_ARCH_ITEMS
+@@ -964,7 +962,6 @@ static abi_ulong create_elf_tables(abi_u
+ if (size & 15)
+ sp -= 16 - (size & 15);
+
+-#ifndef __FreeBSD__
+ /* This is correct because Linux defines
+ * elf_addr_t as Elf32_Off / Elf64_Off
+ */
+@@ -989,8 +986,10 @@ static abi_ulong create_elf_tables(abi_u
+ NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
+ NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
+ NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
++#ifndef __FreeBSD__
+ if (k_platform)
+ NEW_AUX_ENT(AT_PLATFORM, u_platform);
++#endif
+ #ifdef ARCH_DLINFO
+ /*
+ * ARCH_DLINFO must come last so platform specific code can enforce
+@@ -999,7 +998,6 @@ static abi_ulong create_elf_tables(abi_u
+ ARCH_DLINFO;
+ #endif
+ #undef NEW_AUX_ENT
+-#endif /* ! __FreeBSD__ */
+
+ sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
+ return sp;
+--- oldqemu-1.3.0/bsd-user/main.c 2012-12-13 23:51:09.000000000 +0100
++++ qemu-1.3.0/bsd-user/main.c 2012-12-13 23:01:30.000000000 +0100
+@@ -392,6 +392,84 @@ void cpu_loop(CPUX86State *env)
+ #ifdef TARGET_ARM
+ // #define DEBUG_ARM
+
++static int do_strex(CPUARMState *env)
++{
++ uint32_t val;
++ int size;
++ int rc = 1;
++ int segv = 0;
++ uint32_t addr;
++ start_exclusive();
++ addr = env->exclusive_addr;
++ if (addr != env->exclusive_test) {
++ goto fail;
++ }
++ size = env->exclusive_info & 0xf;
++ switch (size) {
++ case 0:
++ segv = get_user_u8(val, addr);
++ break;
++ case 1:
++ segv = get_user_u16(val, addr);
++ break;
++ case 2:
++ case 3:
++ segv = get_user_u32(val, addr);
++ break;
++ default:
++ abort();
++ }
++ if (segv) {
++ env->cp15.c6_data = addr;
++ goto done;
++ }
++ if (val != env->exclusive_val) {
++ goto fail;
++ }
++ if (size == 3) {
++ segv = get_user_u32(val, addr + 4);
++ if (segv) {
++ env->cp15.c6_data = addr + 4;
++ goto done;
++ }
++ if (val != env->exclusive_high) {
++ goto fail;
++ }
++ }
++ val = env->regs[(env->exclusive_info >> 8) & 0xf];
++ switch (size) {
++ case 0:
++ segv = put_user_u8(val, addr);
++ break;
++ case 1:
++ segv = put_user_u16(val, addr);
++ break;
++ case 2:
++ case 3:
++ segv = put_user_u32(val, addr);
++ break;
++ }
++ if (segv) {
++ env->cp15.c6_data = addr;
++ goto done;
++ }
++ if (size == 3) {
++ val = env->regs[(env->exclusive_info >> 12) & 0xf];
++ segv = put_user_u32(val, addr + 4);
++ if (segv) {
++ env->cp15.c6_data = addr + 4;
++ goto done;
++ }
++ }
++ rc = 0;
++fail:
++ env->regs[15] += 4;
++ env->regs[(env->exclusive_info >> 4) & 0xf] = rc;
++done:
++ end_exclusive();
++ return segv;
++}
++
+ void cpu_loop(CPUARMState *env)
+ {
+ int trapnr;
+@@ -622,6 +700,7 @@ void cpu_loop(CPUARMState *env)
+ if (do_kernel_trap(env))
+ goto error;
+ break;
++#endif
+ case EXCP_STREX:
+ if (do_strex(env)) {
+ addr = env->cp15.c6_data;
+@@ -629,7 +708,6 @@ void cpu_loop(CPUARMState *env)
+ }
+ break;
+ error:
+-#endif
+ default:
+ fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
+ trapnr);
+--- oldqemu-1.3.0/bsd-user/arm/syscall.h 2012-12-13 23:51:09.000000000 +0100
++++ qemu-1.3.0/bsd-user/arm/syscall.h 2012-12-13 23:45:22.000000000 +0100
+@@ -21,3 +21,5 @@ struct target_pt_regs {
+ #define ARM_r0 uregs[0]
+
+ #define ARM_SYSCALL_BASE 0 /* XXX: FreeBSD only */
++
++#define TARGET_FREEBSD_ARM_SET_TP 2
diff --git a/emulators/qemu-devel/files/patch-z7b-bsd-user-tls2 b/emulators/qemu-devel/files/patch-z7b-bsd-user-tls2
new file mode 100644
index 000000000000..81dc689b6869
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z7b-bsd-user-tls2
@@ -0,0 +1,13 @@
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -266,9 +268,7 @@ static abi_long do_freebsd_sysarch(void
+
+ switch (op) {
+ case TARGET_FREEBSD_ARM_SET_TP:
+- if (get_user(val, parms, abi_ulong))
+- return -TARGET_EINVAL;
+- cpu_set_tls(env, val);
++ cpu_set_tls(env, parms);
+ return 0;
+ }
+
diff --git a/emulators/qemu-devel/files/patch-z8-bsd-user-unref b/emulators/qemu-devel/files/patch-z8-bsd-user-unref
new file mode 100644
index 000000000000..6f9b0f96617a
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z8-bsd-user-unref
@@ -0,0 +1,11 @@
+--- qemu-1.4.0/bsd-user/syscall.c.orig
++++ qemu-1.4.0/bsd-user/syscall.c
+@@ -2418,7 +2418,7 @@ do_thr_exit(CPUArchState *cpu_env, abi_u
+ }
+
+ thread_env = NULL;
+- object_delete(OBJECT(ENV_GET_CPU(cpu_env)));
++ object_unref(OBJECT(ENV_GET_CPU(cpu_env)));
+ g_free(ts);
+ pthread_exit(NULL);
+ }
diff --git a/emulators/qemu-devel/files/patch-z9-bsd-user-sson003a b/emulators/qemu-devel/files/patch-z9-bsd-user-sson003a
new file mode 100644
index 000000000000..3a8887d6c98a
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z9-bsd-user-sson003a
@@ -0,0 +1,40 @@
+diff --git a/bsd-user/freebsd/ioctl.h b/bsd-user/freebsd/ioctl.h
+index 67c5583..f83f6c1 100644
+--- a/bsd-user/freebsd/ioctl.h
++++ b/bsd-user/freebsd/ioctl.h
+@@ -8,8 +8,8 @@ IOCTL(TIOCSBRK, IOC_, TYPE_NULL)
+ IOCTL(TIOCCBRK, IOC_, TYPE_NULL)
+ IOCTL(TIOCSDTR, IOC_, TYPE_NULL)
+ IOCTL(TIOCCDTR, IOC_, TYPE_NULL)
+-IOCTL(TIOCGPGRP, IOC_W, MK_PTR(TYPE_INT))
+-IOCTL(TIOCSPGRP, IOC_R, MK_PTR(TYPE_INT))
++IOCTL(TIOCGPGRP, IOC_R, MK_PTR(TYPE_INT))
++IOCTL(TIOCSPGRP, IOC_W, MK_PTR(TYPE_INT))
+ IOCTL(TIOCGETA, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
+ IOCTL(TIOCSETA, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
+ IOCTL(TIOCSETAW, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
+diff --git a/bsd-user/main.c b/bsd-user/main.c
+index d9a0ecd..7cc77aa 100644
+--- a/bsd-user/main.c
++++ b/bsd-user/main.c
+@@ -1907,7 +1907,7 @@ int main(int argc, char **argv)
+ env->hflags |= MIPS_HFLAG_M16;
+ }
+ #if defined(TARGET_MIPS64)
+- env->hflags |= MIPS_HFLAG_UX;
++ env->hflags |= MIPS_HFLAG_UX | MIPS_HFLAG_64;
+ #endif
+ }
+ #else
+diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
+index 581a31f..a40d7ce 100644
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -278,7 +278,6 @@ static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
+ #ifdef TARGET_ARM
+ static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
+ {
+- abi_ulong val;
+
+ switch (op) {
+ case TARGET_FREEBSD_ARM_SET_TP:
diff --git a/emulators/qemu-devel/files/patch-z9b-bsd-user-sson003b b/emulators/qemu-devel/files/patch-z9b-bsd-user-sson003b
new file mode 100644
index 000000000000..68d86a69a347
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z9b-bsd-user-sson003b
@@ -0,0 +1,332 @@
+diff --git a/bsd-user/arm/target_vmparam.h b/bsd-user/arm/target_vmparam.h
+index 0427244..24dca00 100644
+--- a/bsd-user/arm/target_vmparam.h
++++ b/bsd-user/arm/target_vmparam.h
+@@ -20,6 +20,10 @@ struct target_ps_strings {
+
+ #define TARGET_SZSIGCODE 0
+
++/* Make stack size large enough to hold everything. */
++#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \
++ MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size)
++
+ #else
+
+ #define TARGET_USRSTACK 0
+diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
+index 0c48f5a..f5f652f 100644
+--- a/bsd-user/elfload.c
++++ b/bsd-user/elfload.c
+@@ -715,9 +715,13 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
+ /* Create enough stack to hold everything. If we don't use
+ * it for args, we'll use it for something else...
+ */
++#ifdef TARGET_STACK_SIZE
++ size = TARGET_STACK_SIZE;
++#else
+ size = x86_stack_size;
+ if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
+ size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
++#endif
+
+ #ifdef TARGET_USRSTACK
+ stack_base = TARGET_USRSTACK - size;
+@@ -738,7 +742,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
+
+ #if defined(__FreeBSD__)
+ /*
+- * The inital FreeBSD stack looks like follows:
++ * The inital FreeBSD stack is as follows:
+ * (see kern/kern_exec.c exec_copyout_strings() )
+ *
+ * Hi Address -> char **ps_argvstr (struct ps_strings for ps, w, etc.)
+diff --git a/bsd-user/freebsd/strace.list b/bsd-user/freebsd/strace.list
+index bcdd931..c66dcfa 100644
+--- a/bsd-user/freebsd/strace.list
++++ b/bsd-user/freebsd/strace.list
+@@ -118,6 +118,7 @@
+ { TARGET_FREEBSD_NR_revoke, "revoke", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_rfork, "rfork", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_rmdir, "rmdir", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_rtprio_thread, "rtprio_thread", "%s(%d, %d, %p)", NULL, NULL },
+ { TARGET_FREEBSD_NR_sbrk, "sbrk", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_sched_yield, "sched_yield", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_select, "select", NULL, NULL, NULL },
+diff --git a/bsd-user/i386/target_vmparam.h b/bsd-user/i386/target_vmparam.h
+index 8fc98d5..ea7546c 100644
+--- a/bsd-user/i386/target_vmparam.h
++++ b/bsd-user/i386/target_vmparam.h
+@@ -19,6 +19,10 @@ struct target_ps_strings {
+
+ #define TARGET_SZSIGCODE 0
+
++/* Make stack size large enough to hold everything. */
++#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \
++ MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size)
++
+ #else
+
+ #define TARGET_USRSTACK 0
+diff --git a/bsd-user/main.c b/bsd-user/main.c
+index 7cc77aa..32bd3e5 100644
+--- a/bsd-user/main.c
++++ b/bsd-user/main.c
+@@ -855,7 +855,9 @@ void cpu_loop(CPUARMState *env)
+ goto do_segv;
+ }
+ break;
++#if 0
+ error:
++#endif
+ default:
+ fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
+ trapnr);
+diff --git a/bsd-user/mips/target_vmparam.h b/bsd-user/mips/target_vmparam.h
+index 9fca7f3..8abc26c 100644
+--- a/bsd-user/mips/target_vmparam.h
++++ b/bsd-user/mips/target_vmparam.h
+@@ -21,6 +21,10 @@ struct target_ps_strings {
+
+ #define TARGET_SZSIGCODE 0
+
++/* Make stack size large enough to hold everything. */
++#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \
++ MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size)
++
+ #else
+
+ #define TARGET_USRSTACK 0
+diff --git a/bsd-user/mips64/target_vmparam.h b/bsd-user/mips64/target_vmparam.h
+index 47c2267..55ed254 100644
+--- a/bsd-user/mips64/target_vmparam.h
++++ b/bsd-user/mips64/target_vmparam.h
+@@ -20,6 +20,10 @@ struct target_ps_strings {
+
+ #define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
+
++/* Make stack size large enough to hold everything. */
++#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \
++ MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size)
++
+ #else
+
+ #define TARGET_USRSTACK 0
+diff --git a/bsd-user/sparc/target_vmparam.h b/bsd-user/sparc/target_vmparam.h
+index 9494c46..82c29ed 100644
+--- a/bsd-user/sparc/target_vmparam.h
++++ b/bsd-user/sparc/target_vmparam.h
+@@ -1,8 +1,6 @@
+ #ifndef _TARGET_VMPARAM_H_
+ #define _TARGET_VMPARAM_H_
+
+-#define TARGET_USRSTACK 0
+-
+ #ifdef __FreeBSD__
+ struct target_ps_strings {
+ abi_ulong ps_argvstr;
+@@ -14,9 +12,22 @@ struct target_ps_strings {
+ #define TARGET_SPACE_USRSPACE 4096
+ #define TARGET_ARG_MAX 262144
+
++/* XXX */
++#define TARGET_VM_MAXUSER_ADDRESS (0xc0000000 - (512 * 1024 * 1024))
++#define TARGET_USRSTACK TARGET_VM_MAXUSER_ADDRESS
++
+ #define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
+
+ #define TARGET_SZSIGCODE 0
++
++/* Make stack size large enough to hold everything. */
++#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \
++ MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size)
++
++#else
++
++#define TARGET_USRSTACK 0
++
+ #endif /* __FreeBSD__ */
+
+ #endif /* _TARGET_VMPARAM_H_ */
+diff --git a/bsd-user/sparc64/target_vmparam.h b/bsd-user/sparc64/target_vmparam.h
+index 12af063..7f2b464 100644
+--- a/bsd-user/sparc64/target_vmparam.h
++++ b/bsd-user/sparc64/target_vmparam.h
+@@ -21,6 +21,10 @@ struct target_ps_strings {
+
+ #define TARGET_SZSIGCODE 0
+
++/* Make stack size large enough to hold everything. */
++#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \
++ MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size)
++
+ #else
+
+ #define TARGET_USRSTACK 0
+diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
+index a40d7ce..8565ae8 100644
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -409,19 +409,44 @@ static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong ol
+ for (p = hnamep, q = snamep, i = 0; i < namelen; p++, i++)
+ *q++ = tswap32(*p);
+ oidfmt(snamep, namelen, NULL, &kind);
+- /* XXX swap hnewp */
+-#if HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32
+- /* XXX there may be more sysctls that differ */
+- if (namelen == 2 &&
+- snamep[0] == CTL_KERN && snamep[1] == KERN_USRSTACK &&
+- holdlen && holdlen == 4 && hnewp == NULL) {
+- (*(uint32_t *)holdp) = 0xfffff000U;
+- ret = 0;
+- } else
++
++ /* Handle some arch/emulator dependent sysctl()'s here. */
++ if (CTL_KERN == snamep[0]) {
++ switch(snamep[1]) {
++ case KERN_USRSTACK:
++#if defined(TARGET_ARM) && HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32
++ (*(uint32_t *)holdp) = 0xfffff000U;
++ holdlen = sizeof(uint32_t);
++ ret = 0;
++#elif TARGET_USRSTACK != 0
++ (*(abi_ulong *)holdp) = tswapal(TARGET_USRSTACK);
++ holdlen = sizeof(abi_ulong);
++ ret = 0;
++#else
++ ret = -TARGET_ENOENT;
++#endif
++ goto out;
++
++ case KERN_PS_STRINGS:
++#if defined(TARGET_PS_STRINGS)
++ (*(abi_ulong *)holdp) = tswapal(TARGET_PS_STRINGS);
++ holdlen = sizeof(abi_ulong);
++ ret = 0;
++#else
++ ret = -TARGET_ENOENT;
+ #endif
++ goto out;
++
++ default:
++ break;
++ }
++ }
++
+ ret = get_errno(sysctl(snamep, namelen, holdp, &holdlen, hnewp, newlen));
+ if (!ret)
+ sysctl_oldcvt(holdp, holdlen, kind);
++
++out:
+ put_user_ual(holdlen, oldlenp);
+ unlock_user(hnamep, namep, 0);
+ unlock_user(holdp, oldp, holdlen);
+@@ -3293,6 +3318,47 @@ host_to_target_fhandle(abi_ulong target_addr, fhandle_t *host_fh)
+ }
+
+ static inline abi_long
++target_to_host_rtprio(struct rtprio *host_rtp, abi_ulong target_addr)
++{
++ struct target_rtprio *target_rtp;
++
++ if (!lock_user_struct(VERIFY_READ, target_rtp, target_addr, 1))
++ return (-TARGET_EFAULT);
++ __get_user(host_rtp->type, &target_rtp->type);
++ __get_user(host_rtp->prio, &target_rtp->prio);
++ unlock_user_struct(target_rtp, target_addr, 0);
++ return (0);
++}
++
++static inline abi_long
++host_to_target_rtprio(abi_ulong target_addr, struct rtprio *host_rtp)
++{
++ struct target_rtprio *target_rtp;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_rtp, target_addr, 0))
++ return (-TARGET_EFAULT);
++ __put_user(host_rtp->type, &target_rtp->type);
++ __put_user(host_rtp->prio, &target_rtp->prio);
++ unlock_user_struct(target_rtp, target_addr, 1);
++ return (0);
++}
++
++static inline abi_long
++do_rtprio_thread(int function, lwpid_t lwpid, abi_ulong target_addr)
++{
++ int ret;
++ struct rtprio rtp;
++
++ ret = target_to_host_rtprio(&rtp, target_addr);
++ if (0 == ret)
++ ret = get_errno(rtprio_thread(function, lwpid, &rtp));
++ if (0 == ret)
++ ret = host_to_target_rtprio(target_addr, &rtp);
++
++ return (ret);
++}
++
++static inline abi_long
+ target_to_host_sched_param(struct sched_param *host_sp, abi_ulong target_addr)
+ {
+ struct target_sched_param *target_sp;
+@@ -4617,12 +4683,17 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ struct target_rlimit *target_rlim;
+ struct rlimit rlim;
+
+- if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
+- goto 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);
+- ret = get_errno(setrlimit(resource, &rlim));
++ if (RLIMIT_STACK == resource) {
++ /* XXX We should, maybe, allow the stack size to shrink */
++ ret = -TARGET_EPERM;
++ } else {
++ if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
++ goto 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);
++ ret = get_errno(setrlimit(resource, &rlim));
++ }
+ }
+ break;
+
+@@ -4633,7 +4704,12 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ struct target_rlimit *target_rlim;
+ struct rlimit rlim;
+
+- ret = get_errno(getrlimit(resource, &rlim));
++ /* Return the target stack size */
++ if (RLIMIT_STACK == resource) {
++ rlim.rlim_cur = rlim.rlim_max = TARGET_STACK_SIZE;
++ ret = 0;
++ } else
++ ret = get_errno(getrlimit(resource, &rlim));
+ if (!is_error(ret)) {
+ if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2,
+ 0))
+@@ -6148,7 +6224,7 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ break;
+
+ case TARGET_FREEBSD_NR_rtprio_thread:
+- ret = 0;
++ ret = do_rtprio_thread(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_getcontext:
+diff --git a/bsd-user/x86_64/target_vmparam.h b/bsd-user/x86_64/target_vmparam.h
+index aa5e0e0..ff9f534 100644
+--- a/bsd-user/x86_64/target_vmparam.h
++++ b/bsd-user/x86_64/target_vmparam.h
+@@ -20,6 +20,10 @@ struct target_ps_strings {
+
+ #define TARGET_SZSIGCODE 0
+
++/* Make stack size large enough to hold everything. */
++#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \
++ MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size)
++
+ #else
+
+ #define TARGET_USRSTACK 0
diff --git a/emulators/qemu-devel/files/patch-z9c-bsd-user-sson003c b/emulators/qemu-devel/files/patch-z9c-bsd-user-sson003c
new file mode 100644
index 000000000000..2161ac6b14ee
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z9c-bsd-user-sson003c
@@ -0,0 +1,2425 @@
+diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
+index f5f652f..8abb1dd 100644
+--- a/bsd-user/elfload.c
++++ b/bsd-user/elfload.c
+@@ -403,8 +403,11 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
+ {
+
+ regs->cp0_status = 2 << CP0St_KSU;
+- regs->regs[25] = regs->cp0_epc = infop->entry; /* t9 = pc = entry */
++ regs->regs[25] = regs->cp0_epc = infop->entry & ~3; /* t9 = pc = entry */
+ regs->regs[4] = regs->regs[29] = infop->start_stack; /* a0 = sp = start_stack */
++ regs->regs[5] = 0; /* a1 = 0 */
++ regs->regs[6] = 0; /* a2 = 0 */
++ regs->regs[7] = TARGET_PS_STRINGS; /* a3 = ps_strings */
+ }
+
+ #define USE_ELF_CORE_DUMP
+@@ -765,7 +768,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
+ {
+ abi_ulong stack_hi_addr;
+ size_t execpath_len;
+- abi_ulong destp;
++ abi_ulong destp, argvp, envp;
+ struct target_ps_strings ps_strs;
+ char canary[sizeof(abi_long) * 8];
+ char execpath[PATH_MAX];
+@@ -808,6 +811,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
+ /* XXX - check return value of put_user_ual(). */
+ put_user_ual(TARGET_PAGE_SIZE, p);
+
++ argvp = p - TARGET_SPACE_USRSPACE;
+ p = destp = p - TARGET_SPACE_USRSPACE - TARGET_ARG_MAX;
+
+ /* XXX should check strlen(argv and envp strings) < TARGET_ARG_MAX */
+@@ -816,31 +820,38 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
+ * Add argv strings. Note that the argv[] vectors are added by
+ * loader_build_argptr()
+ */
++ envp = argvp + (bprm->argc + 2) * sizeof(abi_ulong);
++ ps_strs.ps_argvstr = tswapl(argvp);
++ ps_strs.ps_nargvstr = tswap32(bprm->argc);
+ // i = bprm->argc;
+ // while (i-- > 0) {
+ for (i = 0; i < bprm->argc; ++i) {
+ size_t len = strlen(bprm->argv[i]) + 1;
+ /* XXX - check return value of memcpy_to_target(). */
+ memcpy_to_target(destp, bprm->argv[i], len);
++ put_user_ual(destp, argvp);
++ argvp += sizeof(abi_ulong);
+ destp += len;
+ }
+- ps_strs.ps_argvstr = tswapl(destp);
+- ps_strs.ps_nargvstr = tswap32(bprm->argc);
++ put_user_ual(0, argvp);
+
+ /*
+ * Add env strings. Note that the envp[] vectors are added by
+ * loader_build_argptr().
+ */
++ ps_strs.ps_envstr = tswapl(envp);
++ ps_strs.ps_nenvstr = tswap32(bprm->envc);
+ // i = bprm->envc;
+ // while(i-- > 0) {
+ for (i = 0; i < bprm->envc; ++i) {
+ size_t len = strlen(bprm->envp[i]) + 1;
+ /* XXX - check return value of memcpy_to_target(). */
+ memcpy_to_target(destp, bprm->envp[i], len);
++ put_user_ual(destp, envp);
++ envp += sizeof(abi_ulong);
+ destp += len;
+ }
+- ps_strs.ps_envstr = tswapl(destp);
+- ps_strs.ps_nenvstr = tswap32(bprm->envc);
++ put_user_ual(0, envp);
+
+ /* XXX - check return value of memcpy_to_target(). */
+ memcpy_to_target(stack_hi_addr - sizeof(ps_strs), &ps_strs,
+@@ -1304,6 +1315,27 @@ static void load_symbols(struct elfhdr *hdr, int fd)
+ syminfos = s;
+ }
+
++/* Check the elf header and see if this a target elf binary. */
++int is_target_elf_binary(int fd)
++{
++ uint8_t buf[128];
++ struct elfhdr elf_ex;
++
++ if (lseek(fd, 0L, SEEK_SET) < 0)
++ return (0);
++ if (read(fd, buf, sizeof(buf)) < 0)
++ return (0);
++
++ elf_ex = *((struct elfhdr *)buf);
++ bswap_ehdr(&elf_ex);
++
++ if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
++ (! elf_check_arch(elf_ex.e_machine)))
++ return (0);
++ else
++ return (1);
++}
++
+ int load_elf_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs,
+ struct image_info * info)
+ {
+@@ -1424,13 +1456,10 @@ int load_elf_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs,
+ /* JRP - Need to add X86 lib dir stuff here... */
+
+ if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
+- strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
++ strcmp(elf_interpreter,"/libexec/ld-elf.so.1") == 0) {
+ ibcs2_interpreter = 1;
+ }
+
+-#if 0
+- printf("Using ELF interpreter %s\n", path(elf_interpreter));
+-#endif
+ if (retval >= 0) {
+ retval = open(path(elf_interpreter), O_RDONLY);
+ if(retval >= 0) {
+diff --git a/bsd-user/freebsd/filio.h b/bsd-user/freebsd/filio.h
+new file mode 100644
+index 0000000..2269484
+--- /dev/null
++++ b/bsd-user/freebsd/filio.h
+@@ -0,0 +1,27 @@
++#ifndef _FREEBSD_FILIO_H_
++#define _FREEBSD_FILIO_H_
++
++/* see sys/filio.h */
++#define TARGET_FIOCLEX TARGET_IO('f', 1)
++#define TARGET_FIONCLEX TARGET_IO('f', 2)
++#define TARGET_FIONREAD TARGET_IOR('f', 127, int)
++#define TARGET_FIONBIO TARGET_IOW('f', 126, int)
++#define TARGET_FIOASYNC TARGET_IOW('f', 125, int)
++#define TARGET_FIOSETOWN TARGET_IOW('f', 124, int)
++#define TARGET_FIOGETOWN TARGET_IOR('f', 123, int)
++#define TARGET_FIODTYPE TARGET_IOR('f', 122, int)
++#define TARGET_FIOGETLBA TARGET_IOR('f', 121, int)
++
++struct target_fiodgname_arg {
++ int32_t len;
++ abi_ulong buf;
++};
++
++#define TARGET_FIODGNAME TARGET_IOW('f', 120, \
++ struct target_fiodgname_arg)
++#define TARGET_FIONWRITE TARGET_IOR('f', 119, int)
++#define TARGET_FIONSPACE TARGET_IOR('f', 118, int)
++#define TARGET_FIOSEEKDATA TARGET_IOWR('f', 97, off_t)
++#define TARGET_FIOSEEKHOLE TARGET_IOWR('f', 98, off_t)
++
++#endif /* !_FREEBSD_FILIO_H_ */
+diff --git a/bsd-user/freebsd/ioctl.h b/bsd-user/freebsd/ioctl.h
+deleted file mode 100644
+index f83f6c1..0000000
+--- a/bsd-user/freebsd/ioctl.h
++++ /dev/null
+@@ -1,35 +0,0 @@
+-#ifndef _FREEBSD_IOCTL_H_
+-#define _FREEBSD_IOCTL_H_
+-
+-/* sys/ttycom.h tty(4) */
+-IOCTL(TIOCSETD, IOC_W, MK_PTR(TYPE_INT))
+-IOCTL(TIOCGETD, IOC_R, MK_PTR(TYPE_INT))
+-IOCTL(TIOCSBRK, IOC_, TYPE_NULL)
+-IOCTL(TIOCCBRK, IOC_, TYPE_NULL)
+-IOCTL(TIOCSDTR, IOC_, TYPE_NULL)
+-IOCTL(TIOCCDTR, IOC_, TYPE_NULL)
+-IOCTL(TIOCGPGRP, IOC_R, MK_PTR(TYPE_INT))
+-IOCTL(TIOCSPGRP, IOC_W, MK_PTR(TYPE_INT))
+-IOCTL(TIOCGETA, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
+-IOCTL(TIOCSETA, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
+-IOCTL(TIOCSETAW, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
+-IOCTL(TIOCSETAF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
+-IOCTL(TIOCOUTQ, IOC_R, MK_PTR(TYPE_INT))
+-IOCTL(TIOCSTI, IOC_W, MK_PTR(TYPE_CHAR))
+-IOCTL(TIOCNOTTY, IOC_, TYPE_NULL)
+-IOCTL(TIOCSTOP, IOC_, TYPE_NULL)
+-IOCTL(TIOCSTART, IOC_, TYPE_NULL)
+-IOCTL(TIOCSCTTY, IOC_, TYPE_NULL)
+-IOCTL(TIOCDRAIN, IOC_, TYPE_NULL)
+-IOCTL(TIOCEXCL, IOC_, TYPE_NULL)
+-IOCTL(TIOCNXCL, IOC_, TYPE_NULL)
+-IOCTL(TIOCFLUSH, IOC_W, MK_PTR(TYPE_INT))
+-IOCTL(TIOCGWINSZ, IOC_R, MK_PTR(MK_STRUCT(STRUCT_winsize)))
+-IOCTL(TIOCSWINSZ, IOC_W, MK_PTR(MK_STRUCT(STRUCT_winsize)))
+-IOCTL(TIOCCONS, IOC_W, MK_PTR(TYPE_INT))
+-IOCTL(TIOCMSET, IOC_W, MK_PTR(TYPE_INT))
+-IOCTL(TIOCMGET, IOC_R, MK_PTR(TYPE_INT))
+-IOCTL(TIOCMBIS, IOC_W, MK_PTR(TYPE_INT))
+-IOCTL(TIOCMBIC, IOC_W, MK_PTR(TYPE_INT))
+-
+-#endif
+diff --git a/bsd-user/freebsd/ioctls.h b/bsd-user/freebsd/ioctls.h
+new file mode 100644
+index 0000000..85d3c41
+--- /dev/null
++++ b/bsd-user/freebsd/ioctls.h
+@@ -0,0 +1,47 @@
++
++/* sys/ttycom.h tty(4) */
++IOCTL(TIOCSETD, IOC_W, MK_PTR(TYPE_INT))
++IOCTL(TIOCGETD, IOC_R, MK_PTR(TYPE_INT))
++IOCTL(TIOCSBRK, IOC_, TYPE_NULL)
++IOCTL(TIOCCBRK, IOC_, TYPE_NULL)
++IOCTL(TIOCSDTR, IOC_, TYPE_NULL)
++IOCTL(TIOCCDTR, IOC_, TYPE_NULL)
++IOCTL(TIOCGPGRP, IOC_R, MK_PTR(TYPE_INT))
++IOCTL(TIOCSPGRP, IOC_W, MK_PTR(TYPE_INT))
++IOCTL(TIOCGETA, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
++IOCTL(TIOCSETA, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
++IOCTL(TIOCSETAW, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
++IOCTL(TIOCSETAF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
++IOCTL(TIOCOUTQ, IOC_R, MK_PTR(TYPE_INT))
++IOCTL(TIOCSTI, IOC_W, MK_PTR(TYPE_CHAR))
++IOCTL(TIOCNOTTY, IOC_, TYPE_NULL)
++IOCTL(TIOCSTOP, IOC_, TYPE_NULL)
++IOCTL(TIOCSTART, IOC_, TYPE_NULL)
++IOCTL(TIOCSCTTY, IOC_, TYPE_NULL)
++IOCTL(TIOCDRAIN, IOC_, TYPE_NULL)
++IOCTL(TIOCEXCL, IOC_, TYPE_NULL)
++IOCTL(TIOCNXCL, IOC_, TYPE_NULL)
++IOCTL(TIOCFLUSH, IOC_W, MK_PTR(TYPE_INT))
++IOCTL(TIOCGWINSZ, IOC_R, MK_PTR(MK_STRUCT(STRUCT_winsize)))
++IOCTL(TIOCSWINSZ, IOC_W, MK_PTR(MK_STRUCT(STRUCT_winsize)))
++IOCTL(TIOCCONS, IOC_W, MK_PTR(TYPE_INT))
++IOCTL(TIOCMSET, IOC_W, MK_PTR(TYPE_INT))
++IOCTL(TIOCMGET, IOC_R, MK_PTR(TYPE_INT))
++IOCTL(TIOCMBIS, IOC_W, MK_PTR(TYPE_INT))
++IOCTL(TIOCMBIC, IOC_W, MK_PTR(TYPE_INT))
++
++/* sys/filio.h */
++IOCTL(FIOCLEX, IOC_, TYPE_NULL)
++IOCTL(FIONCLEX, IOC_, TYPE_NULL)
++IOCTL(FIONREAD, IOC_R, MK_PTR(TYPE_INT))
++IOCTL(FIONBIO, IOC_W, MK_PTR(TYPE_INT))
++IOCTL(FIOASYNC, IOC_W, MK_PTR(TYPE_INT))
++IOCTL(FIOSETOWN, IOC_W, MK_PTR(TYPE_INT))
++IOCTL(FIOGETOWN, IOC_R, MK_PTR(TYPE_INT))
++IOCTL(FIODTYPE, IOC_R, MK_PTR(TYPE_INT))
++IOCTL(FIOGETLBA, IOC_R, MK_PTR(TYPE_INT))
++IOCTL(FIODGNAME, IOC_R, MK_PTR(STRUCT_fiodgname_arg))
++IOCTL(FIONWRITE, IOC_R, MK_PTR(TYPE_INT))
++IOCTL(FIONSPACE, IOC_R, MK_PTR(TYPE_INT))
++IOCTL(FIOSEEKDATA, IOC_RW, MK_PTR(TYPE_ULONG))
++IOCTL(FIOSEEKHOLE, IOC_RW, MK_PTR(TYPE_ULONG))
+diff --git a/bsd-user/freebsd/strace.list b/bsd-user/freebsd/strace.list
+index c66dcfa..8270c37 100644
+--- a/bsd-user/freebsd/strace.list
++++ b/bsd-user/freebsd/strace.list
+@@ -1,7 +1,19 @@
++{ TARGET_FREEBSD_NR___acl_aclcheck_fd, "__acl_get_fd", "%s(%d, %d, %#x)", NULL, NULL },
++{ TARGET_FREEBSD_NR___acl_aclcheck_file, "__acl_get_file", "%s(\"%s\", %d, %#x)", NULL, NULL },
++{ TARGET_FREEBSD_NR___acl_aclcheck_link, "__acl_get_link", "%s(\"%s\", %d, %#x)", NULL, NULL },
++{ TARGET_FREEBSD_NR___acl_delete_fd, "__acl_delete_fd", "%s(%d, %d)", NULL, NULL },
++{ TARGET_FREEBSD_NR___acl_delete_file, "__acl_delete_file", "%s(\"%s\", %d)", NULL, NULL },
++{ TARGET_FREEBSD_NR___acl_delete_link, "__acl_delete_link", "%s(\"%s\", %d)", NULL, NULL },
++{ TARGET_FREEBSD_NR___acl_get_fd, "__acl_get_fd", "%s(\"%s\", %d, %#x)", NULL, NULL },
++{ TARGET_FREEBSD_NR___acl_get_file, "__acl_get_file", "%s(\"%s\", %d, %#x)", NULL, NULL },
++{ TARGET_FREEBSD_NR___acl_get_link, "__acl_get_link", "%s(\"%s\", %d, %#x)", NULL, NULL },
++{ TARGET_FREEBSD_NR___acl_set_fd, "__acl_get_fd", "%s(\"%s\", %d, %#x)", NULL, NULL },
++{ TARGET_FREEBSD_NR___acl_set_file, "__acl_get_file", "%s(\"%s\", %d, %#x)", NULL, NULL },
++{ TARGET_FREEBSD_NR___acl_set_link, "__acl_get_link", "%s(\"%s\", %d, %#x)", NULL, NULL },
+ { TARGET_FREEBSD_NR___getcwd, "__getcwd", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR___semctl, "__semctl", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR___syscall, "__syscall", NULL, NULL, NULL },
+-{ TARGET_FREEBSD_NR___sysctl, "__sysctl", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR___sysctl, "__sysctl", NULL, print_sysctl, NULL },
+ { TARGET_FREEBSD_NR__umtx_op, "_umtx_op", "%s(%#x, %d, %d, %#x, %#x)", NULL, NULL },
+ { TARGET_FREEBSD_NR_accept, "accept", "%s(%d,%#x,%#x)", NULL, NULL },
+ { TARGET_FREEBSD_NR_access, "access", "%s(\"%s\",%#o)", NULL, NULL },
+@@ -23,19 +35,34 @@
+ { TARGET_FREEBSD_NR_dup2, "dup2", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_execve, "execve", NULL, print_execve, NULL },
+ { TARGET_FREEBSD_NR_exit, "exit", "%s(%d)\n", NULL, NULL },
++{ TARGET_FREEBSD_NR_extattrctl, "extattrctl", "%s(\"%s\", %d, \"%s\", %d, \"%s\"", NULL, NULL },
++{ TARGET_FREEBSD_NR_extattr_delete_fd, "extattr_delete_fd", "%s(%d, %d, \"%s\")", NULL, NULL },
++{ TARGET_FREEBSD_NR_extattr_delete_file, "extattr_delete_file", "%s(\"%s\", %d, \"%s\")", NULL, NULL },
++{ TARGET_FREEBSD_NR_extattr_delete_link, "extattr_delete_link", "%s(\"%s\", %d, \"%s\")", NULL, NULL },
++{ TARGET_FREEBSD_NR_extattr_get_fd, "extattr_get_fd", "%s(%d, %d, \"%s\", %#x, %d)", NULL, NULL },
++{ TARGET_FREEBSD_NR_extattr_get_file, "extattr_get_file", "%s(\"%s\", %d, \"%s\", %#x, %d)", NULL, NULL },
++{ TARGET_FREEBSD_NR_extattr_get_file, "extattr_get_link", "%s(\"%s\", %d, \"%s\", %#x, %d)", NULL, NULL },
++{ TARGET_FREEBSD_NR_extattr_list_fd, "extattr_list_fd", "%s(%d, %d, %#x, %d)", NULL, NULL },
++{ TARGET_FREEBSD_NR_extattr_list_file, "extattr_list_file", "%s(\"%s\", %#x, %d)", NULL, NULL },
++{ TARGET_FREEBSD_NR_extattr_list_link, "extattr_list_link", "%s(\"%s\", %d, %#x, %d)", NULL, NULL },
++{ TARGET_FREEBSD_NR_extattr_set_fd, "extattr_set_fd", "%s(%d, %d, \"%s\", %#x, %d)", NULL, NULL },
++{ TARGET_FREEBSD_NR_extattr_set_file, "extattr_set_file", "%s(\"%s\", %d, \"%s\", %#x, %d)", NULL, NULL },
++{ TARGET_FREEBSD_NR_extattr_set_link, "extattr_set_link", "%s(\"%s\", %d, \"%s\", %#x, %d)", NULL, NULL },
+ { TARGET_FREEBSD_NR_fchdir, "fchdir", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_fchflags, "fchflags", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_fchmod, "fchmod", "%s(%d,%#o)", NULL, NULL },
+ { TARGET_FREEBSD_NR_fchown, "fchown", "%s(\"%s\",%d,%d)", NULL, NULL },
+ { TARGET_FREEBSD_NR_fcntl, "fcntl", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_fexecve, "fexecve", NULL, print_execve, NULL },
+ { TARGET_FREEBSD_NR_fhopen, "fhopen", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_fhstat, "fhstat", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_fhstatfs, "fhstatfs", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_flock, "flock", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_fork, "fork", "%s()", NULL, NULL },
+ { TARGET_FREEBSD_NR_fpathconf, "fpathconf", NULL, NULL, NULL },
+-{ TARGET_FREEBSD_NR_fstat, "fstat", "%s(%d,%p)", NULL, NULL },
+-{ TARGET_FREEBSD_NR_fstatfs, "fstatfs", "%s(%d,%p)", NULL, NULL },
++{ TARGET_FREEBSD_NR_fstat, "fstat", "%s(%d,%#x)", NULL, NULL },
++{ TARGET_FREEBSD_NR_fstatat, "fstatat", "%s(%d,\"%s\", %#x)", NULL, NULL },
++{ TARGET_FREEBSD_NR_fstatfs, "fstatfs", "%s(%d,%#x)", NULL, NULL },
+ { TARGET_FREEBSD_NR_fsync, "fsync", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_ftruncate, "ftruncate", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_futimes, "futimes", NULL, NULL, NULL },
+@@ -65,7 +92,7 @@
+ { TARGET_FREEBSD_NR_getsockopt, "getsockopt", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_gettimeofday, "gettimeofday", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_getuid, "getuid", "%s()", NULL, NULL },
+-{ TARGET_FREEBSD_NR_ioctl, "ioctl", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_ioctl, "ioctl", NULL, print_ioctl, NULL },
+ { TARGET_FREEBSD_NR_issetugid, "issetugid", "%s()", NULL, NULL },
+ { TARGET_FREEBSD_NR_kevent, "kevent", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_kill, "kill", NULL, NULL, NULL },
+@@ -74,6 +101,7 @@
+ { TARGET_FREEBSD_NR_lchown, "lchown", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_link, "link", "%s(\"%s\",\"%s\")", NULL, NULL },
+ { TARGET_FREEBSD_NR_listen, "listen", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_lpathconf, "lpathconf", "%s(\"%s\", %d)", NULL, NULL },
+ { TARGET_FREEBSD_NR_lseek, "lseek", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_lstat, "lstat", "%s(\"%s\",%p)", NULL, NULL },
+ { TARGET_FREEBSD_NR_madvise, "madvise", NULL, NULL, NULL },
+@@ -98,7 +126,9 @@
+ { TARGET_FREEBSD_NR_nanosleep, "nanosleep", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_nfssvc, "nfssvc", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_open, "open", "%s(\"%s\",%#x,%#o)", NULL, NULL },
++{ TARGET_FREEBSD_NR_openat, "openat", "%s(%d, \"%s\",%#x,%#o)", NULL, NULL },
+ { TARGET_FREEBSD_NR_pathconf, "pathconf", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_pathconf, "pathconf", "%s(\"%s\", %d)", NULL, NULL },
+ { TARGET_FREEBSD_NR_pipe, "pipe", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_poll, "poll", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_pread, "pread", NULL, NULL, NULL },
+@@ -162,7 +192,7 @@
+ { TARGET_FREEBSD_NR_statfs, "statfs", "%s(\"%s\",%p)", NULL, NULL },
+ { TARGET_FREEBSD_NR_symlink, "symlink", "%s(\"%s\",\"%s\")", NULL, NULL },
+ { TARGET_FREEBSD_NR_sync, "sync", NULL, NULL, NULL },
+-{ TARGET_FREEBSD_NR_sysarch, "sysarch", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_sysarch, "sysarch", NULL, print_sysarch, NULL },
+ { TARGET_FREEBSD_NR_syscall, "syscall", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_thr_create, "thr_create", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_thr_exit, "thr_exit", NULL, NULL, NULL },
+diff --git a/bsd-user/freebsd/syscall_types.h b/bsd-user/freebsd/syscall_types.h
+index 6e43400..60b9288 100644
+--- a/bsd-user/freebsd/syscall_types.h
++++ b/bsd-user/freebsd/syscall_types.h
+@@ -1,8 +1,7 @@
+-#ifndef _FREEBSD_SYSCALL_TYPES_H_
+-#define _FREEBSD_SYSCALL_TYPES_H_
+
+ STRUCT_SPECIAL(termios)
+
+ STRUCT(winsize, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT)
+
+-#endif
++STRUCT(fiodgname_arg, TYPE_INT, TYPE_PTRVOID)
++
+diff --git a/bsd-user/main.c b/bsd-user/main.c
+index 32bd3e5..bb614de 100644
+--- a/bsd-user/main.c
++++ b/bsd-user/main.c
+@@ -2,6 +2,7 @@
+ * qemu user main
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
++ * Copyright (c) 2012-2013 Stacey Son
+ *
+ * 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
+@@ -25,6 +26,7 @@
+ #include <machine/trap.h>
+ #include <sys/types.h>
+ #include <sys/mman.h>
++#include <sys/sysctl.h>
+
+ #include "qemu.h"
+ #include "qemu-common.h"
+@@ -58,6 +60,36 @@ enum BSDType bsd_type;
+ by remapping the process stack directly at the right place */
+ unsigned long x86_stack_size = 512 * 1024;
+
++static void save_proc_pathname(void);
++char qemu_proc_pathname[PATH_MAX];
++
++#ifdef __FreeBSD__
++static void
++save_proc_pathname(void)
++{
++ int mib[4];
++ size_t len;
++
++ mib[0] = CTL_KERN;
++ mib[1] = KERN_PROC;
++ mib[2] = KERN_PROC_PATHNAME;
++ mib[3] = -1;
++
++ len = sizeof(qemu_proc_pathname);
++
++ if (sysctl(mib, 4, qemu_proc_pathname, &len, NULL, 0))
++ perror("sysctl");
++}
++
++#else
++
++static void
++save_proc_pathname(void)
++{
++}
++
++#endif /* !__FreeBSD__ */
++
+ void gemu_log(const char *fmt, ...)
+ {
+ va_list ap;
+@@ -1496,6 +1528,8 @@ int main(int argc, char **argv)
+ if (argc <= 1)
+ usage();
+
++ save_proc_pathname();
++
+ module_call_init(MODULE_INIT_QOM);
+
+ if ((envlist = envlist_create()) == NULL) {
+diff --git a/bsd-user/mips64/target_signal.h b/bsd-user/mips64/target_signal.h
+index e9c8a9f..c592136 100644
+--- a/bsd-user/mips64/target_signal.h
++++ b/bsd-user/mips64/target_signal.h
+@@ -65,13 +65,7 @@ set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
+ abi_ulong frame_addr, struct target_sigaction *ka)
+ {
+
+- frame->sf_signum = sig;
+- frame->sf_siginfo = 0;
+- frame->sf_ucontext = 0;
+-
+- frame->sf_si.si_signo = sig;
+- frame->sf_si.si_code = TARGET_SA_SIGINFO;
+- frame->sf_si.si_addr = regs->CP0_BadVAddr;
++ /* frame->sf_si.si_addr = regs->CP0_BadVAddr; */
+
+ /*
+ * Arguments to signal handler:
+@@ -86,6 +80,8 @@ set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
+ regs->active_tc.gpr[ 4] = sig;
+ regs->active_tc.gpr[ 5] = frame_addr +
+ offsetof(struct target_sigframe, sf_si);
++ regs->active_tc.gpr[ 6] = frame_addr +
++ offsetof(struct target_sigframe, sf_uc);
+ regs->active_tc.gpr[25] = regs->active_tc.PC = ka->_sa_handler;
+ regs->active_tc.gpr[29] = frame_addr;
+ regs->active_tc.gpr[31] = TARGET_PS_STRINGS - TARGET_SZSIGCODE;
+diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
+index d9c9934..110b54e 100644
+--- a/bsd-user/qemu.h
++++ b/bsd-user/qemu.h
+@@ -64,15 +64,15 @@ struct image_info {
+
+ #define MAX_SIGQUEUE_SIZE 1024
+
+-struct sigqueue {
+- struct sigqueue *next;
++struct qemu_sigqueue {
++ struct qemu_sigqueue *next;
+ target_siginfo_t info;
+ };
+
+ struct emulated_sigtable {
+ int pending; /* true if signal is pending */
+- struct sigqueue *first;
+- struct sigqueue info; /* in order to always have memory for the
++ struct qemu_sigqueue *first;
++ struct qemu_sigqueue info; /* in order to always have memory for the
+ first signal, we put it here */
+ };
+
+@@ -95,8 +95,8 @@ typedef struct TaskState {
+ struct bsd_binprm *bprm;
+
+ struct emulated_sigtable sigtab[TARGET_NSIG];
+- struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
+- struct sigqueue *first_free; /* first free siginfo queue entry */
++ struct qemu_sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
++ struct qemu_sigqueue *first_free; /* first free siginfo queue entry */
+ int signal_pending; /* non zero if a signal may be pending */
+
+ uint8_t stack[0];
+@@ -146,6 +146,7 @@ int load_elf_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs,
+ struct image_info * info);
+ int load_flt_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs,
+ struct image_info * info);
++int is_target_elf_binary(int fd);
+
+ void target_set_brk(abi_ulong new_brk);
+ abi_long do_brk(abi_ulong new_brk);
+@@ -222,6 +223,7 @@ void mmap_fork_end(int child);
+
+ /* main.c */
+ extern unsigned long x86_stack_size;
++extern char qemu_proc_pathname[];
+
+ /* user access */
+
+diff --git a/bsd-user/signal.c b/bsd-user/signal.c
+index d56837b..29e8e12 100644
+--- a/bsd-user/signal.c
++++ b/bsd-user/signal.c
+@@ -77,7 +77,7 @@ static uint8_t host_to_target_signal_table[_NSIG] = {
+ [SIGUSR1] = TARGET_SIGUSR1,
+ [SIGUSR2] = TARGET_SIGUSR2,
+ #ifdef SIGTHR
+- [SIGTHR] = TARGET_SIGTHR,
++ [SIGTHR + 3] = TARGET_SIGTHR,
+ #endif
+ /* [SIGLWP] = TARGET_SIGLWP, */
+ #ifdef SIGLIBRT
+@@ -207,9 +207,10 @@ target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
+ static inline void
+ host_to_target_siginfo_noswap(target_siginfo_t *tinfo, const siginfo_t *info)
+ {
+- int sig;
++ int sig, code;
+
+ sig = host_to_target_signal(info->si_signo);
++ code = tswap32(info->si_code); /* XXX should have host_to_target_si_code() */
+ tinfo->si_signo = sig;
+ tinfo->si_errno = info->si_errno;
+ tinfo->si_code = info->si_code;
+@@ -222,11 +223,13 @@ host_to_target_siginfo_noswap(target_siginfo_t *tinfo, const siginfo_t *info)
+ if (SIGILL == sig || SIGFPE == sig || SIGSEGV == sig ||
+ SIGBUS == sig || SIGTRAP == sig) {
+ tinfo->_reason._fault._trapno = info->_reason._fault._trapno;
++ }
+ #ifdef SIGPOLL
+- } else if (SIGPOLL == sig) {
++ if (SIGPOLL == sig) {
+ tinfo->_reason._poll._band = info->_reason._poll._band;
++ }
+ #endif
+- } else {
++ if (SI_TIMER == code) {
+ tinfo->_reason._timer._timerid = info->_reason._timer._timerid;
+ tinfo->_reason._timer._overrun = info->_reason._timer._overrun;
+ }
+@@ -235,8 +238,10 @@ host_to_target_siginfo_noswap(target_siginfo_t *tinfo, const siginfo_t *info)
+ static void
+ tswap_siginfo(target_siginfo_t *tinfo, const target_siginfo_t *info)
+ {
+- int sig;
++ int sig, code;
++
+ sig = info->si_signo;
++ code = info->si_code;
+ tinfo->si_signo = tswap32(sig);
+ tinfo->si_errno = tswap32(info->si_errno);
+ tinfo->si_code = tswap32(info->si_code);
+@@ -247,11 +252,13 @@ tswap_siginfo(target_siginfo_t *tinfo, const target_siginfo_t *info)
+ SIGBUS == sig || SIGTRAP == sig) {
+ tinfo->_reason._fault._trapno =
+ tswap32(info->_reason._fault._trapno);
++ }
+ #ifdef SIGPOLL
+- } else if (SIGPOLL == sig) {
++ if (SIGPOLL == sig) {
+ tinfo->_reason._poll._band = tswap32(info->_reason._poll._band);
++ }
+ #endif
+- } else {
++ if (SI_TIMER == code) {
+ tinfo->_reason._timer._timerid =
+ tswap32(info->_reason._timer._timerid);
+ tinfo->_reason._timer._overrun =
+@@ -286,11 +293,11 @@ core_dump_signal(int sig)
+ }
+
+ /* Signal queue handling. */
+-static inline struct sigqueue *
++static inline struct qemu_sigqueue *
+ alloc_sigqueue(CPUArchState *env)
+ {
+ TaskState *ts = env->opaque;
+- struct sigqueue *q = ts->first_free;
++ struct qemu_sigqueue *q = ts->first_free;
+
+ if (!q)
+ return (NULL);
+@@ -299,7 +306,7 @@ alloc_sigqueue(CPUArchState *env)
+ }
+
+ static inline void
+-free_sigqueue(CPUArchState *env, struct sigqueue *q)
++free_sigqueue(CPUArchState *env, struct qemu_sigqueue *q)
+ {
+
+ TaskState *ts = env->opaque;
+@@ -372,7 +379,7 @@ queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
+ {
+ TaskState *ts = env->opaque;
+ struct emulated_sigtable *k;
+- struct sigqueue *q, **pq;
++ struct qemu_sigqueue *q, **pq;
+ abi_ulong handler;
+ int queue;
+
+@@ -606,7 +613,7 @@ do_sigaction(int sig, const struct target_sigaction *act,
+ return (ret);
+ }
+
+-#if defined(TARGET_MIPS) || defined(TARGET_SPARC64)
++#if defined(TARGET_MIPS64) /* || defined(TARGET_SPARC64) */
+
+ static inline abi_ulong
+ get_sigframe(struct target_sigaction *ka, CPUArchState *regs, size_t frame_size)
+@@ -629,8 +636,8 @@ get_sigframe(struct target_sigaction *ka, CPUArchState *regs, size_t frame_size)
+ }
+
+ /* compare to mips/mips/pm_machdep.c and sparc64/sparc64/machdep.c sendsig() */
+-static void setup_frame(int sig, struct target_sigaction *ka,
+- target_sigset_t *set, CPUArchState *regs)
++static void setup_frame(int sig, int code, struct target_sigaction *ka,
++ target_sigset_t *set, target_siginfo_t *tinfo, CPUArchState *regs)
+ {
+ struct target_sigframe *frame;
+ abi_ulong frame_addr;
+@@ -651,6 +658,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
+ goto give_sigsegv;
+
++ memset(frame, 0, sizeof(*frame));
+ #if defined(TARGET_MIPS)
+ int mflags = on_sig_stack(frame_addr) ? TARGET_MC_ADD_MAGIC :
+ TARGET_MC_SET_ONSTACK | TARGET_MC_ADD_MAGIC;
+@@ -666,6 +674,58 @@ static void setup_frame(int sig, struct target_sigaction *ka,
+ goto give_sigsegv;
+ }
+
++ if (tinfo) {
++ frame->sf_si.si_signo = tinfo->si_signo;
++ frame->sf_si.si_errno = tinfo->si_errno;
++ frame->sf_si.si_code = tinfo->si_code;
++ frame->sf_si.si_pid = tinfo->si_pid;
++ frame->sf_si.si_uid = tinfo->si_uid;
++ frame->sf_si.si_status = tinfo->si_status;
++ frame->sf_si.si_addr = tinfo->si_addr;
++
++ if (TARGET_SIGILL == sig || TARGET_SIGFPE == sig ||
++ TARGET_SIGSEGV == sig || TARGET_SIGBUS == sig ||
++ TARGET_SIGTRAP == sig)
++ frame->sf_si._reason._fault._trapno =
++ tinfo->_reason._fault._trapno;
++
++ /*
++ * If si_code is one of SI_QUEUE, SI_TIMER, SI_ASYNCIO, or
++ * SI_MESGQ, then si_value contains the application-specified
++ * signal value. Otherwise, the contents of si_value are
++ * undefined.
++ */
++ if (SI_QUEUE == code || SI_TIMER == code ||
++ SI_ASYNCIO == code || SI_MESGQ == code) {
++ frame->sf_si.si_value.sival_int =
++ tinfo->si_value.sival_int;
++ }
++
++ if (SI_TIMER == code) {
++ frame->sf_si._reason._timer._timerid =
++ tinfo->_reason._timer._timerid;
++ frame->sf_si._reason._timer._overrun =
++ tinfo->_reason._timer._overrun;
++ }
++
++#ifdef SIGPOLL
++ if (SIGPOLL == sig) {
++ frame->sf_si._reason._band =
++ tinfo->_reason._band;
++ }
++#endif
++
++ frame->sf_signum = sig;
++ frame->sf_siginfo = (abi_ulong)&frame->sf_si;
++ frame->sf_ucontext = (abi_ulong)&frame->sf_uc;
++
++ } else {
++ frame->sf_signum = sig;
++ frame->sf_siginfo = 0;
++ frame->sf_ucontext = 0;
++ }
++
++
+ if (set_sigtramp_args(regs, sig, frame, frame_addr, ka))
+ goto give_sigsegv;
+
+@@ -866,8 +926,8 @@ get_sigframe(struct target_sigaction *ka, CPUSPARCState *regs, size_t frame_size
+ }
+
+ /* compare to sparc64/sparc64/machdep.c sendsig() */
+-static void setup_frame(int sig, struct target_sigaction *ka,
+- target_sigset_t *set, CPUSPARCState *regs)
++static void setup_frame(int sig, int code, struct target_sigaction *ka,
++ target_sigset_t *set, target_siginfo_t *tinfo, CPUSPARCState *regs)
+ {
+ struct target_sigframe *frame;
+ abi_ulong frame_addr;
+@@ -960,21 +1020,12 @@ badframe:
+ #else
+
+ static void
+-setup_frame(int sig, struct target_sigaction *ka, target_sigset_t *set,
+- CPUArchState *env)
++setup_frame(int sig, int code, struct target_sigaction *ka, target_sigset_t *set,
++ target_siginfo_t *tinfo, CPUArchState *env)
+ {
+ fprintf(stderr, "setup_frame: not implemented\n");
+ }
+
+-#if 0
+-static void
+-setup_rt_frame(int sig, struct target_sigaction *ka, target_siginfo_t *info,
+- target_sigset_t *set, CPUArchState *env)
+-{
+- fprintf(stderr, "setup_rt_frame: not implemented\n");
+-}
+-#endif
+-
+ long
+ do_sigreturn(CPUArchState *env, abi_ulong uc_addr)
+ {
+@@ -1043,13 +1094,14 @@ signal_init(void)
+ void
+ process_pending_signals(CPUArchState *cpu_env)
+ {
+- int sig;
++ int sig, code;
+ abi_ulong handler;
+ sigset_t set, old_set;
+ target_sigset_t target_old_set;
++ target_siginfo_t tinfo;
+ struct emulated_sigtable *k;
+ struct target_sigaction *sa;
+- struct sigqueue *q;
++ struct qemu_sigqueue *q;
+ TaskState *ts = cpu_env->opaque;
+
+ if (!ts->signal_pending)
+@@ -1143,14 +1195,16 @@ handle_signal:
+ }
+ #endif
+ #endif
++ code = q->info.si_code;
+ /* prepare the stack frame of the virtual CPU */
+-#if 0 /* XXX no rt for fbsd */
+- if (sa->sa_flags & TARGET_SA_SIGINFO)
+- setup_rt_frame(sig, sa, &q->info, &target_old_set,
++ if (sa->sa_flags & TARGET_SA_SIGINFO) {
++ tswap_siginfo(&tinfo, &q->info);
++ setup_frame(sig, code, sa, &target_old_set, &tinfo,
+ cpu_env);
+- else
+-#endif
+- setup_frame(sig, sa, &target_old_set, cpu_env);
++ } else {
++ setup_frame(sig, code, sa, &target_old_set, NULL,
++ cpu_env);
++ }
+ if (sa->sa_flags & TARGET_SA_RESETHAND)
+ sa->_sa_handler = TARGET_SIG_DFL;
+ }
+diff --git a/bsd-user/strace.c b/bsd-user/strace.c
+index d73bbca..7f0f7bd 100644
+--- a/bsd-user/strace.c
++++ b/bsd-user/strace.c
+@@ -4,7 +4,12 @@
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <sys/syscall.h>
++#include <sys/ioccom.h>
++#include <ctype.h>
+ #include "qemu.h"
++#ifdef __FreeBSD__
++#include "freebsd/syscall_nr.h"
++#endif
+
+ int do_strace=0;
+
+@@ -23,6 +28,29 @@ struct syscallname {
+ */
+
+ static void
++print_sysctl(const struct syscallname *name,
++ abi_long arg1, abi_long arg2, abi_long arg3,
++ abi_long arg4, abi_long arg5, abi_long arg6)
++{
++ uint32_t i;
++ int32_t *namep;
++
++
++ gemu_log("%s({ ", name->name);
++ namep = lock_user(VERIFY_READ, arg1, sizeof(int32_t) * arg2, 1);
++ if (namep) {
++ int32_t *p = namep;
++
++ for(i = 0; i < (uint32_t)arg2; i++)
++ gemu_log("%d ", tswap32(*p++));
++ unlock_user(namep, arg1, 0);
++ }
++ gemu_log("}, %u, 0x" TARGET_ABI_FMT_lx ", 0x" TARGET_ABI_FMT_lx ", 0x"
++ TARGET_ABI_FMT_lx ", 0x" TARGET_ABI_FMT_lx ")",
++ (uint32_t)arg2, arg3, arg4, arg5, arg6);
++}
++
++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)
+@@ -30,10 +58,18 @@ print_execve(const struct syscallname *name,
+ 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);
++#ifdef __FreeBSD__
++ if (TARGET_FREEBSD_NR_fexecve == name->nr) {
++ gemu_log("%s(%d,{", name->name, (int)arg1);
++
++ } else
++#endif
++ {
++ 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;
+@@ -54,6 +90,54 @@ print_execve(const struct syscallname *name,
+ gemu_log("NULL})");
+ }
+
++static void
++print_ioctl(const struct syscallname *name,
++ abi_long arg1, abi_long arg2, abi_long arg3,
++ abi_long arg4, abi_long arg5, abi_long arg6)
++{
++ /* Decode the ioctl request */
++ gemu_log("%s(%d, 0x%0lx { IO%s%s GRP:0x%x('%c') CMD:%d LEN:%d }, 0x"
++ TARGET_ABI_FMT_lx ", ...)",
++
++ name->name,
++ (int)arg1,
++ (unsigned long)arg2,
++ arg2 & IOC_OUT ? "R" : "",
++ arg2 & IOC_IN ? "W" : "",
++ (unsigned)IOCGROUP(arg2),
++ isprint(IOCGROUP(arg2)) ? (char)IOCGROUP(arg2) : '?',
++ (int)arg2 & 0xFF,
++ (int)IOCPARM_LEN(arg2),
++ arg3);
++}
++
++static void
++print_sysarch(const struct syscallname *name,
++ abi_long arg1, abi_long arg2, abi_long arg3,
++ abi_long arg4, abi_long arg5, abi_long arg6)
++{
++#ifdef TARGET_MIPS
++ switch(arg1) {
++ case 1:
++ gemu_log("%s(SET_TLS, 0x" TARGET_ABI_FMT_lx ")",
++ name->name, arg2);
++ break;
++
++ case 2:
++ gemu_log("%s(GET_TLS, 0x" TARGET_ABI_FMT_lx ")",
++ name->name, arg2);
++ break;
++
++ default:
++ gemu_log("UNKNOWN OP: %d, " TARGET_ABI_FMT_lx ")",
++ (int)arg1, arg2);
++ }
++#else
++ gemu_log("%s(%d, " TARGET_ABI_FMT_lx ", " TARGET_ABI_FMT_lx ", "
++ TARGET_ABI_FMT_lx ")", name->name, (int)arg1, arg2, arg3, arg4);
++#endif
++}
++
+ /*
+ * Variants for the return value output function
+ */
+diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
+index 8565ae8..74b5c86 100644
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -2,7 +2,7 @@
+ * BSD syscalls
+ *
+ * Copyright (c) 2003 - 2008 Fabrice Bellard
+- * Copyright (c) 2012 Stacey Son <sson@FreeBSD.org>
++ * Copyright (c) 2012 - 2013 Stacey Son <sson@FreeBSD.org>
+ *
+ * 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
+@@ -33,6 +33,7 @@
+ #include <stdio.h>
+ #include <stdint.h>
+ #include <stdarg.h>
++#include <stddef.h>
+ #include <string.h>
+ #include <dirent.h>
+ #include <errno.h>
+@@ -68,8 +69,12 @@
+ #include <sys/termios.h>
+ #endif
+ #include <sys/ttycom.h>
++#include <sys/filio.h>
+ #include <sys/reboot.h>
+ #include <sys/timex.h>
++#define _ACL_PRIVATE
++#include <sys/acl.h>
++#include <sys/extattr.h>
+ #include <kenv.h>
+ #include <pthread.h>
+ #include <machine/atomic.h>
+@@ -87,6 +92,7 @@
+ #include "qemu-common.h"
+ #ifdef __FreeBSD__
+ #include "freebsd/ttycom.h"
++#include "freebsd/filio.h"
+ #endif
+
+
+@@ -95,6 +101,70 @@
+ static abi_ulong target_brk;
+ static abi_ulong target_original_brk;
+
++static char *get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len);
++
++#ifdef __FreeBSD__
++#include <sys/queue.h>
++#include <sys/user.h>
++#include <libprocstat.h>
++
++
++/*
++ * Get the filename for the given file descriptor.
++ * Note that this may return NULL (fail) if no longer cached in the kernel.
++ */
++static char *
++get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len)
++{
++ unsigned int cnt;
++ struct procstat *procstat = NULL;
++ struct kinfo_proc *kipp = NULL;
++ struct filestat_list *head = NULL;
++ struct filestat *fst;
++ char *ret = NULL;
++
++ procstat = procstat_open_sysctl();
++ if (NULL == procstat)
++ goto out;
++
++ kipp = procstat_getprocs(procstat, KERN_PROC_PID, pid, &cnt);
++ if (NULL == kipp)
++ goto out;
++
++ head = procstat_getfiles(procstat, kipp, 0);
++ if (NULL == head)
++ goto out;
++
++ STAILQ_FOREACH(fst, head, next) {
++ if (fd == fst->fs_fd) {
++ if (fst->fs_path != NULL) {
++ (void)strlcpy(filename, fst->fs_path, len);
++ ret = filename;
++ }
++ break;
++ }
++ }
++
++out:
++ if (head != NULL)
++ procstat_freefiles(procstat, head);
++ if (kipp != NULL)
++ procstat_freeprocs(procstat, kipp);
++ if (procstat != NULL)
++ procstat_close(procstat);
++ return (ret);
++}
++
++#else
++
++static char *
++get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len)
++{
++ return (NULL);
++}
++
++#endif /* ! __FreeBSD__ */
++
+ static inline abi_long get_errno(abi_long ret)
+ {
+ if (ret == -1)
+@@ -297,9 +367,9 @@ static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
+
+ switch(op) {
+ case TARGET_MIPS_SET_TLS:
+- if (get_user(mips_env->tls_value, parms, abi_ulong))
+- ret = -TARGET_EFAULT;
++ mips_env->tls_value = parms;
+ break;
++
+ case TARGET_MIPS_GET_TLS:
+ if (put_user(mips_env->tls_value, parms, abi_ulong))
+ ret = -TARGET_EFAULT;
+@@ -386,24 +456,46 @@ static int sysctl_oldcvt(void *holdp, size_t holdlen, uint32_t kind)
+ return 0;
+ }
+
++/*
++ * Convert the undocmented name2oid sysctl data for the target.
++ */
++static inline void
++sysctl_name2oid(uint32_t *holdp, size_t holdlen)
++{
++ size_t i;
++
++ for(i = 0; i < holdlen; i++)
++ holdp[i] = tswap32(holdp[i]);
++}
++
++static inline void
++sysctl_oidfmt(uint32_t *holdp)
++{
++ /* byte swap the kind */
++ holdp[0] = tswap32(holdp[0]);
++}
++
+ /* XXX this needs to be emulated on non-FreeBSD hosts... */
+ static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong oldp,
+ abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen)
+ {
+ abi_long ret;
+- void *hnamep, *holdp, *hnewp = NULL;
++ void *hnamep, *holdp = NULL, *hnewp = NULL;
+ size_t holdlen;
+ abi_ulong oldlen = 0;
+ int32_t *snamep = g_malloc(sizeof(int32_t) * namelen), *p, *q, i;
+ uint32_t kind = 0;
++ abi_ulong argv, argv0;
++ char *fullpath = NULL;
+
+ if (oldlenp)
+- get_user_ual(oldlen, oldlenp);
++ if (get_user_ual(oldlen, oldlenp))
++ return -TARGET_EFAULT;
+ if (!(hnamep = lock_user(VERIFY_READ, namep, namelen, 1)))
+ return -TARGET_EFAULT;
+ if (newp && !(hnewp = lock_user(VERIFY_READ, newp, newlen, 1)))
+ return -TARGET_EFAULT;
+- if (!(holdp = lock_user(VERIFY_WRITE, oldp, oldlen, 0)))
++ if (oldp && !(holdp = lock_user(VERIFY_WRITE, oldp, oldlen, 0)))
+ return -TARGET_EFAULT;
+ holdlen = oldlen;
+ for (p = hnamep, q = snamep, i = 0; i < namelen; p++, i++)
+@@ -411,7 +503,8 @@ static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong ol
+ oidfmt(snamep, namelen, NULL, &kind);
+
+ /* Handle some arch/emulator dependent sysctl()'s here. */
+- if (CTL_KERN == snamep[0]) {
++ switch(snamep[0]) {
++ case CTL_KERN:
+ switch(snamep[1]) {
+ case KERN_USRSTACK:
+ #if defined(TARGET_ARM) && HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32
+@@ -437,17 +530,77 @@ static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong ol
+ #endif
+ goto out;
+
++ case KERN_PROC:
++ switch(snamep[2]) {
++ case KERN_PROC_PATHNAME:
++ if (get_user_ual(argv, TARGET_PS_STRINGS)) {
++ ret = -TARGET_EFAULT;
++ goto out;
++ }
++ if (get_user_ual(argv0, argv)) {
++ ret = -TARGET_EFAULT;
++ goto out;
++ }
++
++ fullpath = realpath(g2h(argv0), NULL);
++ if (NULL == fullpath)
++ fullpath = (char *)g2h(argv0);
++ holdlen = strlen(fullpath) + 1;
++ if (holdp) {
++ if (oldlen < holdlen) {
++ ret = -TARGET_EINVAL;
++ goto out;
++ }
++ if (!access_ok(VERIFY_WRITE, argv0,
++ holdlen)) {
++ ret = -TARGET_EFAULT;
++ goto out;
++ }
++ strlcpy(holdp, fullpath, oldlen);
++ }
++ ret = 0;
++ goto out;
++
++ default:
++ break;
++ }
++ break;
++
+ default:
+ break;
+ }
++ break;
++
++ default:
++ break;
+ }
+
+ ret = get_errno(sysctl(snamep, namelen, holdp, &holdlen, hnewp, newlen));
+- if (!ret)
+- sysctl_oldcvt(holdp, holdlen, kind);
++ if (!ret && (holdp != 0 && holdlen != 0)) {
++ if (0 == snamep[0] && (3 == snamep[1] || 4 == snamep[1])) {
++ if (3 == snamep[1]) {
++ /* Handle the undocumented name2oid special case. */
++ sysctl_name2oid(holdp, holdlen);
++ } else {
++ /* Handle oidfmt */
++ sysctl_oidfmt(holdp);
++ }
++ } else {
++ sysctl_oldcvt(holdp, holdlen, kind);
++ }
++ }
++#ifdef DEBUG
++ else {
++ printf("sysctl(mib[0]=%d, mib[1]=%d, mib[3]=%d...) returned %d\n",
++ snamep[0], snamep[1], snamep[2], (int)ret);
++ }
++#endif
+
+ out:
+- put_user_ual(holdlen, oldlenp);
++ if (fullpath)
++ free(fullpath);
++ if (oldlenp)
++ put_user_ual(holdlen, oldlenp);
+ unlock_user(hnamep, namep, 0);
+ unlock_user(holdp, oldp, holdlen);
+ if (hnewp)
+@@ -509,6 +662,24 @@ static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
+ }
+
+ static inline abi_long
++target_to_host_ip_mreq(struct ip_mreqn *mreqn, abi_ulong target_addr,
++ socklen_t len)
++{
++ struct target_ip_mreqn *target_smreqn;
++
++ target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
++ if (!target_smreqn)
++ return -TARGET_EFAULT;
++ mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
++ mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
++ if (len == sizeof(struct target_ip_mreqn))
++ mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
++ unlock_user(target_smreqn, target_addr, 0);
++
++ return (0);
++}
++
++static inline abi_long
+ target_to_host_sockaddr(struct sockaddr *addr, abi_ulong target_addr,
+ socklen_t len)
+ {
+@@ -1554,11 +1725,62 @@ int_case:
+ }
+ break;
+
++ case IPPROTO_TCP:
++ /* TCP options all take an 'int' value. */
++ goto int_case;
++
++ case IPPROTO_IP:
++ switch(optname) {
++ case IP_HDRINCL:
++ case IP_TOS:
++ case IP_TTL:
++ case IP_RECVOPTS:
++ case IP_RECVRETOPTS:
++ case IP_RECVDSTADDR:
++
++ case IP_RETOPTS:
++ case IP_RECVTOS:
++ case IP_MULTICAST_TTL:
++ case IP_MULTICAST_LOOP:
++ case IP_PORTRANGE:
++ case IP_IPSEC_POLICY:
++ case IP_FAITH:
++ case IP_ONESBCAST:
++ case IP_BINDANY:
++ if (get_user_u32(len, optlen))
++ return (-TARGET_EFAULT);
++ if (len < 0)
++ return (-TARGET_EINVAL);
++ lv = sizeof(lv);
++ ret = get_errno(getsockopt(sockfd, level, optname,
++ &val, &lv));
++ if (ret < 0)
++ return (ret);
++ if (len < sizeof(int) && len > 0 && val >= 0 &&
++ val < 255) {
++ len = 1;
++ if (put_user_u32(len, optlen)
++ || put_user_u8(val, optval_addr))
++ return (-TARGET_EFAULT);
++ } else {
++ if (len > sizeof(int))
++ len = sizeof(int);
++ if (put_user_u32(len, optlen)
++ || put_user_u32(val, optval_addr))
++ return (-TARGET_EFAULT);
++ }
++ break;
++
++ default:
++ goto unimplemented;
++ }
++ break;
++
+ default:
+ unimplemented:
+ gemu_log("getsockopt level=%d optname=%d not yet supported\n",
+ level, optname);
+- ret = -TARGET_EOPNOTSUPP;
++ ret = (-TARGET_EOPNOTSUPP);
+ break;
+ }
+ return (ret);
+@@ -1569,10 +1791,67 @@ static abi_long
+ do_setsockopt(int sockfd, int level, int optname, abi_ulong optval_addr,
+ socklen_t optlen)
+ {
+- int val;
+ abi_long ret;
++ int val;
++ struct ip_mreqn *ip_mreq;
+
+ switch(level) {
++ case IPPROTO_TCP:
++ /* TCP options all take an 'int' value. */
++ if (optlen < sizeof(uint32_t))
++ return (-TARGET_EINVAL);
++
++ if (get_user_u32(val, optval_addr))
++ return (-TARGET_EFAULT);
++ ret = get_errno(setsockopt(sockfd, level, optname, &val,
++ sizeof(val)));
++ break;
++
++ case IPPROTO_IP:
++ switch (optname) {
++ case IP_HDRINCL:/* int; header is included with data */
++ case IP_TOS: /* int; IP type of service and preced. */
++ case IP_TTL: /* int; IP time to live */
++ case IP_RECVOPTS: /* bool; receive all IP opts w/dgram */
++ case IP_RECVRETOPTS: /* bool; receive IP opts for response */
++ case IP_RECVDSTADDR: /* bool; receive IP dst addr w/dgram */
++ case IP_MULTICAST_IF:/* u_char; set/get IP multicast i/f */
++ case IP_MULTICAST_TTL:/* u_char; set/get IP multicast ttl */
++ case IP_MULTICAST_LOOP:/*u_char;set/get IP multicast loopback */
++ case IP_PORTRANGE: /* int; range to choose for unspec port */
++ case IP_RECVIF: /* bool; receive reception if w/dgram */
++ case IP_IPSEC_POLICY: /* int; set/get security policy */
++ case IP_FAITH: /* bool; accept FAITH'ed connections */
++ case IP_RECVTTL: /* bool; receive reception TTL w/dgram */
++ val = 0;
++ if (optlen >= sizeof(uint32_t)) {
++ if (get_user_u32(val, optval_addr))
++ return (-TARGET_EFAULT);
++ } else if (optlen >= 1) {
++ if (get_user_u8(val, optval_addr))
++ return (-TARGET_EFAULT);
++ }
++ ret = get_errno(setsockopt(sockfd, level, optname,
++ &val, sizeof(val)));
++ break;
++
++ case IP_ADD_MEMBERSHIP: /*ip_mreq; add an IP group membership */
++ case IP_DROP_MEMBERSHIP:/*ip_mreq; drop an IP group membership*/
++ if (optlen < sizeof (struct target_ip_mreq) ||
++ optlen > sizeof (struct target_ip_mreqn))
++ return (-TARGET_EINVAL);
++ ip_mreq = (struct ip_mreqn *) alloca(optlen);
++ target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
++ ret = get_errno(setsockopt(sockfd, level, optname,
++ ip_mreq, optlen));
++ break;
++
++ default:
++ goto unimplemented;
++ }
++ break;
++
++
+ case TARGET_SOL_SOCKET:
+ switch (optname) {
+ /* Options with 'int' argument. */
+@@ -1730,13 +2009,15 @@ target_to_host_semarray(int semid, unsigned short **host_array,
+ if (ret == -1)
+ return (get_errno(ret));
+ nsems = semid_ds.sem_nsems;
+- *host_array = malloc(nsems * sizeof(unsigned short));
++ *host_array = (unsigned short *)malloc(nsems * sizeof(unsigned short));
+ array = lock_user(VERIFY_READ, target_addr,
+ nsems*sizeof(unsigned short), 1);
+- if (!array)
++ if (!array) {
++ free(*host_array);
+ return (-TARGET_EFAULT);
++ }
+ for(i=0; i<nsems; i++) {
+- __get_user((*host_array)[i], &array[i]);
++ (*host_array)[i] = array[i];
+ }
+ unlock_user(array, target_addr, 0);
+
+@@ -1756,18 +2037,21 @@ host_to_target_semarray(int semid, abi_ulong target_addr,
+ semun.buf = &semid_ds;
+
+ ret = semctl(semid, 0, IPC_STAT, semun);
+- if (ret == -1)
++ if (ret == -1) {
++ free(*host_array);
+ return get_errno(ret);
++ }
+
+ nsems = semid_ds.sem_nsems;
+-
+- array = lock_user(VERIFY_WRITE, target_addr,
++ array = (unsigned short *)lock_user(VERIFY_WRITE, target_addr,
+ nsems*sizeof(unsigned short), 0);
+- if (!array)
++ if (!array) {
++ free(*host_array);
+ return (-TARGET_EFAULT);
++ }
+
+ for(i=0; i<nsems; i++) {
+- __put_user((*host_array)[i], &array[i]);
++ array[i] = (*host_array)[i];
+ }
+ free(*host_array);
+ unlock_user(array, target_addr, 1);
+@@ -1779,19 +2063,17 @@ static inline abi_long
+ target_to_host_ipc_perm(struct ipc_perm *host_ip, abi_ulong target_addr)
+ {
+ struct target_ipc_perm *target_ip;
+- struct target_semid_ds *target_sd;
+
+- if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
++ if (!lock_user_struct(VERIFY_READ, target_ip, target_addr, 1))
+ return (-TARGET_EFAULT);
+- target_ip = &(target_sd->sem_perm);
+- host_ip->cuid = tswapal(target_ip->cuid);
+- host_ip->cgid = tswapal(target_ip->cgid);
+- host_ip->uid = tswapal(target_ip->uid);
+- host_ip->gid = tswapal(target_ip->gid);
++ host_ip->cuid = tswap32(target_ip->cuid);
++ host_ip->cgid = tswap32(target_ip->cgid);
++ host_ip->uid = tswap32(target_ip->uid);
++ host_ip->gid = tswap32(target_ip->gid);
+ host_ip->mode = tswap16(target_ip->mode);
+ host_ip->seq = tswap16(target_ip->seq);
+ host_ip->key = tswapal(target_ip->key);
+- unlock_user_struct(target_sd, target_addr, 0);
++ unlock_user_struct(target_ip, target_addr, 0);
+
+ return (0);
+ }
+@@ -1800,18 +2082,17 @@ static inline abi_long
+ host_to_target_ipc_perm(abi_ulong target_addr, struct ipc_perm *host_ip)
+ {
+ struct target_ipc_perm *target_ip;
+- struct target_semid_ds *target_sd;
+- if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
++
++ if (!lock_user_struct(VERIFY_WRITE, target_ip, target_addr, 0))
+ return (-TARGET_EFAULT);
+- target_ip = &(target_sd->sem_perm);
+- target_ip->cuid = tswapal(host_ip->cuid);
+- target_ip->cgid = tswapal(host_ip->cgid);
+- target_ip->uid = tswapal(host_ip->uid);
+- target_ip->gid = tswapal(host_ip->gid);
++ target_ip->cuid = tswap32(host_ip->cuid);
++ target_ip->cgid = tswap32(host_ip->cgid);
++ target_ip->uid = tswap32(host_ip->uid);
++ target_ip->gid = tswap32(host_ip->gid);
+ target_ip->mode = tswap16(host_ip->mode);
+ target_ip->seq = tswap16(host_ip->seq);
+ target_ip->key = tswapal(host_ip->key);
+- unlock_user_struct(target_sd, target_addr, 1);
++ unlock_user_struct(target_ip, target_addr, 1);
+ return (0);
+ }
+
+@@ -1822,11 +2103,12 @@ target_to_host_semid_ds(struct semid_ds *host_sd, abi_ulong target_addr)
+
+ if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
+ return (-TARGET_EFAULT);
+- if (target_to_host_ipc_perm(&(host_sd->sem_perm), target_addr))
++ if (target_to_host_ipc_perm(&(host_sd->sem_perm), (target_addr +
++ offsetof(struct target_semid_ds, sem_perm)) ))
+ return (-TARGET_EFAULT);
+ /* sem_base is not used by kernel for IPC_STAT/IPC_SET */
+- host_sd->sem_base = NULL;
+- host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
++ /* host_sd->sem_base = g2h(target_sd->sem_base); */
++ host_sd->sem_nsems = tswap16(target_sd->sem_nsems);
+ host_sd->sem_otime = tswapal(target_sd->sem_otime);
+ host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
+ unlock_user_struct(target_sd, target_addr, 0);
+@@ -1840,10 +2122,13 @@ host_to_target_semid_ds(abi_ulong target_addr, struct semid_ds *host_sd)
+
+ if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
+ return (-TARGET_EFAULT);
+- if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
++ if (host_to_target_ipc_perm((target_addr +
++ offsetof(struct target_semid_ds, sem_perm)),
++ &(host_sd->sem_perm)))
+ return (-TARGET_EFAULT);
+ /* sem_base is not used by kernel for IPC_STAT/IPC_SET */
+- target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
++ /* target_sd->sem_base = h2g((void *)host_sd->sem_base); */
++ target_sd->sem_nsems = tswap16(host_sd->sem_nsems);
+ target_sd->sem_otime = tswapal(host_sd->sem_otime);
+ target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
+ unlock_user_struct(target_sd, target_addr, 1);
+@@ -1859,6 +2144,7 @@ do_semctl(int semid, int semnum, int cmd, union target_semun target_su)
+ unsigned short *array = NULL;
+ abi_long ret = -TARGET_EINVAL;
+ abi_long err;
++ abi_ulong target_addr;
+
+ cmd &= 0xff;
+
+@@ -1872,24 +2158,28 @@ do_semctl(int semid, int semnum, int cmd, union target_semun target_su)
+
+ case GETALL:
+ case SETALL:
+- err = target_to_host_semarray(semid, &array, target_su.array);
++ if (get_user_ual(target_addr, (abi_ulong)target_su.array))
++ return (-TARGET_EFAULT);
++ err = target_to_host_semarray(semid, &array, target_addr);
+ if (err)
+ return (err);
+ arg.array = array;
+ ret = get_errno(semctl(semid, semnum, cmd, arg));
+- err = host_to_target_semarray(semid, target_su.array, &array);
++ err = host_to_target_semarray(semid, target_addr, &array);
+ if (err)
+ return (err);
+ break;
+
+ case IPC_STAT:
+ case IPC_SET:
+- err = target_to_host_semid_ds(&dsarg, target_su.buf);
++ if (get_user_ual(target_addr, (abi_ulong)target_su.buf))
++ return (-TARGET_EFAULT);
++ err = target_to_host_semid_ds(&dsarg, target_addr);
+ if (err)
+ return (err);
+ arg.buf = &dsarg;
+ ret = get_errno(semctl(semid, semnum, cmd, arg));
+- err = host_to_target_semid_ds(target_su.buf, &dsarg);
++ err = host_to_target_semid_ds(target_addr, &dsarg);
+ if (err)
+ return (err);
+ break;
+@@ -3383,6 +3673,64 @@ host_to_target_sched_param(abi_ulong target_addr, struct sched_param *host_sp)
+ }
+
+ static inline abi_long
++target_to_host_acl(struct acl *host_acl, abi_ulong target_addr)
++{
++ uint32_t i;
++ struct target_acl *target_acl;
++
++ if (!lock_user_struct(VERIFY_READ, target_acl, target_addr, 1))
++ return (-TARGET_EFAULT);
++
++ __get_user(host_acl->acl_maxcnt, &target_acl->acl_maxcnt);
++ __get_user(host_acl->acl_cnt, &target_acl->acl_cnt);
++
++ for(i = 0; i < host_acl->acl_maxcnt; i++) {
++ __get_user(host_acl->acl_entry[i].ae_tag,
++ &target_acl->acl_entry[i].ae_tag);
++ __get_user(host_acl->acl_entry[i].ae_id,
++ &target_acl->acl_entry[i].ae_id);
++ __get_user(host_acl->acl_entry[i].ae_perm,
++ &target_acl->acl_entry[i].ae_perm);
++ __get_user(host_acl->acl_entry[i].ae_entry_type,
++ &target_acl->acl_entry[i].ae_entry_type);
++ __get_user(host_acl->acl_entry[i].ae_flags,
++ &target_acl->acl_entry[i].ae_flags);
++ }
++
++ unlock_user_struct(target_acl, target_addr, 0);
++ return (0);
++}
++
++static inline abi_long
++host_to_target_acl(abi_ulong target_addr, struct acl *host_acl)
++{
++ uint32_t i;
++ struct target_acl *target_acl;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_acl, target_addr, 0))
++ return (-TARGET_EFAULT);
++
++ __put_user(host_acl->acl_maxcnt, &target_acl->acl_maxcnt);
++ __put_user(host_acl->acl_cnt, &target_acl->acl_cnt);
++
++ for(i = 0; i < host_acl->acl_maxcnt; i++) {
++ __put_user(host_acl->acl_entry[i].ae_tag,
++ &target_acl->acl_entry[i].ae_tag);
++ __put_user(host_acl->acl_entry[i].ae_id,
++ &target_acl->acl_entry[i].ae_id);
++ __put_user(host_acl->acl_entry[i].ae_perm,
++ &target_acl->acl_entry[i].ae_perm);
++ __get_user(host_acl->acl_entry[i].ae_entry_type,
++ &target_acl->acl_entry[i].ae_entry_type);
++ __get_user(host_acl->acl_entry[i].ae_flags,
++ &target_acl->acl_entry[i].ae_flags);
++ }
++
++ unlock_user_struct(target_acl, target_addr, 1);
++ return (0);
++}
++
++static inline abi_long
+ do_sched_setparam(pid_t pid, abi_ulong target_sp_addr)
+ {
+ int ret;
+@@ -3993,10 +4341,10 @@ static IOCTLEntry ioctl_entries[] = {
+ { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
+ #define IOCTL_SPECIAL(cmd, access, dofn, ...) \
+ { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
+-#ifdef __FreeBSD__
+-#include "freebsd/ioctl.h"
++#if defined(__FreeBSD__)
++#include "freebsd/ioctls.h"
+ #else
+-#warning No ioctl.h
++#warning No *bsd/ioctls.h
+ #endif
+ { 0, 0 },
+ };
+@@ -4096,6 +4444,158 @@ do_ioctl(int fd, abi_long cmd, abi_long arg)
+ return (ret);
+ }
+
++static inline abi_long
++freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
++ abi_ulong guest_envp, int do_fexec)
++{
++ char **argp, **envp, **qargp, **qarg1;
++ int argc, envc;
++ abi_ulong gp;
++ abi_ulong addr;
++ char **q;
++ int total_size = 0;
++ void *p;
++ abi_long ret;
++
++ argc = 0;
++ for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
++ if (get_user_ual(addr, gp))
++ return (-TARGET_EFAULT);
++ if (!addr)
++ break;
++ argc++;
++ }
++ envc = 0;
++ for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
++ if (get_user_ual(addr, gp))
++ return (-TARGET_EFAULT);
++ if (!addr)
++ break;
++ envc++;
++ }
++
++ qargp = argp = alloca((argc + 3) * sizeof(void *));
++ /* save the first agrument for the emulator */
++ *argp++ = (char *)getprogname();
++ qarg1 = argp;
++ envp = alloca((envc + 1) * sizeof(void *));
++ for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) {
++ if (get_user_ual(addr, gp)) {
++ ret = -TARGET_EFAULT;
++ goto execve_end;
++ }
++ if (!addr)
++ break;
++ if (!(*q = lock_user_string(addr))) {
++ ret = -TARGET_EFAULT;
++ goto execve_end;
++ }
++ total_size += strlen(*q) + 1;
++ }
++ *q = NULL;
++
++ for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) {
++ if (get_user_ual(addr, gp)) {
++ ret = -TARGET_EFAULT;
++ goto execve_end;
++ }
++ if (!addr)
++ break;
++ if (!(*q = lock_user_string(addr))) {
++ ret = -TARGET_EFAULT;
++ goto execve_end;
++ }
++ total_size += strlen(*q) + 1;
++ }
++ *q = NULL;
++
++ /*
++ * This case will not be caught by the host's execve() if its
++ * page size is bigger than the target's.
++ */
++ if (total_size > MAX_ARG_PAGES * TARGET_PAGE_SIZE) {
++ ret = -TARGET_E2BIG;
++ goto execve_end;
++ }
++
++ if (do_fexec) {
++ if (((int)path_or_fd > 0 &&
++ is_target_elf_binary((int)path_or_fd)) == 1) {
++ char execpath[PATH_MAX];
++
++ /*
++ * The executable is an elf binary for the target
++ * arch. execve() it using the emulator if we can
++ * determine the filename path from the fd.
++ */
++ if (get_filename_from_fd(getpid(), (int)path_or_fd,
++ execpath, sizeof(execpath)) != NULL) {
++ *qarg1 = execpath;
++ ret = get_errno(execve(qemu_proc_pathname,
++ qargp, envp));
++ } else {
++ /* Getting the filename path failed. */
++ ret = -TARGET_EBADF;
++ goto execve_end;
++ }
++ } else {
++ ret = get_errno(fexecve((int)path_or_fd, argp, envp));
++ }
++ } else {
++ int fd;
++
++ if (!(p = lock_user_string(path_or_fd))) {
++ ret = -TARGET_EFAULT;
++ goto execve_end;
++ }
++
++ /*
++ * Check the header and see if it a target elf binary. If so
++ * then execute using qemu user mode emulator.
++ */
++ fd = open(p, O_RDONLY | O_CLOEXEC);
++ if (fd > 0 && is_target_elf_binary(fd) == 1) {
++ close(fd);
++ /* Execve() as a target binary using emulator. */
++ *qarg1 = (char *)p;
++ ret = get_errno(execve(qemu_proc_pathname, qargp, envp));
++ } else {
++ close(fd);
++ /* Execve() as a host native binary. */
++ ret = get_errno(execve(p, argp, envp));
++ }
++ unlock_user(p, path_or_fd, 0);
++ }
++
++execve_end:
++ 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;
++ unlock_user(*q, addr, 0);
++ }
++ return (ret);
++}
++
++static inline abi_long
++do_freebsd_execve(abi_ulong path_or_fd, abi_ulong argp, abi_ulong envp)
++{
++
++ return (freebsd_exec_common(path_or_fd, argp, envp, 0));
++}
++
++static inline abi_long
++do_freebsd_fexecve(abi_ulong path_or_fd, abi_ulong argp, abi_ulong envp)
++{
++
++ return (freebsd_exec_common(path_or_fd, argp, envp, 1));
++}
++
+ /* 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>. */
+@@ -4515,96 +5015,14 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ #endif
+
+ case TARGET_FREEBSD_NR_execve:
+- {
+- char **argp, **envp;
+- int argc, envc;
+- abi_ulong gp;
+- abi_ulong guest_argp;
+- abi_ulong guest_envp;
+- abi_ulong addr;
+- char **q;
+- int total_size = 0;
+-
+- argc = 0;
+- guest_argp = arg2;
+- for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
+- if (get_user_ual(addr, gp))
+- goto efault;
+- if (!addr)
+- break;
+- argc++;
+- }
+- envc = 0;
+- guest_envp = arg3;
+- for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
+- if (get_user_ual(addr, gp))
+- goto efault;
+- if (!addr)
+- break;
+- envc++;
+- }
+-
+- argp = alloca((argc + 1) * sizeof(void *));
+- envp = alloca((envc + 1) * sizeof(void *));
+-
+- for (gp = guest_argp, q = argp; gp;
+- gp += sizeof(abi_ulong), q++) {
+- if (get_user_ual(addr, gp))
+- goto execve_efault;
+- if (!addr)
+- break;
+- if (!(*q = lock_user_string(addr)))
+- goto execve_efault;
+- total_size += strlen(*q) + 1;
+- }
+- *q = NULL;
+-
+- for (gp = guest_envp, q = envp; gp;
+- gp += sizeof(abi_ulong), q++) {
+- if (get_user_ual(addr, gp))
+- goto execve_efault;
+- if (!addr)
+- break;
+- if (!(*q = lock_user_string(addr)))
+- goto execve_efault;
+- total_size += strlen(*q) + 1;
+- }
+- *q = NULL;
+-
+- /* This case will not be caught by the host's execve() if its
+- page size is bigger than the target's. */
+- if (total_size > MAX_ARG_PAGES * TARGET_PAGE_SIZE) {
+- ret = -TARGET_E2BIG;
+- goto execve_end;
+- }
+- if (!(p = lock_user_string(arg1)))
+- goto execve_efault;
+- ret = get_errno(execve(p, argp, envp));
+- unlock_user(p, arg1, 0);
+-
+- goto execve_end;
+-
+- execve_efault:
+- ret = -TARGET_EFAULT;
++ ret = do_freebsd_execve(arg1, arg2, arg3);
++ break;
+
+- execve_end:
+- 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;
+- unlock_user(*q, addr, 0);
+- }
+- }
++ case TARGET_FREEBSD_NR_fexecve:
++ ret = do_freebsd_fexecve(arg1, arg2, arg3);
+ break;
+
++
+ case TARGET_FREEBSD_NR_pipe:
+ {
+ int host_pipe[2];
+@@ -5296,11 +5714,11 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ case TARGET_F_SETLKW:
+ if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
+ return (-TARGET_EFAULT);
+- fl.l_type = tswap16(target_fl->l_type);
+- fl.l_whence = tswap16(target_fl->l_whence);
+ fl.l_start = tswapal(target_fl->l_start);
+ fl.l_len = tswapal(target_fl->l_len);
+ fl.l_pid = tswap32(target_fl->l_pid);
++ fl.l_type = tswap16(target_fl->l_type);
++ fl.l_whence = tswap16(target_fl->l_whence);
+ fl.l_sysid = tswap32(target_fl->l_sysid);
+ unlock_user_struct(target_fl, arg3, 0);
+ ret = get_errno(fcntl(arg1, host_cmd, &fl));
+@@ -5370,13 +5788,16 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ if (reclen > len)
+ break;
+ de->d_reclen = tswap16(reclen);
++ de->d_fileno = tswap32(de->d_fileno);
+ len -= reclen;
++ de = (struct dirent *)((void *)de + reclen);
+ }
+ }
+ unlock_user(dirp, arg2, ret);
+- if (arg4)
+- if (put_user(nbytes, arg4, abi_ulong))
++ if (arg4) {
++ if (put_user(basep, arg4, abi_ulong))
+ ret = -TARGET_EFAULT;
++ }
+ }
+ break;
+
+@@ -5431,32 +5852,406 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ break;
+
+
+- case TARGET_FREEBSD_NR___acl_get_file:
+- case TARGET_FREEBSD_NR___acl_set_file:
+- case TARGET_FREEBSD_NR___acl_get_fd:
+- case TARGET_FREEBSD_NR___acl_set_fd:
+- case TARGET_FREEBSD_NR___acl_delete_file:
+- case TARGET_FREEBSD_NR___acl_delete_fd:
+- case TARGET_FREEBSD_NR___acl_aclcheck_file:
+ case TARGET_FREEBSD_NR___acl_aclcheck_fd:
++ {
++ struct acl host_acl;
++
++ ret = target_to_host_acl(&host_acl, arg3);
++ if (!is_error(ret))
++ ret = get_errno(__acl_aclcheck_fd(arg1, arg2,
++ &host_acl));
++ }
++ break;
++
++ case TARGET_FREEBSD_NR___acl_aclcheck_file:
++ {
++ struct acl host_acl;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++
++ ret = target_to_host_acl(&host_acl, arg3);
++ if (!is_error(ret))
++ ret = get_errno(__acl_aclcheck_file(path(p) , arg2,
++ &host_acl));
++
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR___acl_aclcheck_link:
++ {
++ struct acl host_acl;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++
++ ret = target_to_host_acl(&host_acl, arg3);
++ if (!is_error(ret))
++ ret = get_errno(__acl_aclcheck_link(path(p), arg2,
++ &host_acl));
++
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR___acl_delete_fd:
++ ret = get_errno(__acl_delete_fd(arg1, arg2));
++ break;
++
++ case TARGET_FREEBSD_NR___acl_delete_file:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++
++ ret = get_errno(__acl_delete_file(path(p), arg2));
++
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR___acl_delete_link:
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++
++ ret = get_errno(__acl_delete_link(path(p), arg2));
++
++ unlock_user(p, arg1, 0);
++ break;
++
++ case TARGET_FREEBSD_NR___acl_get_fd:
++ {
++ struct acl host_acl;
++
++ ret = get_errno(__acl_get_fd(arg1, arg2, &host_acl));
++
++ if (!is_error(ret))
++ ret = host_to_target_acl(arg3, &host_acl);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR___acl_get_file:
++ {
++ struct acl host_acl;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++
++ ret = get_errno(__acl_get_file(path(p), arg2, &host_acl));
++
++ if (!is_error(ret))
++ ret = host_to_target_acl(arg3, &host_acl);
++
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
+ case TARGET_FREEBSD_NR___acl_get_link:
++ {
++ struct acl host_acl;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++
++ ret = get_errno(__acl_get_link(path(p), arg2, &host_acl));
++
++ if (!is_error(ret))
++ ret = host_to_target_acl(arg3, &host_acl);
++
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR___acl_set_fd:
++ {
++ struct acl host_acl;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++
++ ret = target_to_host_acl(&host_acl, arg3);
++ if (!is_error(ret))
++ ret = get_errno(__acl_set_fd(arg1, arg2, &host_acl));
++
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
++ case TARGET_FREEBSD_NR___acl_set_file:
++ {
++ struct acl host_acl;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++
++ ret = target_to_host_acl(&host_acl, arg3);
++ if (!is_error(ret))
++ ret = get_errno(__acl_set_file(path(p), arg2,
++ &host_acl));
++
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
+ case TARGET_FREEBSD_NR___acl_set_link:
+- case TARGET_FREEBSD_NR___acl_delete_link:
+- case TARGET_FREEBSD_NR___acl_aclcheck_link:
++ {
++ struct acl host_acl;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++
++ ret = target_to_host_acl(&host_acl, arg3);
++ if (!is_error(ret))
++ ret = get_errno(__acl_set_link(path(p), arg2,
++ &host_acl));
++
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
+ case TARGET_FREEBSD_NR_extattrctl:
++ {
++ void *a, *f;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ if (!(f = lock_user_string(arg3)))
++ goto efault;
++ if (!(a = lock_user_string(arg5)))
++ goto efault;
++
++ ret = get_errno(extattrctl(path(p), arg2, f, arg4, a));
++
++ unlock_user(a, arg5, 0);
++ unlock_user(f, arg3, 0);
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
+ case TARGET_FREEBSD_NR_extattr_set_file:
++ {
++ void *a, *d;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ if (!(a = lock_user_string(arg3)))
++ goto efault;
++ if (!(d = lock_user(VERIFY_READ, arg4, arg5, 1)))
++ goto efault;
++
++ ret = get_errno(extattr_set_file(path(p), arg2, a, d, arg5));
++
++ unlock_user(d, arg4, arg5);
++ unlock_user(a, arg3, 0);
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
+ case TARGET_FREEBSD_NR_extattr_get_file:
++ {
++ void *a, *d;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ if (!(a = lock_user_string(arg3)))
++ goto efault;
++
++ if (arg4 && arg5 > 0) {
++ if (!(d = lock_user(VERIFY_WRITE, arg4, arg5, 0)))
++ goto efault;
++ ret = get_errno(extattr_get_file(path(p), arg2, a, d,
++ arg5));
++ unlock_user(d, arg4, arg5);
++ } else {
++ ret = get_errno(extattr_get_file(path(p), arg2, a,
++ NULL, arg5));
++ }
++ unlock_user(a, arg3, 0);
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
+ case TARGET_FREEBSD_NR_extattr_delete_file:
++ {
++ void *a;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ if (!(a = lock_user_string(arg3)))
++ goto efault;
++
++ ret = get_errno(extattr_delete_file(path(p), arg2, a));
++
++ unlock_user(a, arg3, 0);
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
+ case TARGET_FREEBSD_NR_extattr_set_fd:
++ {
++ void *a, *d;
++
++ if (!(a = lock_user_string(arg3)))
++ goto efault;
++ if (!(d = lock_user(VERIFY_READ, arg4, arg5, 1)))
++ goto efault;
++
++ ret = get_errno(extattr_set_fd(arg1, arg2, a, d, arg5));
++
++ unlock_user(d, arg4, arg5);
++ unlock_user(a, arg3, 0);
++ }
++ break;
++
+ case TARGET_FREEBSD_NR_extattr_get_fd:
++ {
++ void *a, *d;
++
++ if (!(a = lock_user_string(arg3)))
++ goto efault;
++
++ if (arg4 && arg5 > 0) {
++ if (!(d = lock_user(VERIFY_WRITE, arg4, arg5, 0)))
++ goto efault;
++ ret = get_errno(extattr_get_fd(arg1, arg2, a, d,
++ arg5));
++ unlock_user(d, arg4, arg5);
++ } else {
++ ret = get_errno(extattr_get_fd(arg1, arg2, a,
++ NULL, arg5));
++ }
++ unlock_user(a, arg3, 0);
++ }
++ break;
++
+ case TARGET_FREEBSD_NR_extattr_delete_fd:
++ {
++ void *a;
++
++ if (!(a = lock_user_string(arg3)))
++ goto efault;
++
++ ret = get_errno(extattr_delete_fd(arg1, arg2, a));
++
++ unlock_user(a, arg3, 0);
++ }
++ break;
++
+ case TARGET_FREEBSD_NR_extattr_get_link:
++ {
++ void *a, *d;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ if (!(a = lock_user_string(arg3)))
++ goto efault;
++
++ if (arg4 && arg5 > 0) {
++ if (!(d = lock_user(VERIFY_WRITE, arg4, arg5, 0)))
++ goto efault;
++ ret = get_errno(extattr_get_link(path(p), arg2, a, d,
++ arg5));
++ unlock_user(d, arg4, arg5);
++ } else {
++ ret = get_errno(extattr_get_link(path(p), arg2, a,
++ NULL, arg5));
++ }
++ unlock_user(a, arg3, 0);
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
+ case TARGET_FREEBSD_NR_extattr_set_link:
++ {
++ void *a, *d;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ if (!(a = lock_user_string(arg3)))
++ goto efault;
++ if (!(d = lock_user(VERIFY_READ, arg4, arg5, 1)))
++ goto efault;
++
++ ret = get_errno(extattr_set_link(path(p), arg2, a, d, arg5));
++
++ unlock_user(d, arg4, arg5);
++ unlock_user(a, arg3, 0);
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
+ case TARGET_FREEBSD_NR_extattr_delete_link:
++ {
++ void *a;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++ if (!(a = lock_user_string(arg3)))
++ goto efault;
++
++ ret = get_errno(extattr_delete_link(path(p), arg2, a));
++
++ unlock_user(a, arg3, 0);
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
+ case TARGET_FREEBSD_NR_extattr_list_fd:
++ {
++ void *d;
++
++ if (arg3 && arg4 > 0) {
++ if (!(d = lock_user(VERIFY_WRITE, arg3, arg4, 0)))
++ goto efault;
++ ret = get_errno(extattr_list_fd(arg1, arg2, d,
++ arg4));
++ unlock_user(d, arg3, arg4);
++ } else {
++ ret = get_errno(extattr_list_fd(arg1, arg2,
++ NULL, arg4));
++ }
++ }
++ break;
++
+ case TARGET_FREEBSD_NR_extattr_list_file:
++ {
++ void *d;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++
++ if (arg3 && arg4 > 0) {
++ if (!(d = lock_user(VERIFY_WRITE, arg3, arg4, 0)))
++ goto efault;
++ ret = get_errno(extattr_list_file(path(p), arg2, d,
++ arg4));
++ unlock_user(d, arg3, arg4);
++ } else {
++ ret = get_errno(extattr_list_file(path(p), arg2,
++ NULL, arg4));
++ }
++ unlock_user(p, arg1, 0);
++ }
++ break;
++
+ case TARGET_FREEBSD_NR_extattr_list_link:
+- ret = unimplemented(num);
++ {
++ void *d;
++
++ if (!(p = lock_user_string(arg1)))
++ goto efault;
++
++ if (arg3 && arg4 > 0) {
++ if (!(d = lock_user(VERIFY_WRITE, arg3, arg4, 0)))
++ goto efault;
++ ret = get_errno(extattr_list_link(path(p), arg2, d,
++ arg4));
++ unlock_user(d, arg3, arg4);
++ } else {
++ ret = get_errno(extattr_list_link(path(p), arg2,
++ NULL, arg4));
++ }
++
++ unlock_user(p, arg1, 0);
++ }
+ break;
+
+ case TARGET_FREEBSD_NR_setlogin:
+@@ -5635,6 +6430,10 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
+ break;
+
++ case TARGET_FREEBSD_NR_freebsd7___semctl:
++ ret = unimplemented(num);
++ break;
++
+ case TARGET_FREEBSD_NR_msgctl:
+ ret = do_msgctl(arg1, arg2, arg3);
+ break;
+@@ -5715,7 +6514,7 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ break;
+
+ case TARGET_FREEBSD_NR_seteuid:
+- ret = get_errno(setegid(arg1));
++ ret = get_errno(seteuid(arg1));
+ break;
+
+ case TARGET_FREEBSD_NR_getpgrp:
+@@ -6953,7 +7752,7 @@ void syscall_init(void)
+
+ #define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
+ #define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__)
+ #include "freebsd/syscall_types.h"
+ #else
+ #warning No syscall_types.h
+diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h
+index 3eb760b..8a92403 100644
+--- a/bsd-user/syscall_defs.h
++++ b/bsd-user/syscall_defs.h
+@@ -203,12 +203,12 @@ struct target_pollfd {
+ #include "openbsd/syscall_nr.h"
+
+ struct target_flock {
+- unsigned long long l_start;
+- unsigned long long l_len;
+- int l_pid;
+- int l_sysid;
+- short l_type;
+- short l_whence;
++ abi_long l_start;
++ abi_long l_len;
++ int32_t l_pid;
++ int16_t l_type;
++ int16_t l_whence;
++ int32_t l_sysid;
+ } QEMU_PACKED;
+
+ struct target_iovec {
+@@ -451,6 +451,7 @@ typedef struct target_siginfo {
+ int32_t si_code; /* signal code */
+ int32_t si_pid; /* sending process */
+ int32_t si_uid; /* sender's ruid */
++ int32_t si_status; /* exit value */
+ abi_ulong si_addr; /* faulting instruction */
+
+ union target_sigval si_value; /* signal value */
+@@ -756,3 +757,41 @@ struct target_timex {
+ struct target_sched_param {
+ int32_t sched_priority;
+ };
++
++
++/*
++ * sys/acl.h
++ */
++
++#define TARGET_ACL_MAX_ENTRIES 254
++
++struct target_acl_entry {
++ int32_t ae_tag;
++ uint32_t ae_id;
++ uint16_t ae_perm;
++ uint16_t ae_entry_type;
++ uint16_t ae_flags;
++};
++
++struct target_acl {
++ uint32_t acl_maxcnt;
++ uint32_t acl_cnt;
++ int32_t acl_space[4];
++ struct target_acl_entry acl_entry[TARGET_ACL_MAX_ENTRIES];
++};
++
++
++/*
++ * netinet/in.h
++ */
++
++struct target_ip_mreq {
++ struct target_in_addr imr_multiaddr;
++ struct target_in_addr imr_interface;
++};
++
++struct target_ip_mreqn {
++ struct target_in_addr imr_multiaddr;
++ struct target_in_addr imr_address;
++ int32_t imr_ifindex;
++};
+diff --git a/configure b/configure
+index d99584d..6d17c97 100755
+--- a/configure
++++ b/configure
+@@ -434,8 +434,9 @@ FreeBSD)
+ make="${MAKE-gmake}"
+ audio_drv_list="oss"
+ audio_possible_drivers="oss sdl esd pa"
+- # needed for kinfo_getvmmap(3) in libutil.h
+- LIBS="-lutil $LIBS"
++ # -lutil needed for kinfo_getvmmap(3) in libutil.h
++ # -lprocstat needed for procstat_*(3) in main.c
++ LIBS="-lprocstat -lutil $LIBS"
+ ;;
+ DragonFly)
+ bsd="yes"
+@@ -1237,6 +1238,11 @@ if test "$static" = "yes" ; then
+ else
+ pie="no"
+ fi
++ if test "$bsd" = "yes" ; then
++ # Missing libs when linking statically
++ LIBS="$LIBS -lintl -lkvm"
++ libs_qga="-lintl $libs_qga"
++ fi
+ fi
+
+ if test "$pie" = ""; then
+diff --git a/util/aes.c b/util/aes.c
+index 1da7bff..30a6608 100644
+--- a/util/aes.c
++++ b/util/aes.c
+@@ -877,6 +877,7 @@ int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+ return 0;
+ }
+
++#if defined(CONFIG_STATIC) && ! defined(__FreeBSD__)
+ #ifndef AES_ASM
+ /*
+ * Encrypt a single block
+@@ -1312,3 +1313,4 @@ void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ }
+ }
+ }
++#endif /* CONFIG_STATIC && ! __FreeBSD__ */
diff --git a/emulators/qemu-devel/files/patch-z9d-bsd-user-sson003d b/emulators/qemu-devel/files/patch-z9d-bsd-user-sson003d
new file mode 100644
index 000000000000..5dfbaa4ea476
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z9d-bsd-user-sson003d
@@ -0,0 +1,92 @@
+diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
+index 8abb1dd..c2c3a65 100644
+--- a/bsd-user/elfload.c
++++ b/bsd-user/elfload.c
+@@ -798,6 +798,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
+ p -= roundup(execpath_len, sizeof(abi_ulong));
+ /* XXX - check return value of memcpy_to_target() */
+ memcpy_to_target(p, execpath, execpath_len);
++ strlcpy(target_proc_pathname, execpath, execpath_len);
+ }
+
+ /* Add canary for SSP. */
+diff --git a/bsd-user/main.c b/bsd-user/main.c
+index bb614de..b6aaa7e 100644
+--- a/bsd-user/main.c
++++ b/bsd-user/main.c
+@@ -62,6 +62,7 @@ unsigned long x86_stack_size = 512 * 1024;
+
+ static void save_proc_pathname(void);
+ char qemu_proc_pathname[PATH_MAX];
++char target_proc_pathname[PATH_MAX];
+
+ #ifdef __FreeBSD__
+ static void
+diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
+index 110b54e..d51f50c 100644
+--- a/bsd-user/qemu.h
++++ b/bsd-user/qemu.h
+@@ -224,6 +224,7 @@ void mmap_fork_end(int child);
+ /* main.c */
+ extern unsigned long x86_stack_size;
+ extern char qemu_proc_pathname[];
++extern char target_proc_pathname[];
+
+ /* user access */
+
+diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
+index 74b5c86..636083a 100644
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -485,8 +485,6 @@ static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong ol
+ abi_ulong oldlen = 0;
+ int32_t *snamep = g_malloc(sizeof(int32_t) * namelen), *p, *q, i;
+ uint32_t kind = 0;
+- abi_ulong argv, argv0;
+- char *fullpath = NULL;
+
+ if (oldlenp)
+ if (get_user_ual(oldlen, oldlenp))
+@@ -533,30 +531,14 @@ static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong ol
+ case KERN_PROC:
+ switch(snamep[2]) {
+ case KERN_PROC_PATHNAME:
+- if (get_user_ual(argv, TARGET_PS_STRINGS)) {
+- ret = -TARGET_EFAULT;
+- goto out;
+- }
+- if (get_user_ual(argv0, argv)) {
+- ret = -TARGET_EFAULT;
+- goto out;
+- }
+-
+- fullpath = realpath(g2h(argv0), NULL);
+- if (NULL == fullpath)
+- fullpath = (char *)g2h(argv0);
+- holdlen = strlen(fullpath) + 1;
++ holdlen = strlen(target_proc_pathname) + 1;
+ if (holdp) {
+ if (oldlen < holdlen) {
+ ret = -TARGET_EINVAL;
+ goto out;
+ }
+- if (!access_ok(VERIFY_WRITE, argv0,
+- holdlen)) {
+- ret = -TARGET_EFAULT;
+- goto out;
+- }
+- strlcpy(holdp, fullpath, oldlen);
++ strlcpy(holdp, target_proc_pathname,
++ oldlen);
+ }
+ ret = 0;
+ goto out;
+@@ -597,8 +579,6 @@ static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong ol
+ #endif
+
+ out:
+- if (fullpath)
+- free(fullpath);
+ if (oldlenp)
+ put_user_ual(holdlen, oldlenp);
+ unlock_user(hnamep, namep, 0);
diff --git a/emulators/qemu-devel/files/patch-z9e-bsd-user-cognet-elfload b/emulators/qemu-devel/files/patch-z9e-bsd-user-cognet-elfload
new file mode 100644
index 000000000000..a47642b24e6e
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z9e-bsd-user-cognet-elfload
@@ -0,0 +1,15 @@
+diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
+index 8abb1dd..eee159b 100644
+--- a/bsd-user/elfload.c
++++ b/bsd-user/elfload.c
+@@ -999,9 +999,9 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
+ NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
+ NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
+ NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
++#ifndef __FreeBSD__
+ NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
+ NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
+-#ifndef __FreeBSD__
+ if (k_platform)
+ NEW_AUX_ENT(AT_PLATFORM, u_platform);
+ #endif
diff --git a/emulators/qemu-devel/files/patch-z9f-bsd-user-sson003f b/emulators/qemu-devel/files/patch-z9f-bsd-user-sson003f
new file mode 100644
index 000000000000..2cf57e8a1429
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-z9f-bsd-user-sson003f
@@ -0,0 +1,321 @@
+diff --git a/bsd-user/arm/target_signal.h b/bsd-user/arm/target_signal.h
+index 6b7bb67..4a9e518 100644
+--- a/bsd-user/arm/target_signal.h
++++ b/bsd-user/arm/target_signal.h
+@@ -3,15 +3,57 @@
+
+ #include "cpu.h"
+
+-static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
+-{
+- return state->regs[13];
+-}
++#define TARGET_REG_R0 0
++#define TARGET_REG_R1 1
++#define TARGET_REG_R2 2
++#define TARGET_REG_R3 3
++#define TARGET_REG_R4 4
++#define TARGET_REG_R5 5
++#define TARGET_REG_R6 6
++#define TARGET_REG_R7 7
++#define TARGET_REG_R8 8
++#define TARGET_REG_R9 9
++#define TARGET_REG_R10 10
++#define TARGET_REG_R11 11
++#define TARGET_REG_R12 12
++#define TARGET_REG_R13 13
++#define TARGET_REG_R14 14
++#define TARGET_REG_R15 15
++#define TARGET_REG_CPSR 16
++/* Convenience synonyms */
++#define TARGET_REG_FP TARGET_REG_R11
++#define TARGET_REG_SP TARGET_REG_R13
++#define TARGET_REG_LR TARGET_REG_R14
++#define TARGET_REG_PC TARGET_REG_R15
++
++#define TARGET_GET_MC_CLEAR_RET 1
+
+ #define TARGET_MINSIGSTKSZ (1024 * 4)
+ #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
++#define TARGET__NGREG 17
++
++typedef struct {
++ uint32_t __fp_fpsr;
++ struct {
++ uint32_t __fp_exponent;
++ uint32_t __fp_mantissa_hi;
++ uint32_t __fp_mantissa_lo;
++ } __fp_fr[8];
++} target__fpregset_t;
+
+-typedef target_ulong target_mcontext_t; /* dummy */
++typedef struct {
++ uint32_t __vfp_fpscr;
++ uint32_t __vfp_fstmx[33];
++ uint32_t __vfp_fpsid;
++} target__vfpregset_t;
++
++typedef struct {
++ uint32_t __gregs[TARGET__NGREG];
++ union {
++ target__fpregset_t __fpregs;
++ target__vfpregset_t __vfpregs;
++ } __fpu;
++} target_mcontext_t;
+
+ typedef struct target_ucontext {
+ target_sigset_t uc_sigmask;
+@@ -22,18 +64,119 @@ typedef struct target_ucontext {
+ int32_t __spare__[4];
+ } target_ucontext_t;
+
++struct target_sigframe {
++ target_siginfo_t sf_si; /* saved siginfo */
++ target_ucontext_t sf_uc; /* saved ucontext */
++};
++
++#define TARGET_SZSIGCODE (8 * 4)
++
++/* Compare to arm/arm/locore.S ENTRY_NP(sigcode) */
++static inline int
++install_sigtramp(abi_ulong offset, unsigned sigf_us, uint32_t sys_sigreturn)
++{
++ int i;
++ uint32_t sys_exit = TARGET_FREEBSD_NR_exit;
++ /*
++ * The code has to load r7 manually rather than using
++ * "ldr r7, =SYS_return to make sure the size of the
++ * code is correct.
++ */
++ uint32_t sigtramp_code[] = {
++ /* 1 */ 0xE1A0000D, /* mov r0, sp */
++ /* 2 */ 0xE59F700C, /* ldr r7, [pc, #12] */
++ /* 3 */ 0xEF000000 + sys_sigreturn, /* swi (SYS_sigreturn) */
++ /* 4 */ 0xE59F7008, /* ldr r7, [pc, #8] */
++ /* 5 */ 0xEF000000 + sys_exit, /* swi (SYS_exit)*/
++ /* 6 */ 0xEAFFFFFA, /* b . -16 */
++ /* 7 */ sys_sigreturn,
++ /* 8 */ sys_exit
++ };
++
++ for(i = 0; i < 8; i++)
++ tswap32s(&sigtramp_code[i]);
++
++ return(memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE));
++}
++
++static inline abi_ulong
++get_sp_from_cpustate(CPUARMState *state)
++{
++ return state->regs[13]; /* sp */
++}
++
++/*
++ * Compare to arm/arm/machdep.c sendsig()
++ * Assumes that the target stack frame memory is locked.
++ */
++static inline int
++set_sigtramp_args(CPUARMState *regs, int sig, struct target_sigframe *frame,
++ abi_ulong frame_addr, struct target_sigaction *ka)
++{
++ /*
++ * Arguments to signal handler:
++ * r0 = signal number
++ * r1 = siginfo pointer
++ * r2 = ucontext pointer
++ * r5 = ucontext pointer
++ * pc = signal handler pointer
++ * sp = sigframe struct pointer
++ * lr = sigtramp at base of user stack
++ */
++
++ regs->regs[0] = sig;
++ regs->regs[1] = frame_addr +
++ offsetof(struct target_sigframe, sf_si);
++ regs->regs[2] = frame_addr +
++ offsetof(struct target_sigframe, sf_uc);
++
++ /* the trampoline uses r5 as the uc address */
++ regs->regs[5] = frame_addr +
++ offsetof(struct target_sigframe, sf_uc);
++ regs->regs[TARGET_REG_PC] = ka->_sa_handler;
++ regs->regs[TARGET_REG_SP] = frame_addr;
++ regs->regs[TARGET_REG_LR] = TARGET_PS_STRINGS - TARGET_SZSIGCODE;
++
++ return (0);
++}
++
++/* Compare to arm/arm/machdep.c get_mcontext() */
+ static inline int
+-get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
++get_mcontext(CPUARMState *regs, target_mcontext_t *mcp, int clear_ret)
+ {
+- fprintf(stderr, "ARM doesn't have support for get_mcontext()\n");
+- return (-TARGET_ENOSYS);
++ int i, err = 0;
++ uint32_t *gr = mcp->__gregs;
++
++
++ if (clear_ret & TARGET_GET_MC_CLEAR_RET)
++ gr[TARGET_REG_R0] = 0;
++ else
++ gr[TARGET_REG_R0] = tswap32(regs->regs[0]);
++ for(i = 1; i < 12; i++)
++ gr[i] = tswap32(regs->regs[i]);
++ gr[TARGET_REG_SP] = tswap32(regs->regs[13]);
++ gr[TARGET_REG_LR] = tswap32(regs->regs[14]);
++ gr[TARGET_REG_PC] = tswap32(regs->regs[15]);
++ gr[TARGET_REG_CPSR] = tswap32(regs->spsr);
++
++ return (err);
+ }
+
++/* Compare to arm/arm/machdep.c set_mcontext() */
+ static inline int
+-set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
++set_mcontext(CPUARMState *regs, target_mcontext_t *mcp, int flags)
+ {
+- fprintf(stderr, "ARM doesn't have support for set_mcontext()\n");
+- return (-TARGET_ENOSYS);
++ int i, err = 0;
++ const uint32_t *gr = mcp->__gregs;
++
++ for(i = 0; i < 12; i++)
++ regs->regs[i] = tswap32(gr[i]);
++ regs->regs[13] = tswap32(gr[TARGET_REG_SP]);
++ regs->regs[14] = tswap32(gr[TARGET_REG_LR]);
++ regs->regs[15] = tswap32(gr[TARGET_REG_PC]);
++ regs->spsr = tswap32(gr[TARGET_REG_CPSR]);
++
++ return (err);
+ }
+
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/arm/target_vmparam.h b/bsd-user/arm/target_vmparam.h
+index 24dca00..bc50fbb 100644
+--- a/bsd-user/arm/target_vmparam.h
++++ b/bsd-user/arm/target_vmparam.h
+@@ -18,8 +18,6 @@ struct target_ps_strings {
+
+ #define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
+
+-#define TARGET_SZSIGCODE 0
+-
+ /* Make stack size large enough to hold everything. */
+ #define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \
+ MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size)
+diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
+index c2c3a65..76681e1 100644
+--- a/bsd-user/elfload.c
++++ b/bsd-user/elfload.c
+@@ -690,24 +690,6 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
+ return p;
+ }
+
+-#if defined(TARGET_MIPS64)
+-static inline int
+-install_sigtramp(abi_ulong offset, unsigned sigf_uc, unsigned syscall)
+-{
+- int i;
+- uint32_t sigtramp_code[] = {
+- 0x67A40000 + sigf_uc, /* daddu $a0, $sp, (sigf_uc) */
+- 0x24020000 + syscall, /* li $v0, (syscall) */
+- 0x0000000C, /* syscall */
+- 0x0000000D /* break */
+- };
+-
+- for(i = 0; i < 4; i++)
+- tswap32s(&sigtramp_code[i]);
+-
+- return (memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE));
+-}
+-#endif
+
+ static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
+ struct image_info *info)
+diff --git a/bsd-user/mips64/target_signal.h b/bsd-user/mips64/target_signal.h
+index c592136..f657909 100644
+--- a/bsd-user/mips64/target_signal.h
++++ b/bsd-user/mips64/target_signal.h
+@@ -5,7 +5,6 @@
+
+ #define TARGET_MINSIGSTKSZ (512 * 4)
+ #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
+-#define TARGET_SZSIGCODE 16
+
+ struct target_sigcontext {
+ target_sigset_t sc_mask; /* signal mask to retstore */
+@@ -56,9 +55,29 @@ get_sp_from_cpustate(CPUMIPSState *state)
+ return state->active_tc.gpr[29];
+ }
+
++#define TARGET_SZSIGCODE (4 * 4)
++
++/* Compare to mips/mips/locore.S sigcode() */
++static inline int
++install_sigtramp(abi_ulong offset, unsigned sigf_uc, unsigned sys_sigreturn)
++{
++ int i;
++ uint32_t sigtramp_code[] = {
++ /* 1 */ 0x67A40000 + sigf_uc, /* daddu $a0, $sp, (sigf_uc) */
++ /* 2 */ 0x24020000 + sys_sigreturn, /* li $v0, (sys_sigreturn) */
++ /* 3 */ 0x0000000C, /* syscall */
++ /* 4 */ 0x0000000D /* break */
++ };
++
++ for(i = 0; i < 4; i++)
++ tswap32s(&sigtramp_code[i]);
++
++ return (memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE));
++}
++
+ /*
+ * Compare to mips/mips/pm_machdep.c sendsig()
+- * Assumes that "frame" memory is locked.
++ * Assumes that target stack frame memory is locked.
+ */
+ static inline int
+ set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
+@@ -67,6 +86,11 @@ set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
+
+ /* frame->sf_si.si_addr = regs->CP0_BadVAddr; */
+
++ /* MIPS only struct target_sigframe members: */
++ frame->sf_signum = sig;
++ frame->sf_siginfo = (abi_ulong)&frame->sf_si;
++ frame->sf_ucontext = (abi_ulong)&frame->sf_uc;
++
+ /*
+ * Arguments to signal handler:
+ * a0 ($4) = signal number
+diff --git a/bsd-user/signal.c b/bsd-user/signal.c
+index 29e8e12..b04e874 100644
+--- a/bsd-user/signal.c
++++ b/bsd-user/signal.c
+@@ -613,7 +613,7 @@ do_sigaction(int sig, const struct target_sigaction *act,
+ return (ret);
+ }
+
+-#if defined(TARGET_MIPS64) /* || defined(TARGET_SPARC64) */
++#if defined(TARGET_MIPS64) || defined(TARGET_ARM)
+
+ static inline abi_ulong
+ get_sigframe(struct target_sigaction *ka, CPUArchState *regs, size_t frame_size)
+@@ -715,17 +715,8 @@ static void setup_frame(int sig, int code, struct target_sigaction *ka,
+ }
+ #endif
+
+- frame->sf_signum = sig;
+- frame->sf_siginfo = (abi_ulong)&frame->sf_si;
+- frame->sf_ucontext = (abi_ulong)&frame->sf_uc;
+-
+- } else {
+- frame->sf_signum = sig;
+- frame->sf_siginfo = 0;
+- frame->sf_ucontext = 0;
+ }
+
+-
+ if (set_sigtramp_args(regs, sig, frame, frame_addr, ka))
+ goto give_sigsegv;
+
diff --git a/emulators/qemu-devel/files/patch-za-bsd-user-8fix b/emulators/qemu-devel/files/patch-za-bsd-user-8fix
new file mode 100644
index 000000000000..ef409469c549
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-za-bsd-user-8fix
@@ -0,0 +1,28 @@
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -123,6 +123,7 @@ get_filename_from_fd(pid_t pid, int fd,
+ struct filestat *fst;
+ char *ret = NULL;
+
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+ procstat = procstat_open_sysctl();
+ if (NULL == procstat)
+ goto out;
+@@ -152,6 +153,7 @@ out:
+ procstat_freeprocs(procstat, kipp);
+ if (procstat != NULL)
+ procstat_close(procstat);
++#endif
+ return (ret);
+ }
+
+@@ -1739,7 +1741,9 @@ int_case:
+ case IP_RECVDSTADDR:
+
+ case IP_RETOPTS:
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+ case IP_RECVTOS:
++#endif
+ case IP_MULTICAST_TTL:
+ case IP_MULTICAST_LOOP:
+ case IP_PORTRANGE:
diff --git a/emulators/qemu-devel/files/patch-zb-bsd-user-sson004a b/emulators/qemu-devel/files/patch-zb-bsd-user-sson004a
new file mode 100644
index 000000000000..c25c52b6d5c6
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-zb-bsd-user-sson004a
@@ -0,0 +1,1151 @@
+diff --git a/bsd-user/arm/syscall.h b/bsd-user/arm/syscall.h
+index bd54b37..4d98841 100644
+--- a/bsd-user/arm/syscall.h
++++ b/bsd-user/arm/syscall.h
+@@ -22,4 +22,7 @@ struct target_pt_regs {
+
+ #define ARM_SYSCALL_BASE 0 /* XXX: FreeBSD only */
+
+-#define TARGET_FREEBSD_ARM_SET_TP 2
++#define TARGET_FREEBSD_ARM_SYNC_ICACHE 0
++#define TARGET_FREEBSD_ARM_DRAIN_WRITEBUF 1
++#define TARGET_FREEBSD_ARM_SET_TP 2
++#define TARGET_FREEBSD_ARM_GET_TP 3
+diff --git a/bsd-user/arm/target_signal.h b/bsd-user/arm/target_signal.h
+index 4a9e518..05c9d1c 100644
+--- a/bsd-user/arm/target_signal.h
++++ b/bsd-user/arm/target_signal.h
+@@ -26,8 +26,6 @@
+ #define TARGET_REG_LR TARGET_REG_R14
+ #define TARGET_REG_PC TARGET_REG_R15
+
+-#define TARGET_GET_MC_CLEAR_RET 1
+-
+ #define TARGET_MINSIGSTKSZ (1024 * 4)
+ #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
+ #define TARGET__NGREG 17
+@@ -109,7 +107,7 @@ get_sp_from_cpustate(CPUARMState *state)
+ * Compare to arm/arm/machdep.c sendsig()
+ * Assumes that the target stack frame memory is locked.
+ */
+-static inline int
++static inline abi_ulong
+ set_sigtramp_args(CPUARMState *regs, int sig, struct target_sigframe *frame,
+ abi_ulong frame_addr, struct target_sigaction *ka)
+ {
+@@ -141,42 +139,89 @@ set_sigtramp_args(CPUARMState *regs, int sig, struct target_sigframe *frame,
+ }
+
+ /* Compare to arm/arm/machdep.c get_mcontext() */
+-static inline int
++static inline abi_long
+ get_mcontext(CPUARMState *regs, target_mcontext_t *mcp, int clear_ret)
+ {
+- int i, err = 0;
++ int err = 0;
+ uint32_t *gr = mcp->__gregs;
+
+
+- if (clear_ret & TARGET_GET_MC_CLEAR_RET)
++ if (clear_ret & TARGET_MC_GET_CLEAR_RET)
+ gr[TARGET_REG_R0] = 0;
+ else
+ gr[TARGET_REG_R0] = tswap32(regs->regs[0]);
+- for(i = 1; i < 12; i++)
+- gr[i] = tswap32(regs->regs[i]);
++
++ gr[TARGET_REG_R1 ] = tswap32(regs->regs[ 1]);
++ gr[TARGET_REG_R2 ] = tswap32(regs->regs[ 2]);
++ gr[TARGET_REG_R3 ] = tswap32(regs->regs[ 3]);
++ gr[TARGET_REG_R4 ] = tswap32(regs->regs[ 4]);
++ gr[TARGET_REG_R5 ] = tswap32(regs->regs[ 5]);
++ gr[TARGET_REG_R6 ] = tswap32(regs->regs[ 6]);
++ gr[TARGET_REG_R7 ] = tswap32(regs->regs[ 7]);
++ gr[TARGET_REG_R8 ] = tswap32(regs->regs[ 8]);
++ gr[TARGET_REG_R9 ] = tswap32(regs->regs[ 9]);
++ gr[TARGET_REG_R10] = tswap32(regs->regs[10]);
++ gr[TARGET_REG_R11] = tswap32(regs->regs[11]);
++ gr[TARGET_REG_R12] = tswap32(regs->regs[12]);
++
+ gr[TARGET_REG_SP] = tswap32(regs->regs[13]);
+ gr[TARGET_REG_LR] = tswap32(regs->regs[14]);
+ gr[TARGET_REG_PC] = tswap32(regs->regs[15]);
+- gr[TARGET_REG_CPSR] = tswap32(regs->spsr);
++ gr[TARGET_REG_CPSR] = tswap32(cpsr_read(regs));
+
+ return (err);
+ }
+
+ /* Compare to arm/arm/machdep.c set_mcontext() */
+-static inline int
+-set_mcontext(CPUARMState *regs, target_mcontext_t *mcp, int flags)
++static inline abi_long
++set_mcontext(CPUARMState *regs, target_mcontext_t *mcp, int srflag)
+ {
+- int i, err = 0;
++ int err = 0;
+ const uint32_t *gr = mcp->__gregs;
++ uint32_t cpsr;
++
++ regs->regs[ 0] = tswap32(gr[TARGET_REG_R0 ]);
++ regs->regs[ 1] = tswap32(gr[TARGET_REG_R1 ]);
++ regs->regs[ 2] = tswap32(gr[TARGET_REG_R2 ]);
++ regs->regs[ 3] = tswap32(gr[TARGET_REG_R3 ]);
++ regs->regs[ 4] = tswap32(gr[TARGET_REG_R4 ]);
++ regs->regs[ 5] = tswap32(gr[TARGET_REG_R5 ]);
++ regs->regs[ 6] = tswap32(gr[TARGET_REG_R6 ]);
++ regs->regs[ 7] = tswap32(gr[TARGET_REG_R7 ]);
++ regs->regs[ 8] = tswap32(gr[TARGET_REG_R8 ]);
++ regs->regs[ 9] = tswap32(gr[TARGET_REG_R9 ]);
++ regs->regs[10] = tswap32(gr[TARGET_REG_R10]);
++ regs->regs[11] = tswap32(gr[TARGET_REG_R11]);
++ regs->regs[12] = tswap32(gr[TARGET_REG_R12]);
+
+- for(i = 0; i < 12; i++)
+- regs->regs[i] = tswap32(gr[i]);
+ regs->regs[13] = tswap32(gr[TARGET_REG_SP]);
+ regs->regs[14] = tswap32(gr[TARGET_REG_LR]);
+ regs->regs[15] = tswap32(gr[TARGET_REG_PC]);
+- regs->spsr = tswap32(gr[TARGET_REG_CPSR]);
++ cpsr = tswap32(gr[TARGET_REG_CPSR]);
++ cpsr_write(regs, cpsr, CPSR_USER | CPSR_EXEC);
+
+ return (err);
+ }
+
++/* Compare to arm/arm/machdep.c sys_sigreturn() */
++static inline abi_long
++get_ucontext_sigreturn(CPUARMState *regs, abi_ulong sf_addr,
++ target_ucontext_t **ucontext, void **locked_addr)
++{
++ struct target_sigframe *sf;
++ uint32_t cpsr = cpsr_read(regs);
++
++ if ((cpsr & CPSR_M) != ARM_CPU_MODE_USR ||
++ (cpsr & (CPSR_I | CPSR_F)) != 0)
++ return (-TARGET_EINVAL);
++
++ if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 0))
++ return (-TARGET_EFAULT);
++
++ *locked_addr = sf;
++ *ucontext = (target_ucontext_t *)g2h(tswapal(sf_addr +
++ offsetof(struct target_sigframe, sf_uc)));
++ return (0);
++}
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
+index 76681e1..7a7c3eb 100644
+--- a/bsd-user/elfload.c
++++ b/bsd-user/elfload.c
+@@ -13,6 +13,7 @@
+
+ #include "qemu.h"
+ #include "disas/disas.h"
++#include "target_signal.h"
+
+ #ifdef _ARCH_PPC64
+ #undef ARCH_DLINFO
+diff --git a/bsd-user/errno_defs.h b/bsd-user/errno_defs.h
+index 1efa502..7f2e0ca 100644
+--- a/bsd-user/errno_defs.h
++++ b/bsd-user/errno_defs.h
+@@ -147,3 +147,7 @@
+ #define TARGET_EIDRM 89 /* Identifier removed */
+ #define TARGET_ENOMSG 90 /* No message of desired type */
+ #define TARGET_ELAST 90 /* Must be equal largest errno */
++
++/* pseudo-errors just used in the kernel/emulator: */
++#define TARGET_ERESTART 255 /* restart syscall */
++#define TARGET_EJUSTRETURN 254 /* Don't modify regs, just ret */
+diff --git a/bsd-user/freebsd/strace.list b/bsd-user/freebsd/strace.list
+index 8270c37..1f8ee10 100644
+--- a/bsd-user/freebsd/strace.list
++++ b/bsd-user/freebsd/strace.list
+@@ -33,6 +33,7 @@
+ { TARGET_FREEBSD_NR_connect, "connect", "%s(%d,%#x,%d)", NULL, NULL },
+ { TARGET_FREEBSD_NR_dup, "dup", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_dup2, "dup2", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_eaccess, "eaccess", "%s(%s,%#x)", NULL, NULL },
+ { TARGET_FREEBSD_NR_execve, "execve", NULL, print_execve, NULL },
+ { TARGET_FREEBSD_NR_exit, "exit", "%s(%d)\n", NULL, NULL },
+ { TARGET_FREEBSD_NR_extattrctl, "extattrctl", "%s(\"%s\", %d, \"%s\", %d, \"%s\"", NULL, NULL },
+@@ -51,7 +52,7 @@
+ { TARGET_FREEBSD_NR_fchdir, "fchdir", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_fchflags, "fchflags", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_fchmod, "fchmod", "%s(%d,%#o)", NULL, NULL },
+-{ TARGET_FREEBSD_NR_fchown, "fchown", "%s(\"%s\",%d,%d)", NULL, NULL },
++{ TARGET_FREEBSD_NR_fchown, "fchown", "%s(%d,%d,%d)", NULL, NULL },
+ { TARGET_FREEBSD_NR_fcntl, "fcntl", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_fexecve, "fexecve", NULL, print_execve, NULL },
+ { TARGET_FREEBSD_NR_fhopen, "fhopen", NULL, NULL, NULL },
+@@ -185,7 +186,7 @@
+ { TARGET_FREEBSD_NR_sigprocmask, "sigprocmask", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_sigreturn, "sigreturn", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_sigsuspend, "sigsuspend", NULL, NULL, NULL },
+-{ TARGET_FREEBSD_NR_socket, "socket", NULL, NULL, NULL },
++{ TARGET_FREEBSD_NR_socket, "socket", "%s(%d,%d,%d)", NULL, NULL },
+ { TARGET_FREEBSD_NR_socketpair, "socketpair", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_sstk, "sstk", NULL, NULL, NULL },
+ { TARGET_FREEBSD_NR_stat, "stat", "%s(\"%s\",%p)", NULL, NULL },
+diff --git a/bsd-user/i386/target_signal.h b/bsd-user/i386/target_signal.h
+index 28481ce..51a2a7b 100644
+--- a/bsd-user/i386/target_signal.h
++++ b/bsd-user/i386/target_signal.h
+@@ -3,11 +3,6 @@
+
+ #include "cpu.h"
+
+-static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
+-{
+- return state->regs[R_ESP];
+-}
+-
+ #define TARGET_MINSIGSTKSZ (512 * 4)
+ #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
+
+@@ -22,18 +17,32 @@ typedef struct target_ucontext {
+ int32_t __spare__[4];
+ } target_ucontext_t;
+
+-static inline int
++static inline abi_ulong
++get_sp_from_cpustate(CPUX86State *state)
++{
++ return state->regs[R_ESP];
++}
++
++static inline abi_long
+ get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
+ {
+ fprintf(stderr, "i386 doesn't have support for get_mcontext()\n");
+ return (-TARGET_ENOSYS);
+ }
+
+-static inline int
++static inline abi_long
+ set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
+ {
+ fprintf(stderr, "i386 doesn't have support for set_mcontext()\n");
+ return (-TARGET_ENOSYS);
+ }
+
++static inline abi_long
++get_ucontext_sigreturn(CPUArchState *regs, abi_ulong sf_addr,
++ target_ucontext_t **ucontext, void **locked_addr)
++{
++ fprintf(stderr, "i386 doesn't have support for do_sigreturn()\n");
++ return (-TARGET_ENOSYS);
++}
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/main.c b/bsd-user/main.c
+index b6aaa7e..b248a91 100644
+--- a/bsd-user/main.c
++++ b/bsd-user/main.c
+@@ -35,6 +35,7 @@
+ #include "tcg.h"
+ #include "qemu/timer.h"
+ #include "qemu/envlist.h"
++#include "target_signal.h"
+
+ #if defined(CONFIG_USE_NPTL) && defined(__FreeBSD__)
+ #include <sys/thr.h>
+@@ -813,15 +814,25 @@ void cpu_loop(CPUARMState *env)
+ arg6,
+ arg7,
+ arg8);
+- if ((unsigned int)ret >= (unsigned int)(-515)) {
+- ret = -ret;
+- cpsr_write(env, CPSR_C, CPSR_C);
+- env->regs[0] = ret;
+- } else {
+- cpsr_write(env, 0, CPSR_C);
+- env->regs[0] = ret; // XXX need to handle lseek()?
+- // env->regs[1] = 0;
+- }
++ /* Compare to arm/arm/vm_machdep.c cpu_set_syscall_retval() */
++ /* XXX armeb may need some extra magic here */
++ if (-TARGET_EJUSTRETURN == ret) {
++ /*
++ * Returning from a successful sigreturn syscall.
++ * Avoid clobbering register state.
++ */
++ break;
++ }
++ /* XXX Need to handle ERESTART. Backup the PC by 1 instruction*/
++ if ((unsigned int)ret >= (unsigned int)(-515)) {
++ ret = -ret;
++ cpsr_write(env, CPSR_C, CPSR_C);
++ env->regs[0] = ret;
++ } else {
++ cpsr_write(env, 0, CPSR_C);
++ env->regs[0] = ret; // XXX need to handle lseek()?
++ // env->regs[1] = 0;
++ }
+ } else {
+ // XXX is this correct?
+ env->regs[0] = do_openbsd_syscall(env,
+@@ -1068,13 +1079,20 @@ void cpu_loop(CPUMIPSState *env)
+ }
+ }
+ /* done_syscall: */
+- if (-TARGET_QEMU_ESIGRETURN == ret) {
++ /*
++ * Compare to mips/mips/vm_machdep.c
++ * cpu_set_syscall_retval()
++ *
++ * XXX need to handle lseek here.
++ */
++ if (-TARGET_EJUSTRETURN == ret) {
+ /*
+ * Returning from a successful sigreturn
+ * syscall. Avoid clobbering register state.
+ */
+ break;
+ }
++ /* XXX need to handle ERESTART */
+ if ((unsigned int)ret >= (unsigned int)(-1133)) {
+ env->active_tc.gpr[7] = 1;
+ ret = -ret;
+diff --git a/bsd-user/mips/target_signal.h b/bsd-user/mips/target_signal.h
+index 484cfd8..0f57f0f 100644
+--- a/bsd-user/mips/target_signal.h
++++ b/bsd-user/mips/target_signal.h
+@@ -61,7 +61,7 @@ get_sp_from_cpustate(CPUMIPSState *state)
+ * Compare to mips/mips/pm_machdep.c sendsig()
+ * Assumes that "frame" memory is locked.
+ */
+-static inline int
++static inline abi_long
+ set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
+ abi_ulong frame_addr, struct target_sigaction *ka)
+ {
+@@ -98,7 +98,7 @@ set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
+ * Compare to mips/mips/pm_machdep.c get_mcontext()
+ * Assumes that the memory is locked if mcp points to user memory.
+ */
+-static inline int
++static inline abi_long
+ get_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
+ {
+ int i, err = 0;
+@@ -152,8 +152,8 @@ get_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
+ }
+
+ /* Compare to mips/mips/pm_machdep.c set_mcontext() */
+-static inline int
+-set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
++static inline abi_long
++set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int srflag)
+ {
+ int i, err = 0;
+
+@@ -184,9 +184,27 @@ set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
+ regs->active_tc.HI[0] = tswapal(mcp->mulhi);
+ regs->tls_value = tswapal(mcp->mc_tls);
+
++ if (srflag) {
++ /* doing sigreturn() */
++ regs->active_tc.PC = regs->CP0_EPC;
++ regs->CP0_EPC = 0; /* XXX for nested signals ? */
++ }
++
+ /* Don't do any of the status and cause registers. */
+
+ return (err);
+ }
+
++/* mips/mips/pm_machdep.c sys_sigreturn() */
++static inline abi_long
++get_ucontext_sigreturn(CPUMIPSState *regs, abi_ulong uc_addr,
++ target_ucontext_t **ucontext, void **locked_addr)
++{
++ if (!lock_user_struct(VERIFY_READ, *ucontext, uc_addr, 0))
++ return (-TARGET_EFAULT);
++
++ *locked_addr = *ucontext;
++ return (0);
++}
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/mips64/target_signal.h b/bsd-user/mips64/target_signal.h
+index f657909..3fee772 100644
+--- a/bsd-user/mips64/target_signal.h
++++ b/bsd-user/mips64/target_signal.h
+@@ -58,7 +58,7 @@ get_sp_from_cpustate(CPUMIPSState *state)
+ #define TARGET_SZSIGCODE (4 * 4)
+
+ /* Compare to mips/mips/locore.S sigcode() */
+-static inline int
++static inline abi_long
+ install_sigtramp(abi_ulong offset, unsigned sigf_uc, unsigned sys_sigreturn)
+ {
+ int i;
+@@ -79,7 +79,7 @@ install_sigtramp(abi_ulong offset, unsigned sigf_uc, unsigned sys_sigreturn)
+ * Compare to mips/mips/pm_machdep.c sendsig()
+ * Assumes that target stack frame memory is locked.
+ */
+-static inline int
++static inline abi_long
+ set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
+ abi_ulong frame_addr, struct target_sigaction *ka)
+ {
+@@ -117,7 +117,7 @@ set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
+ * Compare to mips/mips/pm_machdep.c get_mcontext()
+ * Assumes that the memory is locked if mcp points to user memory.
+ */
+-static inline int
++static inline abi_long
+ get_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
+ {
+ int i, err = 0;
+@@ -171,8 +171,8 @@ get_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
+ }
+
+ /* Compare to mips/mips/pm_machdep.c set_mcontext() */
+-static inline int
+-set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
++static inline abi_long
++set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int srflag)
+ {
+ int i, err = 0;
+
+@@ -203,10 +203,28 @@ set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
+ regs->active_tc.HI[0] = tswapal(mcp->mulhi);
+ regs->tls_value = tswapal(mcp->mc_tls);
+
++ if (srflag) {
++ /* doing sigreturn() */
++ regs->active_tc.PC = regs->CP0_EPC;
++ regs->CP0_EPC = 0; /* XXX for nested signals ? */
++ }
++
+ /* Don't do any of the status and cause registers. */
+
+ return (err);
+ }
+
++/* mips/mips/pm_machdep.c sys_sigreturn() */
++static inline abi_long
++get_ucontext_sigreturn(CPUMIPSState *regs, abi_ulong uc_addr,
++ target_ucontext_t **ucontext, void **locked_addr)
++{
++ if (!lock_user_struct(VERIFY_READ, *ucontext, uc_addr, 0))
++ return (-TARGET_EFAULT);
++
++ *locked_addr = *ucontext;
++ return (0);
++}
++
+ #endif /* TARGET_SIGNAL_H */
+
+diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
+index d51f50c..fbcdd6c 100644
+--- a/bsd-user/qemu.h
++++ b/bsd-user/qemu.h
+@@ -27,7 +27,6 @@ abi_long memcpy_to_target(abi_ulong dest, const void *src,
+ #include "syscall_defs.h"
+ #include "syscall.h"
+ #include "target_vmparam.h"
+-#include "target_signal.h"
+ #include "exec/gdbstub.h"
+
+ #if defined(CONFIG_USE_NPTL)
+diff --git a/bsd-user/signal.c b/bsd-user/signal.c
+index b04e874..e7e9e41 100644
+--- a/bsd-user/signal.c
++++ b/bsd-user/signal.c
+@@ -101,6 +101,9 @@ static struct target_sigaction sigact_table[TARGET_NSIG];
+
+ static void host_signal_handler(int host_signum, siginfo_t *info, void *puc);
+
++static void target_to_host_sigset_internal(sigset_t *d, const target_sigset_t *s);
++void QEMU_NORETURN force_sig(int target_sig);
++
+ static inline int
+ on_sig_stack(unsigned long sp)
+ {
+@@ -315,7 +318,7 @@ free_sigqueue(CPUArchState *env, struct qemu_sigqueue *q)
+ }
+
+ /* Abort execution with signal. */
+-static void QEMU_NORETURN
++void QEMU_NORETURN
+ force_sig(int target_sig)
+ {
+ TaskState *ts = (TaskState *)thread_env->opaque;
+@@ -728,194 +731,20 @@ give_sigsegv:
+ force_sig(TARGET_SIGSEGV);
+ }
+
+-long
+-do_sigreturn(CPUArchState *regs, abi_ulong uc_addr)
+-{
+- target_ucontext_t *ucontext;
+- sigset_t blocked;
+- target_sigset_t target_set;
+- int i;
+-
+-#if defined(DEBUG_SIGNAL)
+- fprintf(stderr, "do_sigreturn\n");
+-#endif
+- if (!lock_user_struct(VERIFY_READ, ucontext, uc_addr, 1))
+- goto badframe;
+-
+- for(i = 0; i < TARGET_NSIG_WORDS; i++) {
+- if (__get_user(target_set.__bits[i], &ucontext->uc_sigmask.__bits[i]))
+- goto badframe;
+- }
+-
+- if (set_mcontext(regs, &ucontext->uc_mcontext, 0))
+- goto badframe;
+-
+- target_to_host_sigset_internal(&blocked, &target_set);
+- sigprocmask(SIG_SETMASK, &blocked, NULL);
+-
+-#if defined(TARGET_MIPS)
+- CPUMIPSState *mips_regs = (CPUMIPSState *)regs;
+- mips_regs->active_tc.PC = mips_regs->CP0_EPC;
+- mips_regs->CP0_EPC = 0; /* XXX for nested signals ? */
+-#endif
+- return (-TARGET_QEMU_ESIGRETURN);
+-
+-badframe:
+- force_sig(TARGET_SIGSEGV);
+- return (0);
+-}
+-
+-
+-
+-/* #elif defined(TARGET_SPARC64) */
+-#if 0
+-
+-#define mc_flags mc_global[0]
+-#define mc_sp mc_out[6]
+-#define mc_fprs mc_local[0]
+-#define mc_fsr mc_local[1]
+-#define mc_qsr mc_local[2]
+-#define mc_tnpc mc_in[0]
+-#define mc_tpc mc_in[1]
+-#define mc_tstate mc_in[2]
+-#define mc_y mc_in[4]
+-#define mc_wstate mc_in[5]
+-
+-#define ureg_i0 regwptr[0 ]
+-#define ureg_i1 regwptr[1 ]
+-#define ureg_i2 regwptr[2 ]
+-#define ureg_i3 regwptr[3 ]
+-#define ureg_i4 regwptr[4 ]
+-#define ureg_i5 regwptr[5 ]
+-#define ureg_i6 regwptr[6 ]
+-#define ureg_i7 regwptr[7 ]
+-#define ureg_l0 regwptr[8 ]
+-#define ureg_l1 regwptr[9 ]
+-#define ureg_l2 regwptr[10]
+-#define ureg_l3 regwptr[11]
+-#define ureg_l4 regwptr[12]
+-#define ureg_l5 regwptr[13]
+-#define ureg_l6 regwptr[14]
+-#define ureg_l7 regwptr[15]
+-#define ureg_o0 regwptr[16]
+-#define ureg_o1 regwptr[17]
+-#define ureg_o2 regwptr[18]
+-#define ureg_o3 regwptr[19]
+-#define ureg_o4 regwptr[20]
+-#define ureg_o5 regwptr[21]
+-#define ureg_o6 regwptr[22]
+-#define ureg_o7 regwptr[23]
+-#define ureg_fp ureg_i6
+-#define ureg_sp ureg_o6
+-#define ureg_tnpc ureg_i0
+-#define ureg_tpc ureg_i1
+-
+-#define TARGET_FPRS_FEF (1 << 2)
+-#define TARGET_MC_VERSION 1L
+-
+-/* compare to sparc64/sparc64/machdep.c set_mcontext() */
+-static inline int
+-restore_sigmcontext(CPUSPARCState *regs, target_mcontext_t *mc)
+-{
+- int err = 0;
+-
+- err |= __get_user(regs->gregs[1], &mc->mc_global[1]);
+- err |= __get_user(regs->gregs[2], &mc->mc_global[2]);
+- err |= __get_user(regs->gregs[3], &mc->mc_global[3]);
+- err |= __get_user(regs->gregs[4], &mc->mc_global[4]);
+- err |= __get_user(regs->gregs[5], &mc->mc_global[5]);
+- err |= __get_user(regs->gregs[6], &mc->mc_global[6]);
+-
+- err |= __get_user(regs->ureg_o0, &mc->mc_out[0]);
+- err |= __get_user(regs->ureg_o1, &mc->mc_out[1]);
+- err |= __get_user(regs->ureg_o2, &mc->mc_out[2]);
+- err |= __get_user(regs->ureg_o3, &mc->mc_out[3]);
+- err |= __get_user(regs->ureg_o4, &mc->mc_out[4]);
+- err |= __get_user(regs->ureg_o5, &mc->mc_out[5]);
+- err |= __get_user(regs->ureg_o6, &mc->mc_out[6]);
+- err |= __get_user(regs->ureg_o7, &mc->mc_out[0]);
+-
+- err |= __get_user(regs->ureg_l0, &mc->mc_fprs); /* mc_local[0] */
+- err |= __get_user(regs->ureg_l1, &mc->mc_fsr); /* mc_local[1] */
+- err |= __get_user(regs->ureg_l2, &mc->mc_qsr); /* mc_local[2] */
+-
+- err |= __get_user(regs->ureg_i0, &mc->mc_tnpc); /* mc_in[0] */
+- err |= __get_user(regs->ureg_i1, &mc->mc_tpc); /* mc_in[1] */
+- err |= __get_user(regs->ureg_i2, &mc->mc_tstate);/* mc_in[2] */
+-
+- err |= __get_user(regs->ureg_i4, &mc->mc_y); /* mc_in[4] */
+-
+- /* XXX
+- if ((regs->ureg_l0 & TARGET_FPRS_FEF) != 0) {
+- regs->ureg_l0 = 0;
+- for(i = 0; i < 64; i++)
+- err |= __get_user(regs->fpr[i], &mc->mc_fp[i]);
+- }
+- */
+-
+- return (err);
+-}
++#else
+
+-/* compare to sparc64/sparc64/machdep.c get_mcontext() */
+-static inline int
+-setup_sigmcontext(CPUSPARCState *regs, target_mcontext_t *mc)
++static void
++setup_frame(int sig, int code, struct target_sigaction *ka, target_sigset_t *set,
++ target_siginfo_t *tinfo, CPUArchState *env)
+ {
+- int err = 0;
+- abi_ulong ver = TARGET_MC_VERSION;
+-
+- err |= __put_user(ver, &mc->mc_flags); /* aka. mc_global[0] */
+- err |= __put_user(regs->gregs[1], &mc->mc_global[1]);
+- err |= __put_user(regs->gregs[2], &mc->mc_global[2]);
+- err |= __put_user(regs->gregs[3], &mc->mc_global[3]);
+- err |= __put_user(regs->gregs[4], &mc->mc_global[4]);
+- err |= __put_user(regs->gregs[5], &mc->mc_global[5]);
+- err |= __put_user(regs->gregs[6], &mc->mc_global[6]);
+- /* skip %g7 since it is used as the userland TLS register */
+-
+- err |= __put_user(regs->ureg_o0, &mc->mc_out[0]);
+- err |= __put_user(regs->ureg_o1, &mc->mc_out[1]);
+- err |= __put_user(regs->ureg_o2, &mc->mc_out[2]);
+- err |= __put_user(regs->ureg_o3, &mc->mc_out[3]);
+- err |= __put_user(regs->ureg_o4, &mc->mc_out[4]);
+- err |= __put_user(regs->ureg_o5, &mc->mc_out[5]);
+- err |= __put_user(regs->ureg_o6, &mc->mc_out[6]);
+- err |= __put_user(regs->ureg_o7, &mc->mc_out[7]);
+-
+- err |= __put_user(regs->ureg_l0, &mc->mc_fprs); /* mc_local[0] */
+- err |= __put_user(regs->ureg_l1, &mc->mc_fsr); /* mc_local[1] */
+- err |= __put_user(regs->ureg_l2, &mc->mc_qsr); /* mc_local[2] */
+
+- err |= __put_user(regs->ureg_i0, &mc->mc_tnpc); /* mc_in[0] */
+- err |= __put_user(regs->ureg_i1, &mc->mc_tpc); /* mc_in[1] */
+- err |= __put_user(regs->ureg_i2, &mc->mc_tstate);/* mc_in[2] */
+-
+- err |= __put_user(regs->ureg_i4, &mc->mc_y); /* mc_in[4] */
+-
+- /* XXX
+- if ((regs->ureg_l0 & TARGET_FPRS_FEF) != 0) {
+- for(i = 0; i < 64; i++)
+- err |= __put_user(regs->fpr[i], &mc->mc_fp[i]);
+- }
+- */
+-
+- return (err);
++ fprintf(stderr, "setup_frame: not implemented\n");
+ }
+
+-static inline abi_ulong
+-get_sigframe(struct target_sigaction *ka, CPUSPARCState *regs, size_t frame_size)
+-{
+- abi_ulong sp;
++#endif /* ! TARGET_ARM && TARGET_MIPS */
+
+- /* Use default user stack */
+- sp = regs->ureg_sp;
+-
+- if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
+- sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+- }
+-
+- return (sp - frame_size);
+-}
+
++#if 0
+ /* compare to sparc64/sparc64/machdep.c sendsig() */
+ static void setup_frame(int sig, int code, struct target_sigaction *ka,
+ target_sigset_t *set, target_siginfo_t *tinfo, CPUSPARCState *regs)
+@@ -974,64 +803,60 @@ give_sigsegv:
+ unlock_user_struct(frame, frame_addr, 1);
+ force_sig(TARGET_SIGSEGV);
+ }
++#endif
+
+-
+-long do_sigreturn(CPUSPARCState *regs, abi_ulong uc_addr)
++static int
++reset_signal_mask(target_ucontext_t *ucontext)
+ {
+- target_ucontext_t *ucontext;
++ int i;
+ sigset_t blocked;
+ target_sigset_t target_set;
+- int i;
+
+-#if defined(DEBUG_SIGNAL)
+- fprintf(stderr, "do_sigreturn\n");
+-#endif
+- if (!lock_user_struct(VERIFY_READ, ucontext, uc_addr, 1))
+- goto badframe;
++ for(i = 0; i < TARGET_NSIG_WORDS; i++)
++ if (__get_user(target_set.__bits[i],
++ &ucontext->uc_sigmask.__bits[i])) {
++ return (-TARGET_EFAULT);
++ }
++ target_to_host_sigset_internal(&blocked, &target_set);
++ sigprocmask(SIG_SETMASK, &blocked, NULL);
+
+- for(i = 0; i < TARGET_NSIG_WORDS; i++) {
+- if (__get_user(target_set.__bits[i], &ucontext->uc_sigmask.__bits[i]))
++ return (0);
++}
++
++long
++do_sigreturn(CPUArchState *regs, abi_ulong addr)
++{
++ int ret;
++ target_ucontext_t *ucontext;
++ void *locked_addr = NULL;
++
++ /* Lock the memory and get the ucontext ptr from the stack frame */
++ ret = get_ucontext_sigreturn(regs, addr, &ucontext, &locked_addr);
++ if (ret) {
++ if (-TARGET_EFAULT == ret)
+ goto badframe;
++ else
++ return (ret);
+ }
+
+- if (restore_sigmcontext(regs, &ucontext->uc_mcontext))
++ /* Set the register state back to before the signal. */
++ if (set_mcontext(regs, &ucontext->uc_mcontext, 1))
+ goto badframe;
+
+- target_to_host_sigset_internal(&blocked, &target_set);
+- sigprocmask(SIG_SETMASK, &blocked, NULL);
++ /* And reset the signal mask. */
++ if (reset_signal_mask(ucontext))
++ goto badframe;
+
+- return (-TARGET_QEMU_ESIGRETURN);
++ unlock_user_struct(locked_addr, addr, 0);
++ return (-TARGET_EJUSTRETURN);
+
+ badframe:
++ if (locked_addr != NULL)
++ unlock_user_struct(locked_addr, addr, 0);
+ force_sig(TARGET_SIGSEGV);
+- return (0);
+-}
+-#endif
+-
+-#else
+-
+-static void
+-setup_frame(int sig, int code, struct target_sigaction *ka, target_sigset_t *set,
+- target_siginfo_t *tinfo, CPUArchState *env)
+-{
+- fprintf(stderr, "setup_frame: not implemented\n");
+-}
+-
+-long
+-do_sigreturn(CPUArchState *env, abi_ulong uc_addr)
+-{
+- fprintf(stderr,"do_sigreturn: not implemented\n");
+- return (-TARGET_ENOSYS);
++ return (-TARGET_EFAULT);
+ }
+
+-long
+-do_rt_sigreturn(CPUArchState *env)
+-{
+- fprintf(stderr, "do_rt_sigreturn: not implemented\n");
+- return (-TARGET_ENOSYS);
+-}
+-#endif
+-
+ void
+ signal_init(void)
+ {
+diff --git a/bsd-user/sparc/target_signal.h b/bsd-user/sparc/target_signal.h
+index e2fe79c..65d315a 100644
+--- a/bsd-user/sparc/target_signal.h
++++ b/bsd-user/sparc/target_signal.h
+@@ -43,4 +43,12 @@ set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
+ return (-TARGET_ENOSYS);
+ }
+
++static inline abi_long
++get_ucontext_sigreturn(CPUArchState *regs, abi_ulong sf_addr,
++ target_ucontext_t **ucontext, void **locked_addr)
++{
++ fprintf(stderr, "SPARC doesn't have support for do_sigreturn()\n");
++ return (-TARGET_ENOSYS);
++}
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/sparc64/target_signal.h b/bsd-user/sparc64/target_signal.h
+index 1bc7c96..fa8edb8 100644
+--- a/bsd-user/sparc64/target_signal.h
++++ b/bsd-user/sparc64/target_signal.h
+@@ -245,4 +245,12 @@ set_mcontext(CPUSPARCState *regs, target_mcontext_t *mcp, int flags)
+ return (0);
+ }
+
++static inline abi_long
++get_ucontext_sigreturn(CPUArchState *regs, abi_ulong sf_addr,
++ target_ucontext_t **ucontext, void **locked_addr)
++{
++ fprintf(stderr, "SPARC64 doesn't have support for do_sigreturn()\n");
++ return (-TARGET_ENOSYS);
++}
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
+index 636083a..2d97a23 100644
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -90,12 +90,12 @@
+
+ #include "qemu.h"
+ #include "qemu-common.h"
++#include "target_signal.h"
+ #ifdef __FreeBSD__
+ #include "freebsd/ttycom.h"
+ #include "freebsd/filio.h"
+ #endif
+
+-
+ //#define DEBUG
+
+ static abi_ulong target_brk;
+@@ -346,32 +346,47 @@ static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
+ #endif
+
+ #ifdef TARGET_ARM
+-static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
++static abi_long do_freebsd_sysarch(CPUARMState *env, int op, abi_ulong parms)
+ {
++ int ret = 0;
+
+ switch (op) {
++ case TARGET_FREEBSD_ARM_SYNC_ICACHE:
++ case TARGET_FREEBSD_ARM_DRAIN_WRITEBUF:
++ break;
++
+ case TARGET_FREEBSD_ARM_SET_TP:
+ cpu_set_tls(env, parms);
+- return 0;
++ break;
++
++ case TARGET_FREEBSD_ARM_GET_TP:
++ /* XXX Need a cpu_get_tls() */
++ if (put_user(env->cp15.c13_tls2, parms, abi_ulong))
++ ret = -TARGET_EFAULT;
++ break;
++
++ default:
++ ret = -TARGET_EINVAL;
++ break;
+ }
+
+- return -TARGET_EINVAL;
++ return (ret);
+ }
+ #endif
+
+ #ifdef TARGET_MIPS
+-static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
++static abi_long do_freebsd_sysarch(CPUMIPSState *env, int op, abi_ulong parms)
+ {
+ int ret = 0;
+- CPUMIPSState *mips_env = (CPUMIPSState *)env;
+
+ switch(op) {
+ case TARGET_MIPS_SET_TLS:
+- mips_env->tls_value = parms;
++ cpu_set_tls(env, parms);
+ break;
+
+ case TARGET_MIPS_GET_TLS:
+- if (put_user(mips_env->tls_value, parms, abi_ulong))
++ /* XXX Need a cpu_get_tls() */
++ if (put_user(env->tls_value, parms, abi_ulong))
+ ret = -TARGET_EFAULT;
+ break;
+ default:
+@@ -671,7 +686,7 @@ target_to_host_sockaddr(struct sockaddr *addr, abi_ulong target_addr,
+ if (!target_saddr)
+ return -TARGET_EFAULT;
+
+- sa_family = tswap16(target_saddr->sa_family);
++ sa_family = target_saddr->sa_family;
+
+ /*
+ * Oops. The caller might send a incomplete sun_path; sun_path
+@@ -680,7 +695,7 @@ target_to_host_sockaddr(struct sockaddr *addr, abi_ulong target_addr,
+ * "strlen(x->sun_path)" while it should be "strlen(...) + 1". We will
+ * fix that here if needed.
+ */
+- if (sa_family == AF_UNIX) {
++ if (target_saddr->sa_family == AF_UNIX) {
+ if (len < unix_maxlen && len > 0) {
+ char *cp = (char*)target_saddr;
+
+@@ -692,7 +707,8 @@ target_to_host_sockaddr(struct sockaddr *addr, abi_ulong target_addr,
+ }
+
+ memcpy(addr, target_saddr, len);
+- addr->sa_family = sa_family;
++ addr->sa_family = sa_family; /* type uint8_t */
++ addr->sa_len = target_saddr->sa_len; /* type uint8_t */
+ unlock_user(target_saddr, target_addr, 0);
+
+ return (0);
+@@ -708,7 +724,8 @@ host_to_target_sockaddr(abi_ulong target_addr, struct sockaddr *addr,
+ if (!target_saddr)
+ return (-TARGET_EFAULT);
+ memcpy(target_saddr, addr, len);
+- target_saddr->sa_family = tswap16(addr->sa_family);
++ target_saddr->sa_family = addr->sa_family; /* type uint8_t */
++ target_saddr->sa_len = addr->sa_len; /* type uint8_t */
+ unlock_user(target_saddr, target_addr, len);
+
+ return (0);
+@@ -1427,7 +1444,7 @@ static abi_long
+ do_sendto(int fd, abi_ulong msg, size_t len, int flags, abi_ulong target_addr,
+ socklen_t addrlen)
+ {
+- void *addr;
++ struct sockaddr *saddr;
+ void *host_msg;
+ abi_long ret;
+
+@@ -1437,13 +1454,13 @@ do_sendto(int fd, abi_ulong msg, size_t len, int flags, abi_ulong target_addr,
+ if (!host_msg)
+ return (-TARGET_EFAULT);
+ if (target_addr) {
+- addr = alloca(addrlen);
+- ret = target_to_host_sockaddr(addr, target_addr, addrlen);
++ saddr = alloca(addrlen);
++ ret = target_to_host_sockaddr(saddr, target_addr, addrlen);
+ if (ret) {
+ unlock_user(host_msg, msg, 0);
+ return (ret);
+ }
+- ret = get_errno(sendto(fd, host_msg, len, flags, addr,
++ ret = get_errno(sendto(fd, host_msg, len, flags, saddr,
+ addrlen));
+ } else {
+ ret = get_errno(send(fd, host_msg, len, flags));
+@@ -1458,7 +1475,7 @@ do_recvfrom(int fd, abi_ulong msg, size_t len, int flags, abi_ulong target_addr,
+ abi_ulong target_addrlen)
+ {
+ socklen_t addrlen;
+- void *addr;
++ struct sockaddr *saddr;
+ void *host_msg;
+ abi_long ret;
+
+@@ -1474,16 +1491,16 @@ do_recvfrom(int fd, abi_ulong msg, size_t len, int flags, abi_ulong target_addr,
+ ret = (-TARGET_EINVAL);
+ goto fail;
+ }
+- addr = alloca(addrlen);
+- ret = get_errno(recvfrom(fd, host_msg, len, flags, addr,
++ saddr = alloca(addrlen);
++ ret = get_errno(recvfrom(fd, host_msg, len, flags, saddr,
+ &addrlen));
+ } else {
+- addr = NULL; /* To keep compiler quiet. */
++ saddr = NULL; /* To keep compiler quiet. */
+ ret = get_errno(qemu_recv(fd, host_msg, len, flags));
+ }
+ if (!is_error(ret)) {
+ if (target_addr) {
+- host_to_target_sockaddr(target_addr, addr, addrlen);
++ host_to_target_sockaddr(target_addr, saddr, addrlen);
+ if (put_user_u32(addrlen, target_addrlen)) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+@@ -5670,8 +5687,8 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ return (-TARGET_EFAULT);
+ fl.l_type = tswap16(target_fl->l_type);
+ fl.l_whence = tswap16(target_fl->l_whence);
+- fl.l_start = tswapal(target_fl->l_start);
+- fl.l_len = tswapal(target_fl->l_len);
++ fl.l_start = tswap64(target_fl->l_start);
++ fl.l_len = tswap64(target_fl->l_len);
+ fl.l_pid = tswap32(target_fl->l_pid);
+ fl.l_sysid = tswap32(target_fl->l_sysid);
+ unlock_user_struct(target_fl, arg3, 0);
+@@ -5682,8 +5699,8 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ return (-TARGET_EFAULT);
+ target_fl->l_type = tswap16(fl.l_type);
+ target_fl->l_whence = tswap16(fl.l_whence);
+- target_fl->l_start = tswapal(fl.l_start);
+- target_fl->l_len = tswapal(fl.l_len);
++ target_fl->l_start = tswap64(fl.l_start);
++ target_fl->l_len = tswap64(fl.l_len);
+ target_fl->l_pid = tswap32(fl.l_pid);
+ target_fl->l_sysid = tswap32(fl.l_sysid);
+ unlock_user_struct(target_fl, arg3, 1);
+@@ -5694,8 +5711,8 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ case TARGET_F_SETLKW:
+ if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
+ return (-TARGET_EFAULT);
+- fl.l_start = tswapal(target_fl->l_start);
+- fl.l_len = tswapal(target_fl->l_len);
++ fl.l_start = tswap64(target_fl->l_start);
++ fl.l_len = tswap64(target_fl->l_len);
+ fl.l_pid = tswap32(target_fl->l_pid);
+ fl.l_type = tswap16(target_fl->l_type);
+ fl.l_whence = tswap16(target_fl->l_whence);
+diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h
+index 8a92403..eb804b3 100644
+--- a/bsd-user/syscall_defs.h
++++ b/bsd-user/syscall_defs.h
+@@ -132,8 +132,8 @@
+ #define TARGET_TRAP_TRACE (2) /* process trace trap */
+
+ struct target_rlimit {
+- abi_ulong rlim_cur;
+- abi_ulong rlim_max;
++ uint64_t rlim_cur;
++ uint64_t rlim_max;
+ };
+
+ #if defined(TARGET_ALPHA)
+@@ -203,8 +203,8 @@ struct target_pollfd {
+ #include "openbsd/syscall_nr.h"
+
+ struct target_flock {
+- abi_long l_start;
+- abi_long l_len;
++ int64_t l_start;
++ int64_t l_len;
+ int32_t l_pid;
+ int16_t l_type;
+ int16_t l_whence;
+@@ -260,19 +260,29 @@ __target_cmsg_nxthdr (struct target_msghdr *__mhdr,
+ }
+
+ struct target_sockaddr {
+- uint16_t sa_family;
++ uint8_t sa_len;
++ uint8_t sa_family;
+ uint8_t sa_data[14];
+-};
++} QEMU_PACKED;
+
+ struct target_in_addr {
+ uint32_t s_addr; /* big endian */
+ };
+
++/*
++ * FreeBSD/{arm, mips} uses a 64bits time_t, even in 32bits mode,
++ * so we have to add a special case here.
++ */
++#if defined(TARGET_ARM) || defined(TARGET_MIPS)
++typedef int64_t target_freebsd_time_t;
++#else
++typedef abi_long target_freebsd_time_t;
++#endif
+
+ struct target_timeval {
+- abi_long tv_sec;
++ target_freebsd_time_t tv_sec;
+ abi_long tv_usec;
+-};
++} QEMU_PACKED;
+
+ typedef abi_long target_clock_t;
+
+@@ -304,21 +314,13 @@ struct target_kevent {
+ abi_ulong udata;
+ } __packed;
+
+-/*
+- * FreeBSD/arm uses a 64bits time_t, even in 32bits mode, so we have to
+- * add a special case here.
+- */
+-#if defined(TARGET_ARM)
+-typedef uint64_t target_freebsd_time_t;
+-#else
+-typedef long target_freebsd_time_t;
+-#endif
+
+ struct target_freebsd_timespec {
+ target_freebsd_time_t tv_sec; /* seconds */
+ abi_long tv_nsec; /* and nanoseconds */
+ } __packed;
+
++/* XXX We have target_*_timeval defined twice. */
+ struct target_freebsd_timeval {
+ target_freebsd_time_t tv_sec;
+ abi_long tv_usec;
+@@ -672,7 +674,7 @@ struct target_statfs {
+ uint64_t f_asyncreads; /* count of async reads since mount */
+ uint64_t f_spare[10]; /* unused spare */
+ uint32_t f_namemax; /* maximum filename length */
+- uid_t f_owner; /* user that mounted the filesystem */
++ uint32_t f_owner; /* user that mounted the filesystem */
+ target_fsid_t f_fsid; /* filesystem id */
+ char f_charspare[80]; /* spare string space */
+ char f_fstypename[TARGET_MFSNAMELEN]; /* filesys type name */
+diff --git a/bsd-user/x86_64/target_signal.h b/bsd-user/x86_64/target_signal.h
+index a14e0b9..72df2f0 100644
+--- a/bsd-user/x86_64/target_signal.h
++++ b/bsd-user/x86_64/target_signal.h
+@@ -3,7 +3,8 @@
+
+ #include "cpu.h"
+
+-static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
++static inline abi_ulong
++get_sp_from_cpustate(CPUX86State *state)
+ {
+ return state->regs[R_ESP];
+ }
+@@ -26,18 +27,26 @@ typedef struct target_ucontext {
+ int32_t __spare__[4];
+ } target_ucontext_t;
+
+-static inline int
++static inline abi_long
+ get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
+ {
+ fprintf(stderr, "x86_64 doesn't have support for get_mcontext()\n");
+ return (-TARGET_ENOSYS);
+ }
+
+-static inline int
++static inline abi_long
+ set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
+ {
+ fprintf(stderr, "x86_64 doesn't have support for set_mcontext()\n");
+ return (-TARGET_ENOSYS);
+ }
+
++static inline abi_long
++get_ucontext_sigreturn(CPUArchState *regs, abi_ulong sf_addr,
++ target_ucontext_t **ucontext, void **locked_addr)
++{
++ fprintf(stderr, "x86_64 doesn't have support for do_sigreturn()\n");
++ return (-TARGET_ENOSYS);
++}
++
+ #endif /* TARGET_SIGNAL_H */
diff --git a/emulators/qemu-devel/files/pcap-patch b/emulators/qemu-devel/files/pcap-patch
index ed698e12dbc4..279bdce00147 100644
--- a/emulators/qemu-devel/files/pcap-patch
+++ b/emulators/qemu-devel/files/pcap-patch
@@ -1,31 +1,33 @@
---- configure.orig 2010-01-29 14:36:00.000000000 -0500
-+++ configure 2010-01-29 14:36:00.000000000 -0500
-@@ -194,6 +194,9 @@ zlib="yes"
- guest_agent="yes"
- libiscsi=""
- coroutine=""
+--- configure.orig
++++ configure
+@@ -226,6 +226,9 @@ coroutine=""
+ seccomp=""
+ glusterfs=""
+ virtio_blk_data_plane=""
+pcap="no"
+pcap_create="no"
+bpf="no"
# parse CC options first
for opt do
-@@ -670,6 +673,8 @@ for opt do
+@@ -729,6 +732,10 @@ for opt do
;;
- --enable-vnc-thread) vnc_thread="yes"
+ --enable-vnc-ws) vnc_ws="yes"
;;
+ --enable-pcap) pcap="yes"
+ ;;
++ --disable-pcap) pcap="no"
++ ;;
--disable-slirp) slirp="no"
;;
--disable-uuid) uuid="no"
-@@ -1619,6 +1624,49 @@ EOF
+@@ -1730,6 +1737,51 @@ EOF
fi
##########################################
+# pcap probe
+
-+if test "$pcap" = "yes" ; then
++if test "$pcap" = "yes" -a "$pcap" != "no"; then
+ cat > $TMPC << EOF
+#include <pcap.h>
+int main(void) { return (pcap_lib_version() == (char *)0 ? 1 : 0); }
@@ -35,7 +37,9 @@
+ else
+ libpcap=-lwpcap
+ fi
-+ if ! $cc $ARCH_CFLAGS -o $TMPE $libpcap $TMPC 2> /dev/null ; then
++ if compile_prog "$libpcap" ; then
++ :
++ else
+ echo
+ echo "Error: Could not find pcap"
+ echo "Make sure to have the pcap libs and headers installed."
@@ -50,7 +54,7 @@
+ return (pcap_create("foo", errbuf) == (pcap_t *)0 ? 1 : 0);
+}
+EOF
-+ if $cc $ARCH_CFLAGS -o $TMPE $libpcap $TMPC 2> /dev/null ; then
++ if compile_prog "$libpcap" ; then
+ pcap_create="yes"
+ fi
+ cat > $TMPC << EOF
@@ -59,17 +63,25 @@
+#include <net/bpf.h>
+int main(void) { return (BPF_MAJOR_VERSION); }
+EOF
-+ if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then
++ if compile_prog ; then
+ bpf="yes"
+ fi
+ libs_softmmu="$libpcap $libs_softmmu"
+fi # test "$pcap"
+
+##########################################
- # VNC TLS detection
- if test "$vnc" = "yes" -a "$vnc_tls" != "no" ; then
+ # VNC TLS/WS detection
+ if test "$vnc" = "yes" -a \( "$vnc_tls" != "no" -o "$vnc_ws" != "no" \) ; then
cat > $TMPC <<EOF
-@@ -3117,6 +3165,15 @@ fi
+@@ -3307,6 +3359,7 @@ echo "Extra audio cards $audio_card_list
+ echo "Block whitelist $block_drv_whitelist"
+ echo "Mixer emulation $mixemu"
+ echo "VirtFS support $virtfs"
++echo "pcap support $pcap"
+ echo "VNC support $vnc"
+ if test "$vnc" = "yes" ; then
+ echo "VNC TLS support $vnc_tls"
+@@ -3445,6 +3498,15 @@ fi
if test "$profiler" = "yes" ; then
echo "CONFIG_PROFILER=y" >> $config_host_mak
fi
@@ -85,20 +97,33 @@
if test "$slirp" = "yes" ; then
echo "CONFIG_SLIRP=y" >> $config_host_mak
echo "CONFIG_SMBD_COMMAND=\"$smbd\"" >> $config_host_mak
-Index: net.c
-@@ -37,6 +37,11 @@
- #include "hw/qdev.h"
- #include "iov.h"
+Index: net/clients.h
+@@ -47,6 +47,11 @@ int net_init_tap(const NetClientOptions
+ int net_init_bridge(const NetClientOptions *opts, const char *name,
+ NetClientState *peer);
+
++#ifdef CONFIG_PCAP
++int net_init_pcap(const NetClientOptions *opts, const char *name,
++ NetClientState *peer);
++#endif
++
+ #ifdef CONFIG_VDE
+ int net_init_vde(const NetClientOptions *opts, const char *name,
+ NetClientState *peer);
+Index: net/net.c
+@@ -40,6 +40,11 @@
+ #include "qapi/opts-visitor.h"
+ #include "qapi/dealloc-visitor.h"
+#include <sys/ioctl.h>
+#ifdef __FreeBSD__
+#include <net/if.h>
+#endif
+
- static QTAILQ_HEAD(, VLANState) vlans;
- static QTAILQ_HEAD(, VLANClientState) non_vlan_clients;
-
-@@ -797,6 +802,226 @@ static int net_init_nic(QemuOpts *opts,
+ /* Net bridge is currently not supported for W32. */
+ #if !defined(_WIN32)
+ # define CONFIG_NET_BRIDGE
+@@ -704,6 +709,221 @@ static int net_init_nic(const NetClientO
return idx;
}
@@ -109,26 +134,27 @@ Index: net.c
+#endif
+#include <pcap.h>
+
-+typedef struct PCAPState {
-+ VLANClientState nc;
-+ pcap_t *handle;
-+ int max_eth_frame_size;
-+} PCAPState;
++struct PCAPState {
++ NetClientState nc;
++ pcap_t *handle;
++ int max_eth_frame_size;
++};
+
-+static ssize_t pcap_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
++static ssize_t pcap_receive(NetClientState *nc, const uint8_t *buf, size_t size)
+{
-+ PCAPState *s = DO_UPCAST(PCAPState, nc, nc);
++ struct PCAPState *s = DO_UPCAST(struct PCAPState, nc, nc);
+
+ return pcap_inject(s->handle, (u_char*)buf, size);
+}
+
-+static void pcap_callback(u_char *user, struct pcap_pkthdr *phdr, u_char *pdata)
++static void pcap_callback(u_char *user, struct pcap_pkthdr *phdr, u_char *pdata
++ )
+{
-+ VLANClientState *nc = (VLANClientState *)user;
++ NetClientState *nc = (NetClientState *)user;
+
+ int len = phdr->len;
+#ifdef __FreeBSD__
-+ PCAPState *s = DO_UPCAST(PCAPState, nc, nc);
++ struct PCAPState *s = DO_UPCAST(struct PCAPState, nc, nc);
+ int max_eth_frame_size = s->max_eth_frame_size;
+
+ if (len > max_eth_frame_size) {
@@ -143,7 +169,7 @@ Index: net.c
+
+static void pcap_send(void *opaque)
+{
-+ PCAPState *s = (PCAPState *)opaque;
++ struct PCAPState *s = (struct PCAPState *)opaque;
+
+ for (;;) {
+ if (pcap_dispatch(s->handle, 0, (pcap_handler)&pcap_callback, (u_char *)&s->nc) >= 0)
@@ -151,37 +177,48 @@ Index: net.c
+ }
+}
+
-+static void pcap_cleanup(VLANClientState *nc)
++static void pcap_cleanup(NetClientState *nc)
+{
-+ PCAPState *s = DO_UPCAST(PCAPState, nc, nc);
++ struct PCAPState *s = DO_UPCAST(struct PCAPState, nc, nc);
+
++ qemu_purge_queued_packets(nc);
+ pcap_close(s->handle);
+}
+
+static NetClientInfo net_pcap_info = {
-+ .type = NET_CLIENT_TYPE_PCAP,
-+ .size = sizeof(PCAPState),
++ .type = NET_CLIENT_OPTIONS_KIND_PCAP,
++ .size = sizeof(struct PCAPState),
+ .receive = pcap_receive,
++// .receive_raw = pcap_receive_raw,
++// .receive_iov = pcap_receive_iov,
++// .poll = pcap_poll,
+ .cleanup = pcap_cleanup,
+};
++/*
++ * ... -net pcap,ifname="..."
++ */
+
-+static int net_pcap_init(VLANState *vlan, const char *model, const char *name, const char *ifname)
++int net_init_pcap(const NetClientOptions *opts, const char *name, NetClientState *peer)
+{
-+ VLANClientState *nc;
-+ PCAPState *s = NULL;
++ const NetdevPcapOptions *pcap_opts = opts->pcap;
++ NetClientState *nc;
++ struct PCAPState *s;
++ const char *ifname;
+ char errbuf[PCAP_ERRBUF_SIZE];
+#if defined(_WIN32)
+ HANDLE h;
+#endif
+ int i;
+
-+ s = g_malloc0(sizeof(PCAPState));
-+ nc = qemu_new_net_client(&net_pcap_info, vlan, NULL, model, name);
-+
-+ s = DO_UPCAST(PCAPState, nc, nc);
-+ if (!s)
++ if (!pcap_opts->has_ifname)
+ return -1;
+
++ ifname = pcap_opts->ifname;
++
++ /* create the object */
++ nc = qemu_new_net_client(&net_pcap_info, peer, "pcap", ifname);
++ s = DO_UPCAST(struct PCAPState, nc, nc);
++
+ if (ifname == NULL && (ifname = pcap_lookupdev(errbuf)) == NULL) {
+ fprintf(stderr, "qemu: pcap_create: %s\n", errbuf);
+ goto fail;
@@ -206,6 +243,7 @@ Index: net.c
+ close(i);
+ }
+#endif
++
+#if defined(CONFIG_PCAP_CREATE) || defined(_WIN32)
+ /*
+ * Create pcap handle for the device, set promiscuous mode and activate.
@@ -260,7 +298,6 @@ Index: net.c
+ }
+ }
+#endif /* BIOCIMMEDIATE */
-+
+#if defined(BIOCFEEDBACK)
+ /*
+ * Tell the kernel that the sent packet has to be fed back.
@@ -299,72 +336,43 @@ Index: net.c
+ if (s) {
+ if (s->handle)
+ pcap_close(s->handle);
-+ g_free(s);
+ }
+
+ return -1;
+}
+
-+static int net_init_pcap(QemuOpts *opts,
-+ Monitor *mon,
-+ const char *name,
-+ VLANState *vlan)
-+{
-+ const char *ifname;
-+
-+ ifname = qemu_opt_get(opts, "ifname");
-+
-+ if (net_pcap_init(vlan, "pcap", name, ifname) == -1) {
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+#endif /* CONFIG_PCAP */
-+
- #define NET_COMMON_PARAMS_DESC \
- { \
- .name = "type", \
-@@ -973,6 +1198,21 @@ static const struct {
- { /* end of list */ }
- },
- },
-+#ifdef CONFIG_PCAP
-+ [NET_CLIENT_TYPE_PCAP] = {
-+ .type = "pcap",
-+ .init = net_init_pcap,
-+ .desc = {
-+ NET_COMMON_PARAMS_DESC,
-+ {
-+ .name = "ifname",
-+ .type = QEMU_OPT_STRING,
-+ .help = "interface name",
-+ },
-+ { /* end of list */ }
-+ },
-+ },
+#endif
- [NET_CLIENT_TYPE_SOCKET] = {
- .type = "socket",
- .init = net_init_socket,
-@@ -1343,6 +1583,7 @@ void net_check_clients(void)
- case NET_CLIENT_TYPE_TAP:
- case NET_CLIENT_TYPE_SOCKET:
- case NET_CLIENT_TYPE_VDE:
-+ case NET_CLIENT_TYPE_PCAP:
- has_host_dev = 1;
- break;
- default: ;
---- qemu-options.hx.orig 2010-01-14 17:18:00.000000000 -0500
-+++ qemu-options.hx 2010-01-29 14:36:00.000000000 -0500
-@@ -799,6 +799,10 @@ DEF("smb", HAS_ARG, QEMU_OPTION_smb, "")
- DEF("net", HAS_ARG, QEMU_OPTION_net,
- "-net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
- " create a new Network Interface Card and connect it to VLAN 'n'\n"
+
+ static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])(
+ const NetClientOptions *opts,
+@@ -722,6 +944,9 @@ static int (* const net_client_init_fun[
+ #ifdef CONFIG_NET_BRIDGE
+ [NET_CLIENT_OPTIONS_KIND_BRIDGE] = net_init_bridge,
+ #endif
+#ifdef CONFIG_PCAP
-+ "-net pcap[,vlan=n][,name=str][,ifname=name]\n"
-+ " connect the host network interface using PCAP to VLAN 'n'\n"
++ [NET_CLIENT_OPTIONS_KIND_PCAP] = net_init_pcap,
+#endif
- #ifdef CONFIG_SLIRP
- "-net user[,vlan=n][,name=str][,net=addr[/mask]][,host=addr][,restrict=y|n]\n"
- " [,hostname=host][,dhcpstart=addr][,dns=addr][,tftp=dir][,bootfile=f]\n"
+ [NET_CLIENT_OPTIONS_KIND_HUBPORT] = net_init_hubport,
+ };
+
+--- qapi-schema.json.orig
++++ qapi-schema.json
+@@ -2622,6 +2622,10 @@
+ '*br': 'str',
+ '*helper': 'str' } }
+
++{ 'type': 'NetdevPcapOptions',
++ 'data': {
++ '*ifname': 'str' } }
++
+ ##
+ # @NetdevHubPortOptions
+ #
+@@ -2648,6 +2652,7 @@
+ 'nic': 'NetLegacyNicOptions',
+ 'user': 'NetdevUserOptions',
+ 'tap': 'NetdevTapOptions',
++ 'pcap': 'NetdevPcapOptions',
+ 'socket': 'NetdevSocketOptions',
+ 'vde': 'NetdevVdeOptions',
+ 'dump': 'NetdevDumpOptions',
diff --git a/emulators/qemu-devel/pkg-plist b/emulators/qemu-devel/pkg-plist
index 3138251d17ee..65188aa3fe43 100644
--- a/emulators/qemu-devel/pkg-plist
+++ b/emulators/qemu-devel/pkg-plist
@@ -14,6 +14,7 @@ bin/qemu-system-i386
%%NONX86%%bin/qemu-system-mips64
%%NONX86%%bin/qemu-system-mips64el
%%NONX86%%bin/qemu-system-mipsel
+%%NONX86%%bin/qemu-system-or32
%%NONX86%%bin/qemu-system-ppc
%%NONX86%%bin/qemu-system-ppc64
%%NONX86%%bin/qemu-system-ppcemb
@@ -22,11 +23,16 @@ bin/qemu-system-i386
%%NONX86%%bin/qemu-system-sh4eb
%%NONX86%%bin/qemu-system-sparc
%%NONX86%%bin/qemu-system-sparc64
+%%NONX86%%bin/qemu-system-unicore32
%%BSD_USER%%bin/qemu-arm
+%%BSD_USER%%bin/qemu-armeb
%%BSD_USER%%bin/qemu-i386
+%%BSD_USER%%bin/qemu-mips
+%%BSD_USER64%%bin/qemu-mips64
+%%BSD_USER%%bin/qemu-mipsel
%%BSD_USER%%bin/qemu-sparc
-%%BSD_USER%%bin/qemu-sparc64
-%%BSD_USER%%bin/qemu-x86_64
+%%BSD_USER64%%bin/qemu-sparc64
+%%BSD_USER64%%bin/qemu-x86_64
bin/qemu-system-x86_64
%%NONX86%%bin/qemu-system-xtensa
%%NONX86%%bin/qemu-system-xtensaeb
@@ -40,6 +46,8 @@ etc/qemu-ifdown.sample
etc/qemu/target-x86_64.conf.sample
@exec if [ ! -f %D/etc/qemu/target-x86_64.conf ] ; then cp -p %D/%F %D/etc/qemu/target-x86_64.conf; fi
@dirrmtry etc/qemu
+%%DATADIR%%/acpi-dsdt.aml
+%%DATADIR%%/q35-acpi-dsdt.aml
%%DATADIR%%/bios.bin
%%DATADIR%%/vgabios.bin
%%DATADIR%%/vgabios-cirrus.bin
@@ -58,7 +66,6 @@ etc/qemu/target-x86_64.conf.sample
%%DATADIR%%/pxe-pcnet.rom
%%DATADIR%%/pxe-virtio.rom
%%DATADIR%%/petalogix-ml605.dtb
-%%DATADIR%%/mpc8544ds.dtb
%%DATADIR%%/spapr-rtas.bin
%%DATADIR%%/slof.bin
%%DATADIR%%/s390-zipl.rom
@@ -67,10 +74,10 @@ etc/qemu/target-x86_64.conf.sample
%%DATADIR%%/sgabios.bin
%%DATADIR%%/petalogix-s3adsp1800.dtb
%%DATADIR%%/bamboo.dtb
-%%DATADIR%%/cpus-x86_64.conf
%%DATADIR%%/kvmvapic.bin
%%DATADIR%%/qemu-icon.bmp
%%DATADIR%%/keymaps/ar
+%%DATADIR%%/keymaps/bepo
%%DATADIR%%/keymaps/common
%%DATADIR%%/keymaps/da
%%DATADIR%%/keymaps/de